Skip to content

Commit

Permalink
Gui: added taskbar support (#766)
Browse files Browse the repository at this point in the history
Enables rendering progress in the taskbar icon on Windows and macOS.
  • Loading branch information
rodlie committed Feb 5, 2022
1 parent c0e9768 commit a34d684
Show file tree
Hide file tree
Showing 10 changed files with 515 additions and 3 deletions.
6 changes: 5 additions & 1 deletion Gui/Gui.pro
Expand Up @@ -203,6 +203,7 @@ SOURCES += \
TabGroup.cpp \
TabWidget.cpp \
TableModelView.cpp \
TaskBar.cpp \
TextRenderer.cpp \
TimeLineGui.cpp \
ToolButton.cpp \
Expand Down Expand Up @@ -347,6 +348,7 @@ HEADERS += \
TabGroup.h \
TabWidget.h \
TableModelView.h \
TaskBar.h \
TextRenderer.h \
TimeLineGui.h \
ToolButton.h \
Expand Down Expand Up @@ -411,6 +413,8 @@ OTHER_FILES += \
Resources/Images/splashscreen.svg

macx {
HEADERS += TaskBarMac.h
OBJECTIVE_SOURCES += \
$$PWD/../Gui/QtMac.mm
$$PWD/../Gui/QtMac.mm \
$$PWD/../Gui/TaskBarMac.mm
}
4 changes: 4 additions & 0 deletions Gui/ProgressPanel.cpp
Expand Up @@ -147,7 +147,10 @@ ProgressPanel::ProgressPanel(Gui* gui)
: QWidget(gui)
, PanelWidget(this, gui)
, _imp( new ProgressPanelPrivate() )
, _taskbar(0)
{
_taskbar = new TaskBar(this);

_imp->mainLayout = new QVBoxLayout(this);
_imp->mainLayout->setContentsMargins(0, 0, 0, 0);
_imp->mainLayout->setSpacing(0);
Expand Down Expand Up @@ -466,6 +469,7 @@ ProgressPanel::startTask(const NodePtr& node,
canCancel,
message, process) );

task->setTaskBar(_taskbar);

if ( canPause || node->getEffectInstance()->isOutput() ) {
task->createItems();
Expand Down
2 changes: 2 additions & 0 deletions Gui/ProgressPanel.h
Expand Up @@ -42,6 +42,7 @@ CLANG_DIAG_ON(uninitialized)
#include "Gui/PanelWidget.h"
#include "Gui/GuiFwd.h"

#include "Gui/TaskBar.h"

NATRON_NAMESPACE_ENTER

Expand Down Expand Up @@ -146,6 +147,7 @@ public Q_SLOTS:
virtual void enterEvent(QEvent* e) OVERRIDE FINAL;
virtual void leaveEvent(QEvent* e) OVERRIDE FINAL;
boost::scoped_ptr<ProgressPanelPrivate> _imp;
TaskBar *_taskbar;
};

NATRON_NAMESPACE_EXIT
Expand Down
49 changes: 49 additions & 0 deletions Gui/ProgressTaskInfo.cpp
Expand Up @@ -188,6 +188,7 @@ ProgressTaskInfo::ProgressTaskInfo(ProgressPanel* panel,
const ProcessHandlerPtr& process)
: QObject()
, _imp( new ProgressTaskInfoPrivate(panel, node, this, firstFrame, lastFrame, frameStep, canPause, canCancel, message, process) )
, _taskbar(0)
{
//We compute the time remaining automatically based on a timer if this is not a render but a general progress dialog
_imp->timer.reset(new TimeLapse);
Expand Down Expand Up @@ -250,9 +251,11 @@ ProgressTaskInfo::cancelTask(bool calledFromRenderEngine,
if (_imp->canBePaused) {
_imp->statusItem->setText( tr("Paused") );
_imp->status = eProgressTaskStatusPaused;
updateTaskBarState(retCode == 1 ? TaskBar::PausedProgress : TaskBar::NoProgress);
} else {
_imp->statusItem->setText( tr("Canceled") );
_imp->status = eProgressTaskStatusCanceled;
updateTaskBarState(TaskBar::NoProgress);
}
} else {
if (retCode == 0) {
Expand All @@ -262,10 +265,12 @@ ProgressTaskInfo::cancelTask(bool calledFromRenderEngine,
if (_imp->progressBar) {
_imp->progressBar->setValue(100);
}
updateTaskBarState(TaskBar::NormalProgress);
} else {
_imp->statusItem->setTextColor(Qt::red);
_imp->statusItem->setText( tr("Failed") );
_imp->status = eProgressTaskStatusFinished;
updateTaskBarState(TaskBar::ErrorProgress);
}
}
_imp->refreshButtons();
Expand All @@ -275,6 +280,7 @@ ProgressTaskInfo::cancelTask(bool calledFromRenderEngine,
node->getApp()->removeRenderFromQueue(effect);
if ( ( _imp->panel->isRemoveTasksAfterFinishChecked() && (retCode == 0) ) || (!_imp->canBePaused && !calledFromRenderEngine) ) {
_imp->panel->removeTaskFromTable( shared_from_this() );
updateTaskBarState(TaskBar::NoProgress);
}
if (!calledFromRenderEngine) {
Q_EMIT taskCanceled();
Expand Down Expand Up @@ -397,6 +403,45 @@ ProgressTaskInfo::getProcess() const
return _imp->process;
}

void
ProgressTaskInfo::setTaskBar(TaskBar *taskbar)
{
if (!taskbar) {
return;
}
_taskbar = taskbar;
}

void
ProgressTaskInfo::updateTaskBarProgress(ProgressTaskInfo::ProgressTaskStatusEnum status,
double progress)
{
if (!_taskbar) {
return;
}
switch(status) {
case eProgressTaskStatusPaused:
_taskbar->setProgressState(TaskBar::PausedProgress);
break;
case eProgressTaskStatusRunning:
_taskbar->setProgressState(TaskBar::NormalProgress);
break;
default:
_taskbar->setProgressState(TaskBar::NoProgress);
break;
}
_taskbar->setProgressValue(progress);
}

void
ProgressTaskInfo::updateTaskBarState(TaskBar::ProgressState state)
{
if (!_taskbar) {
return;
}
_taskbar->setProgressState(state);
}

bool
ProgressTaskInfo::wasCanceled() const
{
Expand Down Expand Up @@ -559,6 +604,8 @@ ProgressTaskInfo::updateProgressBar(double totalProgress,
_imp->statusItem->setText( tr("Running") );
_imp->refreshButtons();
}

updateTaskBarProgress(_imp->status, _imp->progressPercent);
}

void
Expand Down Expand Up @@ -683,6 +730,8 @@ ProgressTaskInfo::onCancelTriggered()

cancelTask(false, 0);
_imp->panel->removeTaskFromTable(thisShared);

updateTaskBarState(TaskBar::NoProgress);
}

void
Expand Down
8 changes: 8 additions & 0 deletions Gui/ProgressTaskInfo.h
Expand Up @@ -38,6 +38,7 @@

#include "Gui/GuiFwd.h"

#include "Gui/TaskBar.h"

NATRON_NAMESPACE_ENTER

Expand Down Expand Up @@ -122,6 +123,12 @@ GCC_DIAG_SUGGEST_OVERRIDE_ON

ProcessHandlerPtr getProcess() const;

void setTaskBar(TaskBar *taskbar);

void updateTaskBarProgress(ProgressTaskStatusEnum status, double progress);

void updateTaskBarState(TaskBar::ProgressState state);

public Q_SLOTS:

void onShowProgressPanelTimerTimeout();
Expand Down Expand Up @@ -170,6 +177,7 @@ public Q_SLOTS:
void clearItems();

boost::scoped_ptr<ProgressTaskInfoPrivate> _imp;
TaskBar *_taskbar;
};

NATRON_NAMESPACE_EXIT
Expand Down
181 changes: 181 additions & 0 deletions Gui/TaskBar.cpp
@@ -0,0 +1,181 @@
/* ***** BEGIN LICENSE BLOCK *****
* This file is part of Natron <https://natrongithub.github.io/>,
* (C) 2018-2021 The Natron developers
* (C) 2013-2018 INRIA and Alexandre Gauthier-Foichat
*
* Natron is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Natron is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Natron. If not, see <http://www.gnu.org/licenses/gpl-2.0.html>
* ***** END LICENSE BLOCK ***** */

#include "TaskBar.h"

NATRON_NAMESPACE_ENTER

#ifdef Q_OS_WIN
// MINGW workaround
const GUID nIID_ITaskbarList3 = {0xea1afb91, 0x9e28, 0x4b86, {0x90,0xe9,0x9e,0x9f,0x8a,0x5e,0xef,0xaf}};
#endif

TaskBar::TaskBar(QWidget *parent)
: QObject(parent)
#ifdef Q_OS_WIN
, _wtask(0)
#elif defined(Q_OS_MAC)
, _mtask(0)
#endif
, _min(0.0)
, _max(100.0)
, _val(0.0)
, _state(NoProgress)
{
#ifdef Q_OS_WIN
_wid = parent->window()->winId();
CoInitialize(NULL);
HRESULT hres = CoCreateInstance(CLSID_TaskbarList,
NULL,
CLSCTX_INPROC_SERVER,
nIID_ITaskbarList3,
(LPVOID*)&_wtask);
if ( FAILED(hres) ) {
_wtask = NULL;
CoUninitialize();
} else {
_wtask->HrInit();
}
#elif defined(Q_OS_MAC)
_mtask = new TaskBarMac(this);
#endif
}

TaskBar::~TaskBar()
{
#ifdef Q_OS_WIN
if (_wtask) {
_wtask->Release();
_wtask = NULL;
CoUninitialize();
}
#endif
}

void
TaskBar::setProgressMinimum(double value)
{
if (_min < 0.0) {
return;
}
_min = value;
}

void
TaskBar::setProgressMaximum(double value)
{
if (_max < 0.0) {
return;
}
_max = value;
}

void
TaskBar::setProgressRange(double minVal,
double maxVal)
{
if (minVal >= 0.0 && minVal < maxVal) {
setProgressMinimum(minVal);
setProgressMaximum(maxVal);
}
}

void
TaskBar::setProgressValue(double value)
{
if (_val == value) {
return;
}

double currentVal = value - _min;
double totalVal = _max - _min;
if (currentVal < 0.0 || totalVal <= 0.0) {
return;
}
#ifdef Q_OS_WIN
if (!_wtask) {
return;
}
if (_wtask->SetProgressValue(_wid, currentVal, totalVal) == S_OK) {
_val = value;
}
#elif defined(Q_OS_MAC)
if (!_mtask) {
return;
}
_mtask->setProgress(currentVal / totalVal);
_val = value;
#endif
}

void
TaskBar::setProgressState(TaskBar::ProgressState state)
{
if (_state == state) {
return;
}

#ifdef Q_OS_WIN
if (!_wtask) {
return;
}
TBPFLAG flag;
switch(state) {
case NoProgress:
flag = TBPF_NOPROGRESS;
break;
case IndeterminateProgress:
flag = TBPF_INDETERMINATE;
break;
case PausedProgress:
flag = TBPF_PAUSED;
break;
case ErrorProgress:
flag = TBPF_ERROR;
break;
default:
flag = TBPF_NORMAL;
break;
}
if (_wtask->SetProgressState(_wid, flag) == S_OK) {
_state = state;
}
#elif defined(Q_OS_MAC)
if (!_mtask) {
return;
}
if (state == NoProgress) {
_mtask->setProgressVisible(false);
}
_state = state;
#endif
}

void
TaskBar::clearProgress()
{
setProgressRange(0, 100.0);
setProgressValue(0.0);
setProgressState(NoProgress);
}

NATRON_NAMESPACE_EXIT

NATRON_NAMESPACE_USING
#include "moc_TaskBar.cpp"

0 comments on commit a34d684

Please sign in to comment.