diff --git a/doc/api/qtcreator-api.qdoc b/doc/api/qtcreator-api.qdoc index b1760846ffe7e53f0ecc81c658ac33b1994bcdf0..aca770d8b7b118a715642e42ee274ae5477b9b3d 100644 --- a/doc/api/qtcreator-api.qdoc +++ b/doc/api/qtcreator-api.qdoc @@ -164,6 +164,12 @@ \o For a text typed in by the user you provide a list of things to show in the popup. When the user selects an entry you are requested to do whatever you want. \o \l{Locator::ILocatorFilter}, \l{Locator::FilterEntry}, \l{Locator::BaseFileFilter} + \row + \o Show a progress indicator for a concurrently running task. + \o You can show a progress indicator for your tasks in the left hand tool bar, + and also in the application icon (on platforms that support it). + \o \l{Core::ProgressManager}, \l{Core::FutureProgress} + \row \o \o diff --git a/src/plugins/coreplugin/progressmanager/progressmanager.cpp b/src/plugins/coreplugin/progressmanager/progressmanager.cpp index fce083bf60ed3c53c48d13632b6b97376040f8b9..93b963920c8a0335d371b73a5386bf031d4aae59 100644 --- a/src/plugins/coreplugin/progressmanager/progressmanager.cpp +++ b/src/plugins/coreplugin/progressmanager/progressmanager.cpp @@ -39,6 +39,199 @@ using namespace Core; using namespace Core::Internal; +/*! + \mainclass + \class Core::ProgressManager + \brief The ProgressManager class is used to show a user interface + for running tasks in Qt Creator. + + It tracks the progress of a task that it is told + about, and shows a progress indicator in the left hand tool bar + of Qt Creator's main window to the user. + The progress indicator also allows the user to cancel the task. + + You get the single instance of this class via the + Core::ICore::progressManager() method. + + \section1 Registering a task + The ProgressManager API uses QtConcurrent as the basis for defining + tasks. A task consists of the following properties: + + \table + \header + \o Property + \o Type + \o Description + \row + \o Task abstraction + \o \c QFuture<void> + \o A \c QFuture object that represents the task which is + responsible for reporting the state of the task. See below + for coding patterns how to create this object for your + specific task. + \row + \o Title + \o \c QString + \o A very short title describing your task. This is shown + as a title over the progress bar. + \row + \o Type + \o \c QString + \o A string identifier that is used to group different tasks that + belong together. + For example, all the search operations use the same type + identifier. + \row + \o Flags + \o \l ProgressManager::ProgressFlags + \o Additional flags that specify how the progress bar should + be presented to the user. + \endtable + + To register a task you create your \c QFuture<void> object, and call + addTask(). This method returns a + \l{Core::FutureProgress}{FutureProgress} + object that you can use to further customize the progress bar's appearance. + See the \l{Core::FutureProgress}{FutureProgress} documentation for + details. + + In the following you will learn about two common patterns how to + create the \c QFuture<void> object for your task. + + \section2 Create a threaded task with QtConcurrent + The first option is to directly use QtConcurrent to actually + start a task concurrently in a different thread. + QtConcurrent has several different methods to run e.g. + a class method in a different thread. Qt Creator itself + adds a few more in \c{src/libs/qtconcurrent/runextensions.h}. + The QtConcurrent methods to run a concurrent task return a + \c QFuture object. This is what you want to give the + ProgressManager in the addTask() method. + + Have a look at e.g Locator::ILocatorFilter. Locator filters implement + a method \c refresh which takes a \c QFutureInterface object + as a parameter. These methods look something like: + \code + void Filter::refresh(QFutureInterface<void> &future) { + future.setProgressRange(0, MAX); + ... + while (!future.isCanceled()) { + // Do a part of the long stuff + ... + future.setProgressValue(currentProgress); + ... + } + } + \endcode + + The actual refresh, which calls all the filters' refresh methods + in a different thread, looks like this: + \code + QFuture<void> task = QtConcurrent::run(&ILocatorFilter::refresh, filters); + Core::FutureProgress *progress = Core::ICore::instance() + ->progressManager()->addTask(task, tr("Indexing"), + Locator::Constants::TASK_INDEX); + \endcode + First, we tell QtConcurrent to start a thread which calls all the filters' + refresh method. After that we register the returned QFuture object + with the ProgressManager. + + \section2 Manually create QtConcurrent objects for your thread + If your task has its own means to create and run a thread, + you need to create the necessary objects yourselves, and + report the start/stop state. + + \code + // We are already running in a different thread here + QFutureInterface<void> *progressObject = new QFutureInterface<void>; + progressObject->setProgressRange(0, MAX); + Core::ICore::instance()->progressManager()->addTask( + progressObject->future(), + tr("DoIt"), MYTASKTYPE); + progressObject->reportStarted(); + // Do something + ... + progressObject->setProgressValue(currentProgress); + ... + // We have done what we needed to do + progressObject->reportFinished(); + delete progressObject; + \endcode + In the first line we create the QFutureInterface object that will be + our way for reporting the task's state. + The first thing we report is the expected range of the progress values. + We register the task with the ProgressManager, using the internal + QFuture object that has been created for our QFutureInterface object. + Next we report that the task has begun and start doing our actual + work, regularly reporting the progress via the methods + in QFutureInterface. After the long taking operation has finished, + we report so through the QFutureInterface object, and delete it + afterwards. +*/ + +/*! + \enum Core::ProgressManager::ProgressFlag + Additional flags that specify details in behavior. The + default for a task is to not have any of these flags set. + \value KeepOnFinish + The progress indicator stays visible after the task has finished. + \value ShowInApplicationIcon + The progress indicator for this task is additionally + shown in the application icon in the system's task bar or dock, on + platforms that support that (at the moment Windows 7 and Mac OS X). +*/ + +/*! + \fn Core::ProgressManager::ProgressManager(QObject *parent = 0) + \internal +*/ + +/*! + \fn Core::ProgressManager::~ProgressManager() + \internal +*/ + +/*! + \fn FutureProgress *Core::ProgressManager::addTask(const QFuture<void> &future, const QString &title, const QString &type, ProgressFlags flags = 0) + + Shows a progress indicator for the given task. + The progress indicator shows the specified \a title along with the progress bar. + The \a type of a task will specify a logical grouping with other + running tasks. Via the \a flags parameter you can e.g. let the + progress indicator stay visible after the task has finished. + Returns an object that represents the created progress indicator, + which can be used to further customize. +*/ + +/*! + \fn void Core::ProgressManager::setApplicationLabel(const QString &text) + + Shows the given \a text in a platform dependent way in the application + icon in the system's task bar or dock. This is used + to show the number of build errors on Windows 7 and Mac OS X. +*/ + +/*! + \fn void Core::ProgressManager::cancelTasks(const QString &type) + + Schedules a cancel for all running tasks of the given \a type. + Please note that the cancel functionality depends on the + running task to actually check the \c QFutureInterface::isCanceled + property. +*/ + +/*! + \fn void Core::ProgressManager::taskStarted(const QString &type) + + Sent whenever a task of a given \a type is started. +*/ + +/*! + \fn void Core::ProgressManager::allTasksFinished(const QString &type) + + Sent when all tasks of a \a type have finished. +*/ + ProgressManagerPrivate::ProgressManagerPrivate(QObject *parent) : ProgressManager(parent), m_applicationTask(0)