Commit 90c03d32 authored by con's avatar con

Add functionality to show progress for the application in task bar/dock.

Move the API to the progress manager.
Added a first Mac implementation, other
platforms are pending.
parent 4688634f
......@@ -165,7 +165,17 @@ FORMS += dialogs/newdialog.ui \
generalsettings.ui
RESOURCES += core.qrc \
fancyactionbar.qrc
unix:!macx {
win32 {
SOURCES += progressmanager/progressmanager_win.cpp
}
else:macx {
OBJECTIVE_SOURCES += progressmanager/progressmanager_mac.mm
LIBS += -framework AppKit
}
else:unix {
SOURCES += progressmanager/progressmanager_x11.cpp
images.files = images/qtcreator_logo_*.png
images.path = /share/pixmaps
INSTALLS += images
......
......@@ -40,7 +40,8 @@ using namespace Core;
using namespace Core::Internal;
ProgressManagerPrivate::ProgressManagerPrivate(QObject *parent)
: ProgressManager(parent)
: ProgressManager(parent),
m_applicationTask(0)
{
m_progressView = new ProgressView;
ICore *core = ICore::instance();
......@@ -66,6 +67,8 @@ void ProgressManagerPrivate::cancelTasks(const QString &type)
}
found = true;
disconnect(task.key(), SIGNAL(finished()), this, SLOT(taskFinished()));
if (m_applicationTask == task.key())
disconnectApplicationTask();
task.key()->cancel();
delete task.key();
task = m_runningTasks.erase(task);
......@@ -80,6 +83,8 @@ void ProgressManagerPrivate::cancelAllRunningTasks()
QMap<QFutureWatcher<void> *, QString>::const_iterator task = m_runningTasks.constBegin();
while (task != m_runningTasks.constEnd()) {
disconnect(task.key(), SIGNAL(finished()), this, SLOT(taskFinished()));
if (m_applicationTask == task.key())
disconnectApplicationTask();
task.key()->cancel();
delete task.key();
++task;
......@@ -87,14 +92,23 @@ void ProgressManagerPrivate::cancelAllRunningTasks()
m_runningTasks.clear();
}
FutureProgress *ProgressManagerPrivate::addTask(const QFuture<void> &future, const QString &title, const QString &type, PersistentType persistency)
FutureProgress *ProgressManagerPrivate::addTask(const QFuture<void> &future, const QString &title,
const QString &type, ProgressFlags flags)
{
QFutureWatcher<void> *watcher = new QFutureWatcher<void>();
m_runningTasks.insert(watcher, type);
connect(watcher, SIGNAL(finished()), this, SLOT(taskFinished()));
if (flags & ShowInApplicationIcon) {
m_applicationTask = watcher;
connect(m_applicationTask, SIGNAL(progressRangeChanged(int,int)),
this, SLOT(setApplicationProgressRange(int,int)));
connect(m_applicationTask, SIGNAL(progressValueChanged(int)),
this, SLOT(setApplicationProgressValue(int)));
setApplicationProgressVisible(true);
}
watcher->setFuture(future);
emit taskStarted(type);
return m_progressView->addTask(future, title, type, persistency);
return m_progressView->addTask(future, title, type, flags);
}
QWidget *ProgressManagerPrivate::progressView()
......@@ -107,6 +121,8 @@ void ProgressManagerPrivate::taskFinished()
QObject *taskObject = sender();
QTC_ASSERT(taskObject, return);
QFutureWatcher<void> *task = static_cast<QFutureWatcher<void> *>(taskObject);
if (m_applicationTask == task)
disconnectApplicationTask();
QString type = m_runningTasks.value(task);
m_runningTasks.remove(task);
delete task;
......@@ -115,3 +131,13 @@ void ProgressManagerPrivate::taskFinished()
emit allTasksFinished(type);
}
}
void ProgressManagerPrivate::disconnectApplicationTask()
{
disconnect(m_applicationTask, SIGNAL(progressRangeChanged(int,int)),
this, SLOT(setApplicationProgressRange(int,int)));
disconnect(m_applicationTask, SIGNAL(progressValueChanged(int)),
this, SLOT(setApplicationProgressValue(int)));
setApplicationProgressVisible(false);
m_applicationTask = 0;
}
......@@ -42,12 +42,18 @@ class CORE_EXPORT ProgressManager : public QObject
{
Q_OBJECT
public:
enum PersistentType { CloseOnSuccess, KeepOnFinish };
enum ProgressFlag {
KeepOnFinish = 0x01,
ShowInApplicationIcon = 0x02
};
Q_DECLARE_FLAGS(ProgressFlags, ProgressFlag)
ProgressManager(QObject *parent = 0) : QObject(parent) {}
virtual ~ProgressManager() {}
virtual FutureProgress *addTask(const QFuture<void> &future, const QString &title, const QString &type, PersistentType persistency = KeepOnFinish) = 0;
virtual FutureProgress *addTask(const QFuture<void> &future, const QString &title,
const QString &type, ProgressFlags flags = 0) = 0;
virtual void setApplicationLabel(const QString &text) = 0;
public slots:
virtual void cancelTasks(const QString &type) = 0;
......@@ -59,4 +65,6 @@ signals:
} // namespace Core
Q_DECLARE_OPERATORS_FOR_FLAGS(Core::ProgressManager::ProgressFlags)
#endif //PROGRESSMANAGER_H
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#include "progressmanager_p.h"
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
#import <AppKit/NSDockTile.h>
#import <AppKit/NSApplication.h>
#import <AppKit/NSImageView.h>
#import <Foundation/NSString.h>
@interface ApplicationProgressView : NSView {
int min;
int max;
int value;
}
+ (ApplicationProgressView *)sharedProgressView;
- (void)setRangeMin:(int)v1 max:(int)v2;
- (void)setValue:(int)v;
- (void)updateBadge;
@end
static ApplicationProgressView *sharedProgressView = nil;
@implementation ApplicationProgressView
+ (ApplicationProgressView *)sharedProgressView
{
if (sharedProgressView == nil) {
sharedProgressView = [[ApplicationProgressView alloc] init];
}
return sharedProgressView;
}
- (void)setRangeMin:(int)v1 max:(int)v2
{
min = v1;
max = v2;
[self updateBadge];
}
- (void)setValue:(int)v
{
value = v;
[self updateBadge];
}
- (void)updateBadge
{
[[NSApp dockTile] display];
}
- (void)drawRect:(NSRect)rect
{
NSRect boundary = [self bounds];
[[NSApp applicationIconImage] drawInRect:boundary
fromRect:NSZeroRect
operation:NSCompositeCopy
fraction:1.0];
NSRect progressBoundary = boundary;
progressBoundary.size.height *= 0.13;
progressBoundary.size.width *= 0.8;
progressBoundary.origin.x = (NSWidth(boundary) - NSWidth(progressBoundary))/2.;
progressBoundary.origin.y = NSHeight(boundary)*0.13;
double range = max - min;
double percent = 0.50;
if (range != 0)
percent = (value - min) / range;
if (percent > 1)
percent = 1;
else if (percent < 0)
percent = 0;
NSRect currentProgress = progressBoundary;
currentProgress.size.width *= percent;
[[NSColor blackColor] setFill];
[NSBezierPath fillRect:progressBoundary];
[[NSColor lightGrayColor] setFill];
[NSBezierPath fillRect:currentProgress];
[[NSColor blackColor] setStroke];
[NSBezierPath strokeRect:progressBoundary];
}
@end
void Core::Internal::ProgressManagerPrivate::setApplicationLabel(const QString &text)
{
const char *utf8String = text.toUtf8().constData();
NSString *cocoaString = [[NSString alloc] initWithUTF8String:utf8String];
[[NSApp dockTile] setBadgeLabel:cocoaString];
[cocoaString release];
}
void Core::Internal::ProgressManagerPrivate::setApplicationProgressRange(int min, int max)
{
[[ApplicationProgressView sharedProgressView] setRangeMin:min max:max];
}
void Core::Internal::ProgressManagerPrivate::setApplicationProgressValue(int value)
{
[[ApplicationProgressView sharedProgressView] setValue:value];
}
void Core::Internal::ProgressManagerPrivate::setApplicationProgressVisible(bool visible)
{
if (visible) {
[[NSApp dockTile] setContentView:[ApplicationProgressView sharedProgressView]];
} else {
[[NSApp dockTile] setContentView:nil];
}
[[NSApp dockTile] display];
}
#else
void Core::Internal::ProgressManagerPrivate::setApplicationLabel(const QString &text)
{
Q_UNUSED(text)
}
void Core::Internal::ProgressManagerPrivate::setApplicationProgressRange(int min, int max)
{
Q_UNUSED(min)
Q_UNUSED(max)
}
void Core::Internal::ProgressManagerPrivate::setApplicationProgressValue(int value)
{
Q_UNUSED(value)
}
void Core::Internal::ProgressManagerPrivate::setApplicationProgressVisible(bool visible)
{
Q_UNUSED(visible)
}
#endif
......@@ -49,8 +49,10 @@ public:
~ProgressManagerPrivate();
void init();
FutureProgress *addTask(const QFuture<void> &future, const QString &title, const QString &type, PersistentType persistency);
FutureProgress *addTask(const QFuture<void> &future, const QString &title, const QString &type,
ProgressFlags flags);
void setApplicationLabel(const QString &text);
QWidget *progressView();
public slots:
......@@ -59,9 +61,15 @@ public slots:
private slots:
void taskFinished();
void cancelAllRunningTasks();
void setApplicationProgressRange(int min, int max);
void setApplicationProgressValue(int value);
void setApplicationProgressVisible(bool visible);
void disconnectApplicationTask();
private:
QPointer<ProgressView> m_progressView;
QMap<QFutureWatcher<void> *, QString> m_runningTasks;
QFutureWatcher<void> *m_applicationTask;
};
} // namespace Internal
......
......@@ -27,15 +27,25 @@
**
**************************************************************************/
#ifndef BUILDPROGRESS_MAC_H
#define BUILDPROGRESS_MAC_H
#include "progressmanager_p.h"
#include <QtCore/QString>
void Core::Internal::ProgressManagerPrivate::setApplicationLabel(const QString &text)
{
Q_UNUSED(text)
}
void Core::Internal::ProgressManagerPrivate::setApplicationProgressRange(int min, int max)
{
Q_UNUSED(min)
Q_UNUSED(max)
}
namespace ProjectExplorer {
namespace Internal {
void qtcShowDockTileBadgeLabel(const QString &text);
}
void Core::Internal::ProgressManagerPrivate::setApplicationProgressValue(int value)
{
Q_UNUSED(value)
}
#endif
void Core::Internal::ProgressManagerPrivate::setApplicationProgressVisible(bool visible)
{
Q_UNUSED(visible)
}
......@@ -27,22 +27,25 @@
**
**************************************************************************/
#include "buildprogress_mac.h"
#include "progressmanager_p.h"
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
#include <AppKit/NSDockTile.h>
#include <AppKit/NSApplication.h>
#include <Foundation/NSString.h>
#endif
void ProjectExplorer::Internal::qtcShowDockTileBadgeLabel(const QString &text)
void Core::Internal::ProgressManagerPrivate::setApplicationLabel(const QString &text)
{
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
const char *utf8String = text.toUtf8().constData();
NSString *cocoaString = [[NSString alloc] initWithUTF8String:utf8String];
[[NSApp dockTile] setBadgeLabel:cocoaString];
[cocoaString release];
#else
Q_UNUSED(text)
#endif
}
void Core::Internal::ProgressManagerPrivate::setApplicationProgressRange(int min, int max)
{
Q_UNUSED(min)
Q_UNUSED(max)
}
void Core::Internal::ProgressManagerPrivate::setApplicationProgressValue(int value)
{
Q_UNUSED(value)
}
void Core::Internal::ProgressManagerPrivate::setApplicationProgressVisible(bool visible)
{
Q_UNUSED(visible)
}
......@@ -58,7 +58,7 @@ ProgressView::~ProgressView()
FutureProgress *ProgressView::addTask(const QFuture<void> &future,
const QString &title,
const QString &type,
ProgressManager::PersistentType persistency)
ProgressManager::ProgressFlags flags)
{
removeOldTasks(type);
if (m_taskList.size() == 3)
......@@ -69,7 +69,7 @@ FutureProgress *ProgressView::addTask(const QFuture<void> &future,
m_layout->insertWidget(0, progress);
m_taskList.append(progress);
m_type.insert(progress, type);
m_keep.insert(progress, (persistency == ProgressManager::KeepOnFinish));
m_keep.insert(progress, (flags & ProgressManager::KeepOnFinish));
connect(progress, SIGNAL(finished()), this, SLOT(slotFinished()));
return progress;
}
......
......@@ -55,7 +55,7 @@ public:
FutureProgress *addTask(const QFuture<void> &future,
const QString &title,
const QString &type,
ProgressManager::PersistentType persistency);
ProgressManager::ProgressFlags flags);
private slots:
void slotFinished();
......
......@@ -233,8 +233,7 @@ void CppFindReferences::findAll_helper(Symbol *symbol)
m_watcher.setFuture(result);
Core::FutureProgress *progress = progressManager->addTask(result, tr("Searching..."),
CppTools::Constants::TASK_SEARCH,
Core::ProgressManager::CloseOnSuccess);
CppTools::Constants::TASK_SEARCH);
connect(progress, SIGNAL(clicked()), _resultWindow, SLOT(popup()));
}
......
......@@ -857,8 +857,7 @@ void CppModelManager::updateProjectInfo(const ProjectInfo &pinfo)
if (pinfo.includePaths.size() > 1) {
m_core->progressManager()->addTask(result, tr("Scanning"),
CppTools::Constants::TASK_INDEX,
Core::ProgressManager::CloseOnSuccess);
CppTools::Constants::TASK_INDEX);
}
}
}
......@@ -899,8 +898,7 @@ QFuture<void> CppModelManager::refreshSourceFiles(const QStringList &sourceFiles
if (sourceFiles.count() > 1) {
m_core->progressManager()->addTask(result, tr("Indexing"),
CppTools::Constants::TASK_INDEX,
Core::ProgressManager::CloseOnSuccess);
CppTools::Constants::TASK_INDEX);
}
return result;
}
......
......@@ -109,8 +109,7 @@ void GitCommand::execute()
const QString taskName = QLatin1String("Git ") + m_jobs.front().arguments.at(0);
Core::ICore::instance()->progressManager()->addTask(task, taskName,
QLatin1String("Git.action"),
Core::ProgressManager::CloseOnSuccess);
QLatin1String("Git.action"));
}
void GitCommand::run()
......
......@@ -245,8 +245,7 @@ void LocatorPlugin::refresh(QList<ILocatorFilter*> filters)
QFuture<void> task = QtConcurrent::run(&ILocatorFilter::refresh, filters);
Core::FutureProgress *progress = Core::ICore::instance()
->progressManager()->addTask(task, tr("Indexing"),
Locator::Constants::TASK_INDEX,
Core::ProgressManager::CloseOnSuccess);
Locator::Constants::TASK_INDEX);
connect(progress, SIGNAL(finished()), this, SLOT(saveSettings()));
}
......
......@@ -53,6 +53,8 @@
#include <QtGui/QHeaderView>
#include <QtGui/QIcon>
#include <QtGui/QLabel>
#include <QtGui/QApplication>
#include <QtGui/QMainWindow>
using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;
......@@ -91,10 +93,12 @@ BuildManager::BuildManager(ProjectExplorerPlugin *parent)
m_taskWindow->addCategory(Constants::TASK_CATEGORY_BUILDSYSTEM, tr("Buildsystem", "Category for build system isses listened under 'Build Issues'"));
connect(m_taskWindow, SIGNAL(tasksChanged()),
this, SIGNAL(tasksChanged()));
this, SLOT(updateTaskCount()));
connect(&m_progressWatcher, SIGNAL(canceled()),
this, SLOT(cancel()));
connect(&m_progressWatcher, SIGNAL(finished()),
this, SLOT(finish()));
}
BuildManager::~BuildManager()
......@@ -140,6 +144,23 @@ void BuildManager::cancel()
return;
}
void BuildManager::updateTaskCount()
{
Core::ProgressManager *progressManager = Core::ICore::instance()->progressManager();
int errors = m_taskWindow->errorTaskCount();
if (errors > 0) {
progressManager->setApplicationLabel(QString("%1").arg(errors));
} else {
progressManager->setApplicationLabel("");
}
emit tasksChanged();
}
void BuildManager::finish()
{
QApplication::alert(Core::ICore::instance()->mainWindow(), 3000);
}
void BuildManager::emitCancelMessage()
{
emit addToOutputWindow(tr("<font color=\"#ff0000\">Canceled build.</font>"));
......@@ -201,9 +222,11 @@ void BuildManager::startBuildQueue()
Core::ProgressManager *progressManager = Core::ICore::instance()->progressManager();
m_progressFutureInterface = new QFutureInterface<void>;
m_progressWatcher.setFuture(m_progressFutureInterface->future());
progressManager->setApplicationLabel("");
Core::FutureProgress *progress = progressManager->addTask(m_progressFutureInterface->future(),
tr("Build"),
Constants::TASK_BUILD);
tr("Build"),
Constants::TASK_BUILD,
Core::ProgressManager::KeepOnFinish | Core::ProgressManager::ShowInApplicationIcon);
connect(progress, SIGNAL(clicked()), this, SLOT(showBuildResults()));
progress->setWidget(new BuildProgress(m_taskWindow));
m_progress = 0;
......
......@@ -99,6 +99,8 @@ private slots:
void progressChanged();
void emitCancelMessage();
void showBuildResults();
void updateTaskCount();
void finish();
private:
void startBuildQueue();
......
......@@ -37,10 +37,6 @@
#include <QtGui/QPixmap>
#include <QtDebug>
#ifdef Q_OS_MAC
#include "buildprogress_mac.h"
#endif
using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;
......@@ -98,10 +94,4 @@ void BuildProgress::updateState()
m_warningIcon->setEnabled(haveWarnings);
m_warningLabel->setEnabled(haveWarnings);
m_warningLabel->setText(QString("%1").arg(warnings));
#ifdef Q_OS_MAC
if (haveErrors)
qtcShowDockTileBadgeLabel(QString("%1").arg(errors));
else
qtcShowDockTileBadgeLabel("");
#endif
}
......@@ -131,20 +131,21 @@ FORMS += processstep.ui \
removefiledialog.ui \
projectexplorersettingspage.ui \
projectwelcomepagewidget.ui
win32 {
SOURCES += applicationlauncher_win.cpp \
winguiprocess.cpp
HEADERS += winguiprocess.h
}
else:unix:SOURCES += applicationlauncher_x11.cpp
macx {
HEADERS += buildprogress_mac.h
OBJECTIVE_SOURCES += buildprogress_mac.mm
LIBS += -framework Carbon -framework AppKit
else:macx {
SOURCES += applicationlauncher_x11.cpp
LIBS += -framework \
Carbon
}
else:unix {
SOURCES += applicationlauncher_x11.cpp
}
RESOURCES += projectexplorer.qrc
DEFINES += PROJECTEXPLORER_LIBRARY
OTHER_FILES += ProjectExplorer.pluginspec
......@@ -155,8 +155,7 @@ bool SessionFile::load(const QString &fileName)
}
m_core->progressManager()->addTask(future.future(), tr("Session"),
QLatin1String("ProjectExplorer.SessionFile.Load"),
Core::ProgressManager::CloseOnSuccess);
QLatin1String("ProjectExplorer.SessionFile.Load"));
const QStringList &keys = reader.restoreValue(QLatin1String("valueKeys")).toStringList();
foreach (const QString &key, keys) {
......
......@@ -97,8 +97,7 @@ QFuture<void> QmlModelManager::refreshSourceFiles(const QStringList &sourceFiles
if (sourceFiles.count() > 1) {
m_core->progressManager()->addTask(result, tr("Indexing"),
QmlEditor::Constants::TASK_INDEX,
Core::ProgressManager::CloseOnSuccess);
QmlEditor::Constants::TASK_INDEX);
}
return result;
......
......@@ -289,8 +289,7 @@ void QtOptionsPageWidget::buildDebuggingHelper()
QFuture<void> task = QtConcurrent::run(&DebuggingHelperBuildTask::run, buildTask);
const QString taskName = tr("Building helpers");
Core::ICore::instance()->progressManager()->addTask(task, taskName,
QLatin1String("Qt4ProjectManager::BuildHelpers"),
Core::ProgressManager::CloseOnSuccess);
QLatin1String("Qt4ProjectManager::BuildHelpers"));
}
void QtOptionsPageWidget::showDebuggingBuildLog()
......
......@@ -101,9 +101,7 @@ void BaseFileFind::findAll(const QString &txt, QTextDocument::FindFlags findFlag
Core::FutureProgress *progress =
Core::ICore::instance()->progressManager()->addTask(m_watcher.future(),
"Search",
Constants::TASK_SEARCH,
Core::ProgressManager::CloseOnSuccess
);
Constants::TASK_SEARCH);
progress->setWidget(createProgressWidget());
connect(progress, SIGNAL(clicked()), m_resultWindow, SLOT(popup()));
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment