def add_actions(): mainwin.windowMenu.clear() mainwin.windowMenu.addAction(mainwin.closeAllAct) mainwin.windowMenu.addAction(mainwin.cascadeAct) mainwin.windowMenu.addAction(mainwin.separatorAct) windows = mainwin.workspace.subWindowList() mainwin.separatorAct.setVisible(len(windows) != 0) for i, child in enumerate(windows): title = child.windowTitle() if i < 9: text = _('&%s %s' % (i+1, title)) else: text = _('%s %s' % (i+1, title)) action = mainwin.windowMenu.addAction(text) action.setCheckable(True) action.setChecked(child == mainwin.activeMdiChild()) def create_window_activator(window): def activate_window(): mainwin.workspace.setActiveSubWindow(window) return activate_window action.triggered.conect( create_window_activator( child ) )
def select_profile(profiles_dict): title = _('Profile Selection') input_label = _('Select a stored profile:') ok_label = _('OK') cancel_label = _('Quit') input_dialog = ComboBoxInputDialog(autoaccept=True) input_dialog.set_window_title(title) input_dialog.set_label_text(input_label) input_dialog.set_ok_button_text(ok_label) input_dialog.set_cancel_button_text(cancel_label) input_dialog.set_items(sorted(profiles_dict.keys()) + [NEW_PROFILE_LABEL]) _last_used_profile = last_used_profile() if _last_used_profile: input_dialog.set_choice_by_text(_last_used_profile) input_dialog.set_ok_button_default() last_index = input_dialog.count()-1 custom_font = QFont() custom_font.setItalic(True) icon = art.Icon('tango/16x16/actions/document-new.png').getQIcon() input_dialog.set_data(last_index, custom_font, Qt.FontRole) input_dialog.set_data(last_index, icon, Qt.DecorationRole) dialog_code = input_dialog.exec_() if dialog_code == QDialog.Accepted: return unicode(input_dialog.get_text()) return None
def delete_selected_rows(self): logger.debug("delete selected rows called") confirmation_message = self._admin.get_confirm_delete() confirmed = True rows = set(index.row() for index in self.selectedIndexes()) if not rows: return if confirmation_message: if ( QtGui.QMessageBox.question( self, _("Please confirm"), unicode(confirmation_message), QtGui.QMessageBox.Yes, QtGui.QMessageBox.No, ) == QtGui.QMessageBox.No ): confirmed = False if confirmed: # # if there is an open editor on a row that will be deleted, there # might be an assertion failure in QT # progress_dialog = ProgressDialog(_("Removing")) self.model().rows_removed_signal.connect(progress_dialog.finished) self.model().exception_signal.connect(progress_dialog.exception) self.close_editor() self.model().remove_rows(set(rows)) progress_dialog.exec_()
def set_instance_represenation(self, representation_and_propagate): """Update the gui""" ((desc, pk), propagate) = representation_and_propagate self._entity_representation = desc self.search_input.set_user_input(desc) if pk != False: self.open_button.setIcon( Icon('tango/16x16/places/folder.png').getQIcon() ) self.open_button.setToolTip(unicode(_('open'))) self.open_button.setEnabled(True) self.search_button.setIcon( Icon('tango/16x16/actions/edit-clear.png').getQIcon() ) self.search_button.setToolTip(unicode(_('clear'))) self.entity_set = True else: self.open_button.setIcon( self.new_icon.getQIcon() ) self.open_button.setToolTip(unicode(_('new'))) self.open_button.setEnabled(self._editable) self.search_button.setIcon( self.search_icon.getQIcon() ) self.search_button.setToolTip(_('Search')) self.entity_set = False if propagate: self.editingFinished.emit()
def model_run( self, model_context ): yield action_steps.UpdateProgress( 0, 3, _('Formatting disk') ) time.sleep( 0.7 ) yield action_steps.UpdateProgress( 1, 3, _('Burning movie') ) time.sleep( 0.7 ) yield action_steps.UpdateProgress( 2, 3, _('Finishing') ) time.sleep( 0.5 )
def __init__( self, document ): self.document = document self.thread = QtCore.QThread.currentThread() self.document.moveToThread( QtGui.QApplication.instance().thread() ) self.window_title = _('Edit text') self.title = _('Edit text') self.subtitle = _('Press OK when finished')
def get_sections(self): print(model.authentication.get_current_authentication().username) session = Session user = session.query(ResurseUmane).filter( ResurseUmane.username == model.authentication.get_current_authentication().username).first() sectii = [] if user is None or user.functie == 'Student': return [Section(_('Caracteristici publice'), self, Icon('tango/22x22/apps/system-users.png'), items=[Activitate, ResurseUmane, Granturi, ResurseFinanciare, ResursaLogistica, CalendarActivitatiAction(), ProgramStudiu, ImportOrar()])] if user.functie == 'Administrator': return [Section(_('Caracteristici administrative'), self, Icon('tango/22x22/apps/system-users.png'), items=[])] if user.functie == 'Profesor': return [Section(_('Caracteristici pentru directorul de departament'), self, Icon('tango/22x22/apps/system-users.png'), items=[ProgramStudiu])] if user.functie == 'Director': return [Section(_('Caracteristici pentru cadre didactice'), self, Icon('tango/22x22/apps/system-users.png'), items=[Activitate, ResurseUmane, CalendarActivitatiAction()])]
def __init__(self, parent=None, editable=True, field_name='months', **kw): CustomEditor.__init__(self, parent) self.setObjectName( field_name ) self.years_spinbox = CustomDoubleSpinBox() self.months_spinbox = CustomDoubleSpinBox() self.years_spinbox.setMinimum(0) self.years_spinbox.setMaximum(10000) self.months_spinbox.setMinimum(0) self.months_spinbox.setMaximum(12) self.years_spinbox.setSuffix(_(' years')) self.months_spinbox.setSuffix(_(' months')) self.years_spinbox.setDecimals(0) self.years_spinbox.setAlignment(Qt.AlignRight|Qt.AlignVCenter) self.years_spinbox.setSingleStep(1) self.months_spinbox.setDecimals(0) self.months_spinbox.setAlignment(Qt.AlignRight|Qt.AlignVCenter) self.months_spinbox.setSingleStep(1) self.years_spinbox.editingFinished.connect( self._spinbox_editing_finished ) self.months_spinbox.editingFinished.connect( self._spinbox_editing_finished ) layout = QHBoxLayout() layout.addWidget(self.years_spinbox) layout.addWidget(self.months_spinbox) layout.setContentsMargins(0, 0, 0, 0) self.setLayout(layout)
def setupButtons( self, layout, table ): button_layout = QtGui.QVBoxLayout() button_layout.setSpacing( 0 ) self.delete_button = QtGui.QToolButton() self.delete_button.setIcon( self.delete_icon.getQIcon() ) self.delete_button.setAutoRaise( True ) self.delete_button.setToolTip(_('Delete')) self.delete_button.clicked.connect( table.delete_selected_rows ) self.add_button = QtGui.QToolButton() icon = self.new_icon.getQIcon() self.add_button.setIcon( icon ) self.add_button.setAutoRaise( True ) self.add_button.setToolTip(_('New')) self.add_button.clicked.connect(self.newRow) self.copy_button = QtGui.QToolButton() self.copy_button.setIcon( self.copy_icon.getQIcon() ) self.copy_button.setAutoRaise( True ) self.copy_button.setToolTip(_('Copy')) self.copy_button.clicked.connect( table.copy_selected_rows ) export_button = QtGui.QToolButton() export_button.setIcon( self.spreadsheet_icon.getQIcon() ) export_button.setAutoRaise( True ) export_button.setToolTip(_('Export as spreadsheet')) export_button.clicked.connect(self.exportToExcel) button_layout.addStretch() button_layout.addWidget( self.add_button ) button_layout.addWidget( self.copy_button ) button_layout.addWidget( self.delete_button ) button_layout.addWidget( export_button ) layout.addLayout( button_layout )
def __init__(self, profiles, parent=None): super(ProfileWizard, self).__init__(parent) self._connection_valid = False self.network_reply = None self.profiles = profiles self.setWindowTitle(_('Profile Wizard')) self.set_banner_logo_pixmap(art.Icon('tango/22x22/categories/preferences-system.png').getQPixmap()) self.set_banner_title(_('Create New/Edit Profile')) self.set_banner_subtitle(_('Please enter the database settings')) self.banner_widget().setStyleSheet('background-color: white;') self.manager = QtNetwork.QNetworkAccessManager( self ) self.manager.finished.connect( self.update_network_status ) #self.manager.networkAccessibleChanged.connect( self.network_accessible_changed ) self.manager.proxyAuthenticationRequired.connect( self.proxy_authentication_required ) self.create_labels_and_widgets() self.create_buttons() self.set_tab_order() self.set_widgets_values() # note: connections come after labels and widgets are created # and have default values self.connect_widgets() self.connect_buttons() timer = QtCore.QTimer(self) timer.timeout.connect( self.new_network_request ) timer.setInterval( 3000 ) timer.start() self.new_network_request()
def register_exception(logger, text, exception): """Log an exception and return a serialized form of the exception with exception information in a user readable format, to be used when displaying an exception message box. that serialized form can be fed to the model_thread_exception_message_box function. :return: a tuple with exception information """ if isinstance( exception, UserException ): # this exception is not supposed to generate any logging # or inform the developer about something return (exception.title, exception.text, exception.icon, exception.resolution, exception.detail) logger.error( text, exc_info = exception ) title = _('Exception') text = _('An unexpected event occurred') icon = None # chop the size of the text to prevent error dialogs larger than the screen resolution = unicode(exception)[:1000] import traceback, cStringIO sio = cStringIO.StringIO() traceback.print_exc(file=sio) detail = sio.getvalue() sio.close() return (title, text, icon, resolution, detail)
def __init__(self, parent=None, width=50, height=40, dpi=50, field_name='chart', **kwargs): from matplotlib.figure import Figure from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas super(ChartEditor, self).__init__( parent ) AbstractCustomEditor.__init__( self ) self.setObjectName( field_name ) chart_frame = QtGui.QFrame( self ) chart_frame.setFrameShape( self.Box ) chart_frame.setContentsMargins( 1, 1, 1, 1 ) chart_frame_layout = QtGui.QHBoxLayout() chart_frame_layout.setContentsMargins( 0, 0, 0, 0) chart_frame.setLayout( chart_frame_layout ) # find out background color, because using a transparent # figure fails when the window is resized: the background # is not redrawn # need to do str() else matplotlib gets confused by the qstring # bgcolorrgb = str(self.palette().background().color().name()) self.fig = Figure( figsize=(width, height), dpi=dpi, facecolor='#ffffff', ) layout = QtGui.QHBoxLayout() self.canvas = FigureCanvas( self.fig ) chart_frame_layout.addWidget( self.canvas ) layout.addWidget(chart_frame) button_layout = QtGui.QVBoxLayout() button_layout.setSpacing( 0 ) icon = Icon( 'tango/16x16/actions/document-print-preview.png' ).getQIcon() button_layout.addStretch() print_button = QtGui.QToolButton() print_button.setIcon( icon ) print_button.setAutoRaise( True ) print_button.setToolTip( _('Print Preview') ) print_button.clicked.connect( self.print_preview ) button_layout.addWidget( print_button ) icon = Icon( 'tango/16x16/actions/edit-copy.png' ).getQIcon() copy_button = QtGui.QToolButton() copy_button.setIcon( icon ) copy_button.setAutoRaise( True ) copy_button.setToolTip( _('Copy to clipboard') ) copy_button.clicked.connect( self.copy_to_clipboard ) button_layout.addWidget( copy_button ) layout.addLayout( button_layout ) layout.setContentsMargins( 0, 0, 0, 0) self.setLayout(layout) self.canvas.setSizePolicy( QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding ) self.canvas.installEventFilter(self) self.show_fullscreen_signal.connect(self.show_fullscreen) self.canvas.updateGeometry() self._litebox = None
def __init__(self, admin, field_attributes, parent=None, flags=QtCore.Qt.Dialog): super(ChangeFieldDialog, self).__init__("", parent, flags) from camelot.view.controls.editors import ChoicesEditor self.field_attributes = field_attributes self.field = None self.value = None self.setWindowTitle(admin.get_verbose_name_plural()) self.set_banner_title(_("Replace field contents")) self.set_banner_subtitle(_("Select the field to update and enter its new value")) self.banner_widget().setStyleSheet("background-color: white;") editor = ChoicesEditor(parent=self) editor.setObjectName("field_choice") layout = QtGui.QVBoxLayout() layout.addWidget(editor) self.main_widget().setLayout(layout) def filter(attributes): if not attributes["editable"]: return False if attributes["delegate"] in (delegates.One2ManyDelegate,): return False return True choices = [ (field, unicode(attributes["name"])) for field, attributes in field_attributes.items() if filter(attributes) ] choices.sort(key=lambda choice: choice[1]) editor.set_choices(choices + [(None, "")]) editor.set_value(None) self.field_changed(0) editor.currentIndexChanged.connect(self.field_changed) self.set_default_buttons()
def __init__(self, parent=None): super(ProfileSelection, self).__init__(parent) self._connection_valid = False self.profiles = fetch_profiles() logger.debug("original profiles fetched:\n%s" % self.profiles) self.profiles_choices = set() for profile in self.profiles: if "profilename" in profile and profile["profilename"]: self.profiles_choices.add((profile["profilename"], profile["profilename"])) logger.debug("original profiles choices:\n%s" % self.profiles_choices) self.setWindowTitle(_("Profile Selection")) self.set_banner_logo_pixmap(art.Icon("tango/22x22/categories/preferences-system.png").getQPixmap()) self.set_banner_title(_("Database Settings")) self.set_banner_subtitle(_("Connect with an existing profile")) self.banner_widget().setStyleSheet("background-color: white;") self.create_labels_and_widgets() self.set_widgets_values() self.connect_widgets() self.create_buttons() self.connect_buttons()
def model_run( self, model_context ): from PyQt4 import QtGui from camelot.view import action_steps yield action_steps.UpdateProgress( text = _('Closing form') ) validator = model_context.admin.get_validator() obj = model_context.get_object() admin = model_context.admin if obj == None: yield action_steps.CloseView() # # validate the object, and if the object is valid, simply close # the view # messages = validator.objectValidity( obj ) valid = ( len( messages ) == 0 ) if valid: yield action_steps.CloseView() else: # # if the object is not valid, request the user what to do # message = action_steps.MessageBox( '\n'.join( messages ), QtGui.QMessageBox.Warning, _('Invalid form'), QtGui.QMessageBox.Ok | QtGui.QMessageBox.Discard ) reply = yield message if reply == QtGui.QMessageBox.Discard: yield action_steps.CloseView() if admin.is_persistent( obj ): admin.refresh( obj ) yield action_steps.UpdateObject( obj ) else: yield action_steps.DeleteObject( obj ) admin.expunge( obj )
def delete_selected_rows(self): assert object_thread( self ) logger.debug( 'delete selected rows called' ) confirmed = True rows = set( index.row() for index in self.selectedIndexes() ) if not rows: return if self._admin.get_delete_mode()=='on_confirm': if QtGui.QMessageBox.question(self, _('Please confirm'), unicode(self._admin.get_delete_message(None)), QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) == QtGui.QMessageBox.No: confirmed = False if confirmed: # # if there is an open editor on a row that will be deleted, there # might be an assertion failure in QT, or the data of the editor # might be pushed to the row that replaces the deleted one # progress_dialog = ProgressDialog(_('Removing')) self.model().rows_removed_signal.connect( progress_dialog.finished ) self.model().exception_signal.connect( progress_dialog.exception ) self.close_editor() self.model().remove_rows( set( rows ) ) progress_dialog.exec_()
def __init__(self, objects, admin): self.objects = objects self.admin = admin self.window_title = admin.get_verbose_name_plural() self.title = _("Data Preview") self.subtitle = _("Please review the data below.") self.icon = Icon("tango/32x32/mimetypes/x-office-spreadsheet.png")
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()
def model_run( self, model_context ): import os.path import chardet from camelot.view import action_steps from camelot.view.import_utils import ( UnicodeReader, RowData, RowDataAdminDecorator, XlsReader ) file_names = yield action_steps.SelectFile() if not len( file_names ): return file_name = file_names[0] yield action_steps.UpdateProgress( text = _('Reading data') ) # # read the data into temporary row_data objects # if os.path.splitext( file_name )[-1] == '.xls': items = XlsReader( file_name ) else: detected = chardet.detect( open( file_name ).read() )['encoding'] enc = detected or 'utf-8' items = UnicodeReader( open( file_name ), encoding = enc ) collection = [ RowData(i, row_data) for i, row_data in enumerate( items ) ] # # validate the temporary data # admin = model_context.admin row_data_admin = RowDataAdminDecorator( admin ) yield action_steps.ChangeObjects( collection, row_data_admin ) # # Ask confirmation # yield action_steps.MessageBox( icon = QtGui.QMessageBox.Warning, title = _('Proceed with import'), text = _('Importing data cannot be undone,\n' 'are you sure you want to continue') ) # # import the temporary objects into real objects # for i,row in enumerate( collection ): new_entity_instance = admin.entity() for field_name, attributes in row_data_admin.get_columns(): try: from_string = attributes['from_string'] except KeyError: LOGGER.warn( 'field %s has no from_string field attribute, dont know how to import it properly'%attributes['original_field'] ) from_string = lambda _a:None setattr( new_entity_instance, attributes['original_field'], from_string(getattr(row, field_name)) ) admin.add( new_entity_instance ) # in case the model is a collection proxy, the new objects should # be appended model_context._model.append( new_entity_instance ) yield action_steps.UpdateProgress( i, len( collection ), _('Importing data') ) yield action_steps.FlushSession( model_context.session ) yield action_steps.Refresh()
def add_new_profile_name(self): logger.info("adding a new profile name") name, ok = QInputDialog.getText(self, _("New Profile Name"), _("Enter a value:")) if ok and name: name = str(name) self.profiles_choices.add((name, name)) self.profile_editor.set_choices(self.profiles_choices) self.profile_editor.set_value(name)
def set_special_date(self, action): if action.text().compare(_('Today')) == 0: self.set_value(datetime.date.today()) elif action.text().compare(_('Far future')) == 0: self.set_value(datetime.date( year = 2400, month = 12, day = 31 )) elif action.text().compare(_('Clear')) == 0: self.set_value(None) self.editingFinished.emit()
def save_profiles_to_file(self): caption = _('Save Profiles To a File') filters = _('Profiles file (*.ini)') path = QFileDialog.getSaveFileName(self, caption, 'profiles', filters) if not path: logger.debug('Could not save profiles to file; no path.') return store_profiles(self.profiles, to_file=path)
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)
def __init__(self, parent = None, editable = True, nullable = True, field_name = 'date', **kwargs): CustomEditor.__init__(self, parent) self.setObjectName( field_name ) self.date_format = local_date_format() self.line_edit = DecoratedLineEdit() self.line_edit.set_minimum_width( len( self.date_format ) ) self.line_edit.set_background_text( QtCore.QDate(2000,1,1).toString(self.date_format) ) # The order of creation of this widgets and their parenting # seems very sensitive under windows and creates system crashes # so don't change this without extensive testing on windows special_date_menu = QtGui.QMenu(self) calendar_widget_action = QtGui.QWidgetAction(special_date_menu) self.calendar_widget = QtGui.QCalendarWidget(special_date_menu) self.calendar_widget.activated.connect(self.calendar_widget_activated) self.calendar_widget.clicked.connect(self.calendar_widget_activated) calendar_widget_action.setDefaultWidget(self.calendar_widget) self.calendar_action_trigger.connect( special_date_menu.hide ) special_date_menu.addAction(calendar_widget_action) special_date_menu.addAction(_('Today')) special_date_menu.addAction(_('Far future')) self.special_date = QtGui.QToolButton(self) self.special_date.setIcon( self.special_date_icon.getQIcon() ) self.special_date.setAutoRaise(True) self.special_date.setToolTip(_('Calendar and special dates')) self.special_date.setMenu(special_date_menu) self.special_date.setPopupMode(QtGui.QToolButton.InstantPopup) self.special_date.setFixedHeight(self.get_height()) self.special_date.setFocusPolicy(Qt.ClickFocus) # end of sensitive part if nullable: special_date_menu.addAction(_('Clear')) self.hlayout = QtGui.QHBoxLayout() self.hlayout.addWidget(self.line_edit) self.hlayout.addWidget(self.special_date) self.hlayout.setContentsMargins(0, 0, 0, 0) self.hlayout.setSpacing(0) self.hlayout.setAlignment(Qt.AlignRight|Qt.AlignVCenter) self.setContentsMargins(0, 0, 0, 0) self.setLayout(self.hlayout) self.minimum = datetime.date.min self.maximum = datetime.date.max self.setFocusProxy(self.line_edit) self.line_edit.editingFinished.connect( self.line_edit_finished ) self.line_edit.textEdited.connect(self.text_edited) special_date_menu.triggered.connect(self.set_special_date)
def update_values(cls, parent, slot, **kwargs): default = dict( parent = parent, text = _('Replace field contents'), slot = slot, tip = _('Replace the content of a field for all rows in a selection') ) default.update(kwargs) return cls.create_action(**default)
def __init__(self, name, icon=progress_icon): QtGui.QProgressDialog.__init__( self, QtCore.QString(), _('Cancel'), 0, 0 ) label = QtGui.QLabel( unicode(name) ) #label.setPixmap(icon.getQPixmap()) self.setLabel( label ) self.setWindowTitle( _('Please wait') ) # show immediately, to prevent a pop up before another window # opened in an action_step self.show()
def update_network_status(self, reply): if reply.isFinished(): error = reply.error() if error == QtNetwork.QNetworkReply.NoError: self.network_status_label.setText(_('Internet available.')) self.network_status_label.setStyleSheet('color: green') return self.network_status_label.setText(_('Internet not available.\n%s.'%reply.errorString())) self.network_status_label.setStyleSheet('color: red')
def merge_document(cls, parent, slot, **kwargs): default = dict( parent = parent, text = _('Merge document'), slot = slot, tip = _('Merge a template document with all rows in a selection') ) default.update(kwargs) return cls.create_action(**default)
def export_mail(cls, parent, slot, **kwargs): default = dict( parent=parent, text=_('Send by e-mail'), slot=slot, actionicon=cls.icon_mail, tip=_('Send by e-mail') ) default.update(kwargs) return cls.create_action(**default)
def import_file(cls, parent, slot, **kwargs): default = dict( parent=parent, text=_('Import from file'), slot=slot, actionicon=cls.icon_import, tip=_('Import from file') ) default.update(kwargs) return cls.create_action(**default)
def run(self, collection_getter, selection_getter): from PyQt4 import QtGui from camelot.view.model_thread import post from camelot.core.utils import ugettext as _ filename = unicode( QtGui.QFileDialog.getSaveFileName( None, _("Save File"), )) def create_po_exporter(filename, collection_getter): def po_exporter(): file = open(filename, 'w') for translation in collection_getter(): file.write((u'msgid "%s"\n' % translation.source).encode('utf-8')) file.write((u'msgstr "%s"\n\n' % translation.value).encode('utf-8')) return po_exporter post(create_po_exporter(filename, collection_getter))
def paint(self, painter, option, index): painter.save() self.drawBackground(painter, option, index) field_attributes = variant_to_pyobject(index.data(Qt.UserRole)) editable, background_color = True, None if field_attributes != ValueLoading: editable = field_attributes.get('editable', True) background_color = field_attributes.get('background_color', None) rect = option.rect value = index.model().data(index, Qt.EditRole).toBool() font_color = QtGui.QColor() if value: text = self.yes if self.color_yes: color = self.color_yes else: text = self.no if self.color_no: color = self.color_no font_color.setRgb(color.red(), color.green(), color.blue()) if (option.state & QtGui.QStyle.State_Selected): painter.fillRect(option.rect, option.palette.highlight()) else: if editable: painter.fillRect(option.rect, background_color or option.palette.base()) else: painter.fillRect(option.rect, background_color or option.palette.window()) painter.setPen(font_color.toRgb()) painter.drawText(rect.x() + 2, rect.y(), rect.width() - 4, rect.height(), Qt.AlignVCenter | Qt.AlignLeft, _(text)) painter.restore()
def set_toolbar_actions(self, toolbar_area, toolbar_actions): """Set the toolbar for a specific area :param toolbar_area: the area on which to put the toolbar, from :class:`Qt.LeftToolBarArea` through :class:`Qt.BottomToolBarArea` :param toolbar_actions: a list of :class:`camelot.admin.action..base.Action` objects, as returned by the :meth:`camelot.admin.application_admin.ApplicationAdmin.get_toolbar_actions` method. """ from camelot.view.controls.action_widget import ActionAction if toolbar_actions != None: # # gather menu bar actions to prevent duplication of QActions # qactions = dict() menu_bar = self.menuBar() if menu_bar: for qaction in menu_bar.findChildren(ActionAction): qactions[qaction.action] = qaction toolbar = QtWidgets.QToolBar(_('Toolbar')) self.addToolBar(toolbar_area, toolbar) toolbar.setObjectName('MainWindowToolBar_%i' % toolbar_area) toolbar.setMovable(False) toolbar.setFloatable(False) for action in toolbar_actions: qaction = qactions.get(action, None) if qaction != None: # the action already exists in the menu toolbar.addAction(qaction) if qaction == None: rendered = action.render(self.gui_context, toolbar) # both QWidgets and QActions can be put in a toolbar if isinstance(rendered, QtWidgets.QWidget): toolbar.addWidget(rendered) elif isinstance(rendered, QtWidgets.QAction): rendered.triggered.connect(self.action_triggered) toolbar.addAction(rendered) self.toolbars.append(toolbar) toolbar.addWidget(BusyWidget())
class ImportCovers( Action ): verbose_name = _('Import cover images') icon = Icon('tango/22x22/mimetypes/image-x-generic.png') # begin select files def model_run( self, model_context ): from camelot.view.action_steps import ( SelectFile, UpdateProgress, Refresh, FlushSession ) select_image_files = SelectFile( 'Image Files (*.png *.jpg);;All Files (*)' ) select_image_files.single = False file_names = yield select_image_files file_count = len( file_names ) # end select files # begin create movies import os from sqlalchemy import orm from camelot.core.orm import Session from camelot_example.model import Movie movie_mapper = orm.class_mapper( Movie ) cover_property = movie_mapper.get_property( 'cover' ) storage = cover_property.columns[0].type.storage session = Session() for i, file_name in enumerate(file_names): yield UpdateProgress( i, file_count ) title = os.path.splitext( os.path.basename( file_name ) )[0] stored_file = storage.checkin( six.text_type( file_name ) ) movie = Movie( title = six.text_type( title ) ) movie.cover = stored_file yield FlushSession( session ) # end create movies # begin refresh yield Refresh()
class ChangeRatingAction( Action ): """Action to print a list of movies""" verbose_name = _('Change Rating') def model_run( self, model_context ): # # the model_run generator method yields various ActionSteps # options = Options() yield ChangeObject( options ) if options.only_selected: iterator = model_context.get_selection() else: iterator = model_context.get_collection() for movie in iterator: yield UpdateProgress( text = u'Change %s'%unicode( movie ) ) movie.rating = min( 5, max( 0, (movie.rating or 0 ) + options.change ) ) # # FlushSession will write the changes to the database and inform # the GUI # yield FlushSession( model_context.session )
class BurnToDisk(Action): verbose_name = _('Burn to disk') def model_run(self, model_context): yield action_steps.UpdateProgress(0, 3, _('Formatting disk')) time.sleep(0.7) yield action_steps.UpdateProgress(1, 3, _('Burning movie')) time.sleep(0.7) yield action_steps.UpdateProgress(2, 3, _('Finishing')) time.sleep(0.5) # end simple action definition def get_state(self, model_context): """Turn the burn to disk button on, only if the title of the movie is entered""" state = super(BurnToDisk, self).get_state(model_context) obj = model_context.get_object() if obj and obj.title: state.enabled = True else: state.enabled = False return state
def __init__(self, app_admin, parent): super(DesktopWorkspace, self).__init__(parent) self.gui_context = ApplicationActionGuiContext() self.gui_context.admin = app_admin self.gui_context.workspace = self self._app_admin = app_admin layout = QtWidgets.QHBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) # Setup the tab widget self._tab_widget = QtWidgets.QTabWidget(self) tab_bar = DesktopTabbar(self._tab_widget) tab_bar.setToolTip(_('Double click to (un)maximize')) tab_bar.change_view_mode_signal.connect(self._change_view_mode) self._tab_widget.setTabBar(tab_bar) self._tab_widget.setDocumentMode(True) self._tab_widget.setTabsClosable(True) self._tab_widget.tabCloseRequested.connect(self._tab_close_request) self._tab_widget.currentChanged.connect(self._tab_changed) layout.addWidget(self._tab_widget) self.setLayout(layout)
def __init__(self, parent): super(DesktopWorkspace, self).__init__(parent) layout = QtGui.QHBoxLayout() layout.setMargin(0) layout.setSpacing(0) # setup the tab widget self._tab_widget = QtGui.QTabWidget(self) tab_bar = DesktopTabbar(self._tab_widget) tab_bar.setToolTip(_('Double click to (un)maximize')) tab_bar.change_view_mode_signal.connect(self._change_view_mode) self._tab_widget.setTabBar(tab_bar) self._tab_widget.setDocumentMode(True) self._tab_widget.setMovable(True) self._tab_widget.setTabsClosable(True) self._tab_widget.hide() self._tab_widget.tabCloseRequested.connect(self._tab_close_request) self._tab_widget.currentChanged.connect(self._tab_changed) layout.addWidget(self._tab_widget) # setup the background widget self._background_widget = self.background(self) self._background_widget.show() layout.addWidget(self._background_widget) self.setLayout(layout)
class OpenTableView(EntityAction): """An application action that opens a TableView of an Entity :param entity_admin: an instance of :class:`camelot.admin.entity_admin.EntityAdmin` to be used to visualize the entities """ modes = [Mode('new_tab', _('Open in New Tab'))] def get_state(self, model_context): state = super(OpenTableView, self).get_state(model_context) state.verbose_name = self.verbose_name or self._entity_admin.get_verbose_name_plural( ) return state def gui_run(self, gui_context): table_view = self._entity_admin.create_table_view(gui_context) if gui_context.mode_name == 'new_tab': gui_context.workspace.add_view(table_view) else: gui_context.workspace.set_view(table_view)
class OpenTableView(EntityAction): """An application action that opens a TableView of an Entity :param entity_admin: an instance of :class:`camelot.admin.entity_admin.EntityAdmin` to be used to visualize the entities """ modes = [Mode('new_tab', _('Open in New Tab'))] def get_state(self, model_context): state = super(OpenTableView, self).get_state(model_context) state.verbose_name = self.verbose_name or self._entity_admin.get_verbose_name_plural( ) return state def model_run(self, model_context): from camelot.view import action_steps yield action_steps.UpdateProgress(text=_('Open table')) step = action_steps.OpenTableView(self._entity_admin, self._entity_admin.get_query()) step.new_tab = (model_context.mode_name == 'new_tab') yield step
class UpdatePerson( Action ): verbose_name = _('Update person') def model_run( self, model_context ): for person in model_context.get_selection(): soc_number = person.social_security_number if soc_number: # assume the social sec number contains the birth date person.birth_date = datetime.date( int(soc_number[0:4]), int(soc_number[4:6]), int(soc_number[6:8]) ) # delete the email of the person for contact_mechanism in person.contact_mechanisms: model_context.session.delete( contact_mechanism ) # add a new email m = ('email', '*****@*****.**'%( person.first_name, person.last_name ) ) cm = party.ContactMechanism( mechanism = m ) party.PartyContactMechanism( party = person, contact_mechanism = cm ) # flush the session on finish and update the GUI yield action_steps.FlushSession( model_context.session )
def create_labels_and_widgets(self): self.profile_label = QLabel(_('Profile Name:')) self.dialect_label = QLabel(_('Driver:')) self.host_label = QLabel(_('Server Host:')) self.port_label = QLabel(_('Port:')) self.database_name_label = QLabel(_('Database Name:')) self.username_label = QLabel(_('Username:'******'Password:')) layout = QGridLayout() layout.addWidget(self.profile_label, 0, 0, Qt.AlignRight) layout.addWidget(self.dialect_label, 1, 0, Qt.AlignRight) layout.addWidget(self.host_label, 2, 0, Qt.AlignRight) layout.addWidget(self.port_label, 2, 3, Qt.AlignRight) layout.addWidget(self.database_name_label, 3, 0, Qt.AlignRight) layout.addWidget(self.username_label, 4, 0, Qt.AlignRight) layout.addWidget(self.password_label, 5, 0, Qt.AlignRight) self.profile_editor = ChoicesEditor(parent=self) self.dialect_editor = ChoicesEditor(parent=self) self.host_editor = TextLineEditor(self) self.port_editor = TextLineEditor(self) self.port_editor.setFixedWidth(60) self.database_name_editor = TextLineEditor(self) self.username_editor = TextLineEditor(self) self.password_editor = TextLineEditor(self) self.password_editor.setEchoMode(QLineEdit.Password) layout.addWidget(self.profile_editor, 0, 1, 1, 4) layout.addWidget(self.dialect_editor, 1, 1, 1, 1) layout.addWidget(self.host_editor, 2, 1, 1, 1) layout.addWidget(self.port_editor, 2, 4, 1, 1) layout.addWidget(self.database_name_editor, 3, 1, 1, 1) layout.addWidget(self.username_editor, 4, 1, 1, 1) layout.addWidget(self.password_editor, 5, 1, 1, 1) self.main_widget().setLayout(layout)
class Admin(object): field_attributes = dict( street1=dict(editable=True, name=_('Street'), minimal_column_width=50), street2=dict(editable=True, name=_('Street Extra'), minimal_column_width=50), city=dict(editable=True, delegate=delegates.Many2OneDelegate, target=City), email=dict(editable=True, minimal_column_width=20, name=_('Email'), address_type='email', from_string=lambda s: ('email', s), delegate=delegates.VirtualAddressDelegate), phone=dict(editable=True, minimal_column_width=20, address_type='phone', name=_('Phone'), from_string=lambda s: ('phone', s), delegate=delegates.VirtualAddressDelegate), mobile=dict(editable=True, minimal_column_width=20, address_type='mobile', name=_('Mobile'), from_string=lambda s: ('mobile', s), delegate=delegates.VirtualAddressDelegate), fax=dict(editable=True, minimal_column_width=20, address_type='fax', name=_('Fax'), from_string=lambda s: ('fax', s), delegate=delegates.VirtualAddressDelegate), )
def __init__(self): super(ExportAsPO, self).__init__( name=_('po export'), icon=Icon('tango/16x16/actions/document-save.png'))
class Admin( PartyRelationship.Admin ): verbose_name = _('Supplier - Customer') list_display = ['established_from', 'established_to', 'from_date', 'thru_date']
class SharedAdmin( Admin ): verbose_name = _('Shares') verbose_name_plural = _('Shares') list_display = ['established_from', 'shares', 'from_date', 'thru_date'] form_display = ['established_from', 'shares', 'from_date', 'thru_date', 'comment'] form_size = (500, 300)
def __init__(self, items, value=None): self.items = items self.value = value self.autoaccept = True self.title = _('Please select') self.subtitle = _('Make a selection and press the OK button')
def __init__(self): QtGui.QProgressDialog.__init__(self, _('Please wait'), QtCore.QString(), 0, 0) self.setWindowTitle(_('Save file')) self.setRange(0, 0)
def get_delete_message(self, obj): return _('Are you sure you want to delete this')
class SupplierAdmin( EntityAdmin ): verbose_name = _('Supplier') list_display = ['established_from', ] form_display = ['established_from', 'comment', 'from_date', 'thru_date'] field_attributes = {'established_from':{'name':_( 'Name' )}}
class Admin( EntityAdmin ): verbose_name = _('Address role type') list_display = ['code', 'description']
def note(self): for person in self.__class__.query.filter_by(first_name=self.first_name, last_name=self.last_name): if person != self: return _('A person with the same name allready exists')
class Admin( EntityAdmin ): verbose_name = _('Authentication mechanism') list_display = ['username', 'last_login', 'is_active']
def __init__(self, parent=None, width=50, height=40, dpi=50, field_name='chart', **kwargs): from matplotlib.figure import Figure from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas super(ChartEditor, self).__init__(parent) AbstractCustomEditor.__init__(self) self.setObjectName(field_name) chart_frame = QtWidgets.QFrame(self) chart_frame.setFrameShape(self.Box) chart_frame.setContentsMargins(1, 1, 1, 1) chart_frame_layout = QtWidgets.QHBoxLayout() chart_frame_layout.setContentsMargins(0, 0, 0, 0) chart_frame.setLayout(chart_frame_layout) # find out background color, because using a transparent # figure fails when the window is resized: the background # is not redrawn # need to do str() else matplotlib gets confused by the qstring # bgcolorrgb = str(self.palette().background().color().name()) self.fig = Figure( figsize=(width, height), dpi=dpi, facecolor='#ffffff', ) layout = QtWidgets.QHBoxLayout() self.canvas = FigureCanvas(self.fig) chart_frame_layout.addWidget(self.canvas) layout.addWidget(chart_frame) button_layout = QtWidgets.QVBoxLayout() button_layout.setSpacing(0) icon = Icon( 'tango/16x16/actions/document-print-preview.png').getQIcon() button_layout.addStretch() print_button = QtWidgets.QToolButton() print_button.setIcon(icon) print_button.setAutoRaise(True) print_button.setToolTip(_('Print Preview')) print_button.clicked.connect(self.print_preview) button_layout.addWidget(print_button) icon = Icon('tango/16x16/actions/edit-copy.png').getQIcon() copy_button = QtWidgets.QToolButton() copy_button.setIcon(icon) copy_button.setAutoRaise(True) copy_button.setToolTip(_('Copy to clipboard')) copy_button.clicked.connect(self.copy_to_clipboard) button_layout.addWidget(copy_button) layout.addLayout(button_layout) layout.setContentsMargins(0, 0, 0, 0) self.setLayout(layout) self.canvas.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) self.canvas.installEventFilter(self) self.show_fullscreen_signal.connect(self.show_fullscreen) self.canvas.updateGeometry() self._litebox = None self.gui_context = ListActionGuiContext()
def __init__(self, parent=None): QtWidgets.QDialog.__init__(self, parent) mainLayout = QtWidgets.QVBoxLayout() topLeftLayout = QtWidgets.QVBoxLayout() topRightLayout = QtWidgets.QHBoxLayout() bottomRightLayout = QtWidgets.QHBoxLayout() bottomLayout = QtGui.QGridLayout() self.setWindowTitle(_('Calculator')) self.input = QtWidgets.QLineEdit(self) self.input.textEdited.connect(self.Calculate) #BUTTONS--- self.equals = QtWidgets.QPushButton('=', self) self.discount = QtWidgets.QPushButton('Discount', self) self.save = QtWidgets.QPushButton('&Save', self) self.cancel = QtWidgets.QPushButton('Cancel', self) self.zero = QtWidgets.QPushButton('0', self) self.one = QtWidgets.QPushButton('1', self) self.two = QtWidgets.QPushButton('2', self) self.three = QtWidgets.QPushButton('3', self) self.four = QtWidgets.QPushButton('4', self) self.five = QtWidgets.QPushButton('5', self) self.six = QtWidgets.QPushButton('6', self) self.seven = QtWidgets.QPushButton('7', self) self.eight = QtWidgets.QPushButton('8', self) self.nine = QtWidgets.QPushButton('9', self) self.clear = QtWidgets.QPushButton('&Clear', self) self.backspace = QtWidgets.QToolButton() icon = Icon('tango/16x16/actions/go-previous.png').getQIcon() self.backspace.setIcon(icon) self.backspace.setAutoRaise(True) self.plus = QtWidgets.QPushButton('+', self) self.min = QtWidgets.QPushButton('-', self) self.multiply = QtWidgets.QPushButton('x', self) self.devide = QtWidgets.QPushButton('/', self) self.comma = QtWidgets.QPushButton(',', self) #Button-Connects--- self.equals.clicked.connect(self.ShowCalculate) self.zero.clicked.connect(lambda: self.buttonClick(0)) self.one.clicked.connect(lambda: self.buttonClick(1)) self.two.clicked.connect(lambda: self.buttonClick(2)) self.three.clicked.connect(lambda: self.buttonClick(3)) self.four.clicked.connect(lambda: self.buttonClick(4)) self.five.clicked.connect(lambda: self.buttonClick(5)) self.six.clicked.connect(lambda: self.buttonClick(6)) self.seven.clicked.connect(lambda: self.buttonClick(7)) self.eight.clicked.connect(lambda: self.buttonClick(8)) self.nine.clicked.connect(lambda: self.buttonClick(9)) self.plus.clicked.connect(lambda: self.buttonClick('+')) self.min.clicked.connect(lambda: self.buttonClick('-')) self.multiply.clicked.connect(lambda: self.buttonClick('*')) self.devide.clicked.connect(lambda: self.buttonClick('/')) self.clear.clicked.connect(self.clearInput) self.backspace.clicked.connect(lambda: self.input.backspace()) self.comma.clicked.connect(lambda: self.buttonClick('.')) self.cancel.clicked.connect(lambda: self.close()) self.save.clicked.connect(self.SaveValue) self.discount.clicked.connect(self.discountClick) self.output = QtWidgets.QLabel(self) #self.output.move(3, 8) mainLayout.addLayout(topLeftLayout) topLeftLayout.addLayout(topRightLayout) topRightLayout.addWidget(self.input) topRightLayout.addWidget(self.backspace) topLeftLayout.addWidget(self.output) topLeftLayout.addLayout(bottomRightLayout) bottomRightLayout.addWidget(self.equals) bottomRightLayout.addWidget(self.discount) bottomRightLayout.addWidget(self.save) bottomRightLayout.addWidget(self.cancel) mainLayout.addLayout(bottomLayout) bottomLayout.addWidget(self.one, 0, 0) bottomLayout.addWidget(self.two, 0, 1) bottomLayout.addWidget(self.three, 0, 2) bottomLayout.addWidget(self.plus, 0, 3) bottomLayout.addWidget(self.four, 1, 0) bottomLayout.addWidget(self.five, 1, 1) bottomLayout.addWidget(self.six, 1, 2) bottomLayout.addWidget(self.min, 1, 3) bottomLayout.addWidget(self.seven, 2, 0) bottomLayout.addWidget(self.eight, 2, 1) bottomLayout.addWidget(self.nine, 2, 2) bottomLayout.addWidget(self.multiply, 2, 3) bottomLayout.addWidget(self.clear, 3, 0) bottomLayout.addWidget(self.zero, 3, 1) bottomLayout.addWidget(self.comma, 3, 2) bottomLayout.addWidget(self.devide, 3, 3) self.setLayout(mainLayout)
class Admin(EntityAdmin): verbose_name = _('Visitors per director') list_display = ['first_name', 'last_name', 'visitors']
def backup(self): """Generator function that yields tuples : (numer_of_steps_completed, total_number_of_steps, description_of_current_step) while performing a backup. """ import os import tempfile import shutil import settings from sqlalchemy import create_engine from sqlalchemy import MetaData from sqlalchemy.pool import NullPool from sqlalchemy.dialects import mysql as mysql_dialect import sqlalchemy.types yield (0, 0, _('Analyzing database structure')) from_engine = settings.ENGINE() from_meta_data = MetaData() from_meta_data.bind = from_engine from_meta_data.reflect() yield (0, 0, _('Preparing backup file')) # # We'll first store the backup in a temporary file, since # the selected file might be on a server or in a storage # file_descriptor, temp_file_name = tempfile.mkstemp(suffix='.db') os.close(file_descriptor) logger.info("preparing backup to '%s'"%temp_file_name) if os.path.exists(self._filename): os.remove(self._filename) to_engine = create_engine( u'sqlite:///%s'%temp_file_name, poolclass=NullPool ) to_meta_data = MetaData() to_meta_data.bind = to_engine # # Only copy tables, to prevent issues with indices and constraints # from_and_to_tables = [] for from_table in from_meta_data.sorted_tables: if self.backup_table_filter(from_table): to_table = from_table.tometadata(to_meta_data) # # Dirty hack : loop over all columns to detect mysql TINYINT # columns and convert them to BOOL # for col in to_table.columns: if isinstance(col.type, mysql_dialect.TINYINT): col.type = sqlalchemy.types.Boolean() # # End of dirty hack # to_table.create(to_engine) from_and_to_tables.append((from_table, to_table)) number_of_tables = len(from_and_to_tables) for i,(from_table, to_table) in enumerate(from_and_to_tables): yield (i, number_of_tables + 1, _('Copy data of table %s')%from_table.name) self.copy_table_data(from_table, to_table) yield (number_of_tables, number_of_tables + 1, _('Store backup at requested location') ) if not self._storage: shutil.move(temp_file_name, self._filename) else: self._storage.checkin( temp_file_name, self._filename ) os.remove( temp_file_name ) yield (number_of_tables + 1, number_of_tables + 1, _('Backup completed'))
def restore(self): """Generator function that yields tuples : (numer_of_steps_completed, total_number_of_steps, description_of_current_step) while performing a restore. """ # # The restored database may contain different AuthenticationMechanisms # from camelot.model.authentication import clear_current_authentication clear_current_authentication() # # Proceed with the restore # import os from camelot.core.files.storage import StoredFile import settings from sqlalchemy import create_engine from sqlalchemy import MetaData from sqlalchemy.pool import NullPool yield (0, 0, _('Open backup file')) if self._storage: if not self._storage.exists(self._filename): raise Exception('Backup file does not exist') stored_file = StoredFile(self._storage, self._filename) filename = self._storage.checkout( stored_file ) else: if not os.path.exists(self._filename): raise Exception('Backup file does not exist') filename = self._filename from_engine = create_engine('sqlite:///%s'%filename, poolclass=NullPool ) yield (0, 0, _('Prepare database for restore')) to_engine = settings.ENGINE() self.prepare_schema_for_restore(from_engine, to_engine) yield (0, 0, _('Analyzing backup structure')) from_meta_data = MetaData() from_meta_data.bind = from_engine from_meta_data.reflect() yield (0, 0, _('Analyzing database structure')) to_meta_data = MetaData() to_meta_data.bind = to_engine to_meta_data.reflect() to_tables = list(table for table in to_meta_data.sorted_tables if self.restore_table_filter(table)) number_of_tables = len(to_tables) steps = number_of_tables * 2 + 2 for i,to_table in enumerate(reversed(to_tables)): yield (i, steps, _('Delete data from table %s')%to_table.name) self.delete_table_data(to_table) for i,to_table in enumerate(to_tables): if to_table.name in from_meta_data.tables: yield (number_of_tables+i, steps, _('Copy data from table %s')%to_table.name) self.copy_table_data(from_meta_data.tables[to_table.name], to_table) yield (number_of_tables * 2 + 1, steps, _('Update schema after restore')) self.update_schema_after_restore(from_engine, to_engine) yield (number_of_tables * 2 + 2, steps, _('Expire current session')) from sqlalchemy.orm.session import _sessions for session in _sessions.values(): session.expire_all() yield (1, 1, _('Restore completed'))
class Admin(EntityAdmin): verbose_name = _('Authentication mechanism') list_display = [ 'authentication_type', 'username', 'from_date', 'thru_date', 'last_login' ]
class ShareholderAdmin( Admin ): verbose_name = _('Shareholder') list_display = ['established_to', 'shares', 'from_date', 'thru_date'] form_display = ['established_to', 'shares', 'from_date', 'thru_date', 'comment'] form_size = (500, 300)