22 #include <QMouseEvent> 26 #include <QProgressBar> 28 #include <QHeaderView> 40 QVBoxLayout *vLayout =
new QVBoxLayout();
41 vLayout->setMargin( 0 );
42 mTreeView =
new QTreeView();
43 mModel =
new QgsTaskManagerModel( manager,
this );
44 mTreeView->setModel( mModel );
45 connect( mModel, &QgsTaskManagerModel::rowsInserted,
this, &QgsTaskManagerWidget::modelRowsInserted );
46 mTreeView->setHeaderHidden(
true );
47 mTreeView->setRootIsDecorated(
false );
48 mTreeView->setSelectionBehavior( QAbstractItemView::SelectRows );
50 mTreeView->setColumnWidth( QgsTaskManagerModel::Progress, progressColWidth );
52 mTreeView->setColumnWidth( QgsTaskManagerModel::Status, statusColWidth );
53 mTreeView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
54 mTreeView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOn );
55 mTreeView->header()->setStretchLastSection(
false );
56 mTreeView->header()->setSectionResizeMode( QgsTaskManagerModel::Description, QHeaderView::Stretch );
58 connect( mTreeView, &QTreeView::clicked,
this, &QgsTaskManagerWidget::clicked );
60 vLayout->addWidget( mTreeView );
71 void QgsTaskManagerWidget::modelRowsInserted(
const QModelIndex &,
int start,
int end )
73 for (
int row = start; row <= end; ++row )
75 QgsTask *task = mModel->indexToTask( mModel->index( row, 1 ) );
79 QProgressBar *progressBar =
new QProgressBar();
80 progressBar->setAutoFillBackground(
true );
81 progressBar->setRange( 0, 0 );
87 progressBar->setMaximum( 100 );
88 progressBar->setValue( progress );
91 progressBar->setMaximum( 0 );
94 mTreeView->setIndexWidget( mModel->index( row, QgsTaskManagerModel::Progress ), progressBar );
96 QgsTaskStatusWidget *statusWidget =
new QgsTaskStatusWidget(
nullptr, task->
status(), task->
canCancel() );
97 statusWidget->setAutoFillBackground(
true );
99 connect( statusWidget, &QgsTaskStatusWidget::cancelClicked, task, &
QgsTask::cancel );
100 mTreeView->setIndexWidget( mModel->index( row, QgsTaskManagerModel::Status ), statusWidget );
104 void QgsTaskManagerWidget::clicked(
const QModelIndex &index )
106 QgsTask *task = mModel->indexToTask( index );
118 QgsTaskManagerModel::QgsTaskManagerModel(
QgsTaskManager *manager, QObject *parent )
119 : QAbstractItemModel( parent )
120 , mManager( manager )
122 Q_ASSERT( mManager );
127 mRowToTaskIdList << mManager->
taskId( task );
135 QModelIndex QgsTaskManagerModel::index(
int row,
int column,
const QModelIndex &parent )
const 137 if ( column < 0 || column >= columnCount() )
140 return QModelIndex();
143 if ( !parent.isValid() && row >= 0 && row < mRowToTaskIdList.count() )
146 return createIndex( row, column );
150 return QModelIndex();
154 QModelIndex QgsTaskManagerModel::parent(
const QModelIndex &index )
const 159 return QModelIndex();
162 int QgsTaskManagerModel::rowCount(
const QModelIndex &parent )
const 164 if ( !parent.isValid() )
166 return mRowToTaskIdList.count();
175 int QgsTaskManagerModel::columnCount(
const QModelIndex &parent )
const 181 QVariant QgsTaskManagerModel::data(
const QModelIndex &index,
int role )
const 183 if ( !index.isValid() )
186 QgsTask *task = indexToTask( index );
191 case Qt::DisplayRole:
193 switch ( index.column() )
207 return static_cast<int>( task->
status() );
209 case Qt::ToolTipRole:
210 switch ( index.column() )
220 return tr(
"Queued" );
222 return tr(
"On hold" );
225 if ( index.column() == Status && !task->
canCancel() )
226 return tr(
"Running (cannot cancel)" );
228 return tr(
"Running" );
231 return tr(
"Complete" );
233 return tr(
"Terminated" );
250 Qt::ItemFlags QgsTaskManagerModel::flags(
const QModelIndex &index )
const 252 Qt::ItemFlags flags = QAbstractItemModel::flags( index );
254 if ( ! index.isValid() )
259 QgsTask *task = indexToTask( index );
260 if ( index.column() == Status )
263 flags = flags | Qt::ItemIsEditable;
265 return flags | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
268 bool QgsTaskManagerModel::setData(
const QModelIndex &index,
const QVariant &value,
int role )
272 if ( !index.isValid() )
275 QgsTask *task = indexToTask( index );
279 switch ( index.column() )
283 if ( value.toBool() && task->
canCancel() )
293 void QgsTaskManagerModel::taskAdded(
long id )
295 beginInsertRows( QModelIndex(), mRowToTaskIdList.count(),
296 mRowToTaskIdList.count() );
297 mRowToTaskIdList << id;
301 void QgsTaskManagerModel::taskDeleted(
long id )
303 for (
int row = 0; row < mRowToTaskIdList.count(); ++row )
305 if ( mRowToTaskIdList.at( row ) == id )
307 beginRemoveRows( QModelIndex(), row, row );
308 mRowToTaskIdList.removeAt( row );
315 void QgsTaskManagerModel::progressChanged(
long id,
double progress )
317 Q_UNUSED( progress );
319 QModelIndex index = idToIndex(
id, Progress );
320 if ( !index.isValid() )
325 emit dataChanged( index, index );
328 void QgsTaskManagerModel::statusChanged(
long id,
int status )
336 QModelIndex index = idToIndex(
id, Status );
337 if ( !index.isValid() )
342 emit dataChanged( index, index );
346 QgsTask *QgsTaskManagerModel::indexToTask(
const QModelIndex &index )
const 348 if ( !index.isValid() || index.parent().isValid() )
351 long id = index.row() >= 0 && index.row() < mRowToTaskIdList.count() ? mRowToTaskIdList.at( index.row() ) : -1;
353 return mManager->
task(
id );
358 int QgsTaskManagerModel::idToRow(
long id )
const 360 for (
int row = 0; row < mRowToTaskIdList.count(); ++row )
362 if ( mRowToTaskIdList.at( row ) == id )
370 QModelIndex QgsTaskManagerModel::idToIndex(
long id,
int column )
const 372 int row = idToRow(
id );
374 return QModelIndex();
376 return index( row, column );
384 QgsTaskStatusWidget::QgsTaskStatusWidget( QWidget *parent,
QgsTask::TaskStatus status,
bool canCancel )
386 , mCanCancel( canCancel )
389 setMouseTracking(
true );
392 QSize QgsTaskStatusWidget::sizeHint()
const 394 return QSize( 32, 32 );
397 void QgsTaskStatusWidget::setStatus(
int status )
403 void QgsTaskStatusWidget::paintEvent( QPaintEvent *e )
405 QWidget::paintEvent( e );
435 icon.paint( &p, 1, height() / 2 - 12, 24, 24 );
439 void QgsTaskStatusWidget::mousePressEvent( QMouseEvent * )
442 emit cancelClicked();
445 void QgsTaskStatusWidget::mouseMoveEvent( QMouseEvent * )
454 void QgsTaskStatusWidget::leaveEvent( QEvent * )
483 QgsTaskManagerFloatingWidget::QgsTaskManagerFloatingWidget(
QgsTaskManager *manager, QWidget *parent )
486 setLayout(
new QVBoxLayout() );
490 setMinimumSize( minWidth, minHeight );
491 layout()->addWidget( w );
492 setStyleSheet(
".QgsTaskManagerFloatingWidget { border-top-left-radius: 8px;" 493 "border-top-right-radius: 8px; background-color: rgb(0, 0, 0, 70%); }" );
497 QgsTaskManagerStatusBarWidget::QgsTaskManagerStatusBarWidget(
QgsTaskManager *manager, QWidget *parent )
498 : QToolButton( parent )
499 , mManager( manager )
501 setAutoRaise(
true );
502 setSizePolicy( QSizePolicy::Fixed, QSizePolicy::MinimumExpanding );
503 setLayout(
new QVBoxLayout() );
505 mProgressBar =
new QProgressBar();
506 mProgressBar->setMinimum( 0 );
507 mProgressBar->setMaximum( 0 );
508 layout()->setContentsMargins( 5, 5, 5, 5 );
509 layout()->addWidget( mProgressBar );
511 mFloatingWidget =
new QgsTaskManagerFloatingWidget( manager, parent ? parent->window() : nullptr );
512 mFloatingWidget->setAnchorWidget(
this );
515 mFloatingWidget->hide();
516 connect(
this, &QgsTaskManagerStatusBarWidget::clicked,
this, &QgsTaskManagerStatusBarWidget::toggleDisplay );
525 QSize QgsTaskManagerStatusBarWidget::sizeHint()
const 528 int height = QToolButton::sizeHint().height();
529 return QSize( width, height );
532 void QgsTaskManagerStatusBarWidget::toggleDisplay()
534 if ( mFloatingWidget->isVisible() )
535 mFloatingWidget->hide();
538 mFloatingWidget->show();
539 mFloatingWidget->raise();
543 void QgsTaskManagerStatusBarWidget::overallProgressChanged(
double progress )
545 mProgressBar->setValue( progress );
547 mProgressBar->setMaximum( 0 );
548 else if ( mProgressBar->maximum() == 0 )
549 mProgressBar->setMaximum( 100 );
550 setToolTip( mManager->
activeTasks().at( 0 )->description() );
553 void QgsTaskManagerStatusBarWidget::countActiveTasksChanged(
int count )
557 mProgressBar->setMaximum( 0 );
558 setToolTip( tr(
"%1 active tasks running" ).arg( count ) );
562 void QgsTaskManagerStatusBarWidget::allFinished()
564 mFloatingWidget->hide();
567 mProgressBar->setMaximum( 0 );
568 mProgressBar->setValue( 0 );
571 void QgsTaskManagerStatusBarWidget::showButton()
575 mProgressBar->setMaximum( 100 );
576 mProgressBar->setValue( 0 );
static const double UI_SCALE_FACTOR
UI scaling factor.
void statusChanged(int status)
Will be emitted by task when its status changes.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
TaskStatus
Status of tasks.
QList< QgsTask * > tasks() const
Returns all tasks tracked by the manager.
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
void progressChanged(double progress)
Will be emitted by task when its progress changes.
Task was terminated or errored.
void countActiveTasksChanged(int count)
Emitted when the number of active tasks changes.
void triggerTask(QgsTask *task)
Triggers a task, e.g.
QString description() const
Returns the task's description.
QgsTask * task(long id) const
Returns the task with matching ID.
void progressChanged(long taskId, double progress)
Will be emitted when a task reports a progress change.
Task is queued but on hold and will not be started.
Abstract base class for long running background tasks.
bool canCancel() const
Returns true if the task can be canceled.
void statusChanged(long taskId, int status)
Will be emitted when a task reports a status change.
Task successfully completed.
Task manager for managing a set of long-running QgsTask tasks.
void taskAdded(long taskId)
Emitted when a new task has been added to the manager.
virtual void cancel()
Notifies the task that it should terminate.
void allTasksFinished()
Emitted when all tasks are complete.
Task is queued and has not begun.
double progress() const
Returns the task's progress (between 0.0 and 100.0)
QList< QgsTask *> activeTasks() const
Returns a list of the active (queued or running) tasks.
Task is currently running.
long taskId(QgsTask *task) const
Returns the unique task ID corresponding to a task managed by the class.
void finalTaskProgressChanged(double progress)
Will be emitted when only a single task remains to complete and that task has reported a progress cha...
TaskStatus status() const
Returns the current task status.