Skip to content

Commit d270b4f

Browse files
committed
Improvements to task manager ui
1 parent 5da2513 commit d270b4f

File tree

12 files changed

+460
-10
lines changed

12 files changed

+460
-10
lines changed

python/core/qgstaskmanager.sip

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,17 @@ class QgsTaskManager : QObject
235235
*/
236236
QStringList dependentLayers( long taskId ) const;
237237

238+
/** Returns a list of the active (queued or running) tasks.
239+
* @see countActiveTasks()
240+
*/
241+
QList< QgsTask* > activeTasks() const;
242+
243+
/** Returns the number of active (queued or running) tasks.
244+
* @see activeTasks()
245+
* @see countActiveTasksChanged()
246+
*/
247+
int countActiveTasks() const;
248+
238249
signals:
239250

240251
//! Will be emitted when a task reports a progress change
@@ -255,4 +266,12 @@ class QgsTaskManager : QObject
255266
//! @param taskId ID of task
256267
void taskAboutToBeDeleted( long taskId );
257268

269+
//! Emitted when all tasks are complete
270+
//! @see countActiveTasksChanged()
271+
void allTasksFinished();
272+
273+
//! Emitted when the number of active tasks changes
274+
//! @see countActiveTasks()
275+
void countActiveTasksChanged( int count );
276+
258277
};

python/gui/qgsfloatingwidget.sip

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/** \ingroup gui
2+
* \class QgsFloatingWidget
3+
* A QWidget subclass for creating widgets which float outside of the normal Qt layout
4+
* system. Floating widgets use an "anchor widget" to determine how they are anchored
5+
* within their parent widget.
6+
* \note Added in version 2.16
7+
*/
8+
9+
class QgsFloatingWidget : QWidget
10+
{
11+
%TypeHeaderCode
12+
#include <qgsfloatingwidget.h>
13+
%End
14+
15+
public:
16+
17+
//! Reference points for anchoring widget position
18+
enum AnchorPoint
19+
{
20+
TopLeft, //!< Top-left of widget
21+
TopMiddle, //!< Top center of widget
22+
TopRight, //!< Top-right of widget
23+
MiddleLeft, //!< Middle left of widget
24+
Middle, //!< Middle of widget
25+
MiddleRight, //!< Middle right of widget
26+
BottomLeft, //!< Bottom-left of widget
27+
BottomMiddle, //!< Bottom center of widget
28+
BottomRight, //!< Bottom-right of widget
29+
};
30+
31+
/** Constructor for QgsFloatingWidget.
32+
* @param parent parent widget
33+
*/
34+
QgsFloatingWidget( QWidget* parent /TransferThis/ = nullptr );
35+
36+
/** Sets the widget to "anchor" the floating widget to. The floating widget will be repositioned whenever the
37+
* anchor widget moves or is resized so that it maintains the same relative position to the anchor widget.
38+
* @param widget anchor widget. Both the floating widget and the anchor widget must share some common parent.
39+
* @see anchorWidget()
40+
*/
41+
void setAnchorWidget( QWidget* widget );
42+
43+
/** Returns the widget that the floating widget is "anchored" tto. The floating widget will be repositioned whenever the
44+
* anchor widget moves or is resized so that it maintains the same relative position to the anchor widget.
45+
* @see setAnchorWidget()
46+
*/
47+
QWidget* anchorWidget();
48+
49+
/** Returns the floating widget's anchor point, which corresponds to the point on the widget which should remain
50+
* fixed in the same relative position whenever the widget's parent is resized or moved.
51+
* @see setAnchorPoint()
52+
*/
53+
AnchorPoint anchorPoint() const;
54+
55+
/** Sets the floating widget's anchor point, which corresponds to the point on the widget which should remain
56+
* fixed in the same relative position whenever the widget's parent is resized or moved.
57+
* @param point anchor point
58+
* @see anchorPoint()
59+
*/
60+
void setAnchorPoint( AnchorPoint point );
61+
62+
/** Returns the anchor widget's anchor point, which corresponds to the point on the anchor widget which
63+
* the floating widget should "attach" to. The floating widget should remain fixed in the same relative position
64+
* to this anchor widget whenever the widget's parent is resized or moved.
65+
* @see setAnchorWidgetPoint()
66+
*/
67+
AnchorPoint anchorWidgetPoint() const;
68+
69+
/** Returns the anchor widget's anchor point, which corresponds to the point on the anchor widget which
70+
* the floating widget should "attach" to. The floating widget should remain fixed in the same relative position
71+
* to this anchor widget whenever the widget's parent is resized or moved.
72+
* @see setAnchorWidgetPoint()
73+
*/
74+
void setAnchorWidgetPoint( AnchorPoint point );
75+
76+
protected:
77+
void showEvent( QShowEvent* e );
78+
virtual void paintEvent( QPaintEvent* e );
79+
80+
};

python/gui/qgstaskmanagerwidget.sip

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,50 @@ class QgsTaskManagerWidget : QWidget
1919

2020
};
2121

22+
/** \ingroup gui
23+
* \class QgsTaskManagerFloatingWidget
24+
* A widget which displays tasks from a QgsTaskManager and allows for interaction with the manager
25+
* @see QgsTaskManager
26+
* @note introduced in QGIS 2.16
27+
*/
28+
class QgsTaskManagerFloatingWidget : QgsFloatingWidget
29+
{
30+
%TypeHeaderCode
31+
#include <qgstaskmanagerwidget.h>
32+
%End
33+
34+
public:
35+
36+
/** Constructor for QgsTaskManagerWidget
37+
* @param manager task manager associated with widget
38+
* @param parent parent widget
39+
*/
40+
QgsTaskManagerFloatingWidget( QgsTaskManager* manager, QWidget* parent = nullptr );
41+
42+
};
43+
44+
/** \ingroup gui
45+
* \class QgsTaskManagerFloatingWidget
46+
* A widget which displays tasks from a QgsTaskManager and allows for interaction with the manager
47+
* @see QgsTaskManager
48+
* @note introduced in QGIS 2.16
49+
*/
50+
class QgsTaskManagerStatusBarWidget : QToolButton
51+
{
52+
%TypeHeaderCode
53+
#include <qgstaskmanagerwidget.h>
54+
%End
55+
56+
public:
57+
58+
/** Constructor for QgsTaskManagerStatusBarWidget
59+
* @param manager task manager associated with widget
60+
* @param parent parent widget
61+
*/
62+
QgsTaskManagerStatusBarWidget( QgsTaskManager* manager, QWidget* parent = nullptr );
63+
64+
};
65+
2266

2367
/** \ingroup gui
2468
* \class QgsTaskManagerModel

src/app/qgisapp.cpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -853,13 +853,6 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
853853
QMainWindow::addDockWidget( Qt::BottomDockWidgetArea, mUserInputDockWidget );
854854
mUserInputDockWidget->setFloating( true );
855855

856-
// create the task manager dock on starting QGIS - this is like the browser
857-
mTaskManagerDock = new QDockWidget( tr( "Task Manager" ), this );
858-
mTaskManagerDock->setObjectName( "TaskManager" );
859-
addDockWidget( Qt::RightDockWidgetArea, mTaskManagerDock );
860-
mTaskManagerDock->setWidget( new QgsTaskManagerWidget( QgsTaskManager::instance(), mTaskManagerDock ) );
861-
mTaskManagerDock->hide();
862-
863856
// create the GPS tool on starting QGIS - this is like the browser
864857
mpGpsWidget = new QgsGPSInformationWidget( mMapCanvas );
865858
//create the dock widget
@@ -1148,8 +1141,8 @@ QgisApp::QgisApp()
11481141
, mOverviewDock( nullptr )
11491142
, mpGpsDock( nullptr )
11501143
, mLogDock( nullptr )
1151-
, mTaskManagerDock( nullptr )
11521144
, mNonEditMapTool( nullptr )
1145+
, mTaskManagerWidget( nullptr )
11531146
, mScaleWidget( nullptr )
11541147
, mMagnifierWidget( nullptr )
11551148
, mCoordsEdit( nullptr )

src/app/qgisapp.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ class QgsSnappingWidget;
7878
class QgsStatusBarCoordinatesWidget;
7979
class QgsStatusBarMagnifierWidget;
8080
class QgsStatusBarScaleWidget;
81+
class QgsTaskManagerStatusBarWidget;
8182
class QgsTransactionGroup;
8283
class QgsUndoWidget;
8384
class QgsUserInputDockWidget;
@@ -1560,7 +1561,6 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
15601561
QgsDockWidget *mOverviewDock;
15611562
QgsDockWidget *mpGpsDock;
15621563
QgsDockWidget *mLogDock;
1563-
QDockWidget *mTaskManagerDock;
15641564

15651565
#ifdef Q_OS_MAC
15661566
//! Window menu action to select this window
@@ -1673,6 +1673,8 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
16731673

16741674
QgsMapTool *mNonEditMapTool;
16751675

1676+
QgsTaskManagerStatusBarWidget* mTaskManagerWidget;
1677+
16761678
QgsStatusBarScaleWidget* mScaleWidget;
16771679

16781680
//! zoom widget

src/core/qgstaskmanager.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ QStringList QgsTaskManager::dependentLayers( long taskId ) const
312312

313313
void QgsTaskManager::taskProgressChanged( double progress )
314314
{
315+
QMutexLocker ml( mTaskMutex );
315316
QgsTask* task = qobject_cast< QgsTask* >( sender() );
316317

317318
//find ID of task
@@ -320,6 +321,10 @@ void QgsTaskManager::taskProgressChanged( double progress )
320321
return;
321322

322323
emit progressChanged( id, progress );
324+
if ( mActiveTasks.count() == 1 )
325+
{
326+
emit progressChanged( progress );
327+
}
323328
}
324329

325330
void QgsTaskManager::taskStatusChanged( int status )
@@ -393,13 +398,29 @@ bool QgsTaskManager::cleanupAndDeleteTask( QgsTask *task )
393398
void QgsTaskManager::processQueue()
394399
{
395400
QMutexLocker ml( mTaskMutex );
401+
int prevActiveCount = mActiveTasks.count();
402+
mActiveTasks.clear();
396403
for ( QMap< long, TaskInfo >::iterator it = mTasks.begin(); it != mTasks.end(); ++it )
397404
{
398405
QgsTask* task = it.value().task;
399406
if ( task && task->status() == QgsTask::Queued && dependenciesSatisified( taskId( task ) ) )
400407
{
401408
mTasks[ it.key()].future = QtConcurrent::run( task, &QgsTask::start );
402409
}
410+
411+
if ( task && ( task->status() != QgsTask::Complete && task->status() != QgsTask::Terminated ) )
412+
{
413+
mActiveTasks << task;
414+
}
415+
}
416+
417+
if ( mActiveTasks.isEmpty() )
418+
{
419+
emit allTasksFinished();
420+
}
421+
if ( prevActiveCount != mActiveTasks.count() )
422+
{
423+
emit countActiveTasksChanged( mActiveTasks.count() );
403424
}
404425
}
405426

src/core/qgstaskmanager.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,13 +266,29 @@ class CORE_EXPORT QgsTaskManager : public QObject
266266
*/
267267
QStringList dependentLayers( long taskId ) const;
268268

269+
/** Returns a list of the active (queued or running) tasks.
270+
* @see countActiveTasks()
271+
*/
272+
QList< QgsTask* > activeTasks() const { return mActiveTasks; }
273+
274+
/** Returns the number of active (queued or running) tasks.
275+
* @see activeTasks()
276+
* @see countActiveTasksChanged()
277+
*/
278+
int countActiveTasks() const { return mActiveTasks.count(); }
279+
269280
signals:
270281

271282
//! Will be emitted when a task reports a progress change
272283
//! @param taskId ID of task
273284
//! @param progress percent of progress, from 0.0 - 100.0
274285
void progressChanged( long taskId, double progress );
275286

287+
//! Will be emitted when only a single task remains to complete
288+
//! and that task has reported a progress change
289+
//! @param progress percent of progress, from 0.0 - 100.0
290+
void progressChanged( double progress );
291+
276292
//! Will be emitted when a task reports a status change
277293
//! @param taskId ID of task
278294
//! @param status new task status
@@ -286,6 +302,14 @@ class CORE_EXPORT QgsTaskManager : public QObject
286302
//! @param taskId ID of task
287303
void taskAboutToBeDeleted( long taskId );
288304

305+
//! Emitted when all tasks are complete
306+
//! @see countActiveTasksChanged()
307+
void allTasksFinished();
308+
309+
//! Emitted when the number of active tasks changes
310+
//! @see countActiveTasks()
311+
void countActiveTasksChanged( int count );
312+
289313
private slots:
290314

291315
void taskProgressChanged( double progress );
@@ -313,6 +337,9 @@ class CORE_EXPORT QgsTaskManager : public QObject
313337
//! Tracks the next unique task ID
314338
long mNextTaskId;
315339

340+
//! List of active (queued or running) tasks
341+
QList< QgsTask* > mActiveTasks;
342+
316343
bool cleanupAndDeleteTask( QgsTask* task );
317344

318345
//! Process the queue of outstanding jobs and starts up any

src/gui/qgsfloatingwidget.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515

1616
#include "qgsfloatingwidget.h"
1717
#include <QEvent>
18-
18+
#include <QStyleOption>
19+
#include <QPainter>
1920

2021
//
2122
// QgsFloatingWidget
@@ -69,6 +70,15 @@ void QgsFloatingWidget::showEvent( QShowEvent *e )
6970
QWidget::showEvent( e );
7071
}
7172

73+
void QgsFloatingWidget::paintEvent( QPaintEvent* e )
74+
{
75+
Q_UNUSED( e );
76+
QStyleOption opt;
77+
opt.init( this );
78+
QPainter p( this );
79+
style()->drawPrimitive( QStyle::PE_Widget, &opt, &p, this );
80+
}
81+
7282
void QgsFloatingWidget::anchorPointChanged()
7383
{
7484
if ( mAnchorWidget )

src/gui/qgsfloatingwidget.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ class GUI_EXPORT QgsFloatingWidget: public QWidget
4646
BottomRight, //!< Bottom-right of widget
4747
};
4848

49+
/** Constructor for QgsFloatingWidget.
50+
* @param parent parent widget
51+
*/
4952
QgsFloatingWidget( QWidget* parent = nullptr );
5053

5154
/** Sets the widget to "anchor" the floating widget to. The floating widget will be repositioned whenever the
@@ -90,6 +93,7 @@ class GUI_EXPORT QgsFloatingWidget: public QWidget
9093

9194
protected:
9295
void showEvent( QShowEvent* e ) override;
96+
virtual void paintEvent( QPaintEvent* e ) override;
9397

9498
private slots:
9599

0 commit comments

Comments
 (0)