Source code for camelot.view.controls.progress_dialog

#  ============================================================================
#
#  Copyright (C) 2007-2016 Conceptive Engineering bvba.
#  www.conceptive.be / info@conceptive.be
#
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions are met:
#      * Redistributions of source code must retain the above copyright
#        notice, this list of conditions and the following disclaimer.
#      * Redistributions in binary form must reproduce the above copyright
#        notice, this list of conditions and the following disclaimer in the
#        documentation and/or other materials provided with the distribution.
#      * Neither the name of Conceptive Engineering nor the
#        names of its contributors may be used to endorse or promote products
#        derived from this software without specific prior written permission.
#  
#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
#  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
#  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
#  DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
#  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
#  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
#  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
#  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#  ============================================================================

"""Functions and classes to use a progress dialog in combination with
a model thread"""

import logging

from camelot.core.utils import ugettext
from camelot.view.art import Icon

import six

from ...core.qt import QtGui, QtCore, QtWidgets, Qt, q_string, py_to_variant

LOGGER = logging.getLogger( 'camelot.view.controls.progress_dialog' )

[docs]class ProgressDialog(QtWidgets.QProgressDialog): """ A Progress Dialog, used during the :meth:`gui_run` of an action. .. image:: /_static/controls/progress_dialog.png """ progress_icon = Icon('tango/32x32/actions/appointment-new.png') def __init__(self, name, icon=progress_icon): QtWidgets.QProgressDialog.__init__( self, q_string(u''), q_string(u''), 0, 0 ) label = QtWidgets.QLabel( six.text_type(name) ) progress_bar = QtWidgets.QProgressBar() progress_bar.setObjectName('progress_bar') cancel_button = QtWidgets.QPushButton( ugettext('Cancel') ) cancel_button.setObjectName( 'cancel' ) ok_button = QtWidgets.QPushButton( ugettext('OK') ) ok_button.setObjectName( 'ok' ) ok_button.clicked.connect( self.accept ) ok_button.hide() copy_button = QtWidgets.QPushButton( ugettext('Copy') ) copy_button.setObjectName( 'copy' ) copy_button.clicked.connect( self.copy_clicked ) copy_button.hide() copy_button.setToolTip(ugettext('Copy details to clipboard')) self.setBar( progress_bar ) self.setLabel( label ) self.setCancelButton( cancel_button ) self._window_title = ugettext('Please wait') self.setWindowTitle(self._window_title) # use a list view to display details, for performance reasons, # since this widget will not freeze in case the list of details # becomes long details = QtWidgets.QListView( parent = self ) details.setObjectName( 'details' ) details.hide() layout = QtWidgets.QVBoxLayout() layout.addWidget( label ) layout.addWidget( progress_bar ) button_layout = QtWidgets.QHBoxLayout() button_layout.setDirection( QtWidgets.QBoxLayout.RightToLeft ) button_layout.addWidget( ok_button ) button_layout.addWidget( cancel_button ) button_layout.addWidget( copy_button ) button_layout.addStretch() layout.addWidget( details ) layout.addLayout( button_layout ) self.setLayout( layout ) # show immediately, to prevent a pop up before another window # opened in an action_step self.show() #QtCore.QTimer.singleShot( 1000, self.show ) @property def title(self): return self._window_title @title.setter def title(self, value): self._window_title = value self.setWindowTitle(value) # This method is overwritten,to undo the overwrite of this method # in QProgressDialog, as the QProgressDialog then manually relayouts # the dialog instead of using the normal layouts def resizeEvent(self, event): return QtWidgets.QWidget.resizeEvent(self, event) @QtCore.qt_slot(bool) def copy_clicked(self, checked): details = self.findChild( QtWidgets.QListView, 'details' ) if details is None: return model = details.model() if model is not None: text = u'\n'.join([six.text_type(s) for s in model.stringList()]) QtWidgets.QApplication.clipboard().setText(text)
[docs] def add_detail( self, text ): """Add detail text to the list of details in the progress dialog :param text: a string """ details = self.findChild( QtWidgets.QListView, 'details' ) copy_button = self.findChild( QtWidgets.QPushButton, 'copy' ) if copy_button is not None: copy_button.show() if details is not None: # a standarditem model is used, in the ideal case, the item # model with the real data should live in the model thread, and # this should only be a proxy if details.isHidden(): model = QtGui.QStringListModel( parent = self ) details.setModel( model ) details.show() model = details.model() model.insertRow(model.rowCount()) model.setData(model.index(model.rowCount()-1, 0), py_to_variant(text), Qt.DisplayRole)
[docs] def clear_details( self ): """Clear the detail text""" details = self.findChild( QtWidgets.QListView, 'details' ) if details is not None: details.hide()
[docs] def enlarge(self): """ Increase the size of the dialog window """ desktop = QtWidgets.QApplication.desktop() geo = desktop.availableGeometry(self) self.resize(geo.width() * 0.75, geo.height() * 0.75) frame = self.frameGeometry() frame.moveCenter(geo.center()) self.move(frame.topLeft())
def set_ok_hidden( self, hidden = True ): ok_button = self.findChild( QtWidgets.QPushButton, 'ok' ) progress_bar = self.findChild(QtWidgets.QProgressBar, 'progress_bar') if ok_button: ok_button.setHidden( hidden ) progress_bar.setHidden(not hidden) self.setWindowTitle(self.title if hidden else ugettext('Completed')) def set_cancel_hidden( self, hidden = True ): cancel_button = self.findChild( QtWidgets.QPushButton, 'cancel' ) if cancel_button: cancel_button.setHidden( hidden )
[docs]class SplashProgress( QtWidgets.QSplashScreen ): """ Wrapper around :class:`QtWidgets.QSplashScreen` to make it behave as if it were a progress dialog, this allows reuse of the progress related action steps within a splash screen. """ # don't let splash screen stay on top, this might hinder # registration wizards or others that wait for user input # while camelot is starting up def __init__( self, pixmap ): super( SplashProgress, self ).__init__(pixmap) # allow the splash screen to keep the application alive, even # if the last dialog was closed layout = QtWidgets.QVBoxLayout() progress_bar = QtWidgets.QProgressBar(parent=self) progress_bar.setObjectName('progress_bar') layout.addStretch(1) layout.addWidget(progress_bar) self.setAttribute(Qt.WA_QuitOnClose) self.setWindowTitle(' ') # support transparency if pixmap.mask(): self.setMask(pixmap.mask()) self.setLayout(layout) def setMaximum( self, maximum ): progress_bar = self.findChild(QtWidgets.QProgressBar, 'progress_bar') progress_bar.setMaximum(maximum) def setValue( self, value ): progress_bar = self.findChild(QtWidgets.QProgressBar, 'progress_bar') progress_bar.setValue(value) def setLabelText( self, text ): progress_bar = self.findChild(QtWidgets.QProgressBar, 'progress_bar') progress_bar.setFormat(text) def wasCanceled( self ): return False def clear_details( self ): pass def add_detail( self, text ): self.setLabelText(text) def set_cancel_hidden( self, hidden = True ): pass def set_ok_hidden( self, hidden = True ): pass def exec_(self): pass