Cleanup statusbar messaging system.

Add warning about using a development version
Nicer progress bar for audio thumbs
parent 9dbbcd7f
......@@ -323,6 +323,8 @@ Bin::Bin(QWidget* parent) :
, m_blankThumb()
, m_invalidClipDialog(NULL)
, m_gainedFocus(false)
, m_audioDuration(0)
, m_processedAudio(0)
{
m_layout = new QVBoxLayout(this);
......@@ -505,23 +507,31 @@ QDockWidget *Bin::clipPropertiesDock()
return m_propertiesDock;
}
void Bin::slotAbortAudioThumb(const QString &id)
void Bin::slotAbortAudioThumb(const QString &id, long duration)
{
if (!m_audioThumbsThread.isRunning()) return;
QMutexLocker aMutex(&m_audioThumbMutex);
m_audioThumbsList.removeAll(id);
if (m_audioThumbsList.removeAll(id) > 0)
m_audioDuration -= duration;
}
void Bin::requestAudioThumbs(const QString &id)
void Bin::requestAudioThumbs(const QString &id, long duration)
{
if (!m_audioThumbsList.contains(id) && m_processingAudioThumb != id) {
m_audioThumbMutex.lock();
m_audioThumbsList.append(id);
m_audioDuration += duration;
m_audioThumbMutex.unlock();
processAudioThumbs();
}
}
void Bin::doUpdateThumbsProgress(long ms)
{
int progress = (m_processedAudio + ms) * 100 / m_audioDuration;
emitMessage(i18n("Creating audio thumbnails"), progress, ProcessingJobMessage);
}
void Bin::processAudioThumbs()
{
if (m_audioThumbsThread.isRunning()) return;
......@@ -536,6 +546,10 @@ void Bin::abortAudioThumbs()
if (clip) clip->abortAudioThumbs();
}
m_audioThumbMutex.lock();
foreach(const QString &id, m_audioThumbsList) {
ProjectClip *clip = m_rootFolder->clip(id);
if (clip) clip->setJobStatus(AbstractClipJob::THUMBJOB, JobDone, 0);
}
m_audioThumbsList.clear();
m_audioThumbMutex.unlock();
m_audioThumbsThread.waitForFinished();
......@@ -545,20 +559,26 @@ void Bin::slotCreateAudioThumbs()
{
int max = m_audioThumbsList.count();
int count = 0;
m_processedAudio = 0;
while (!m_audioThumbsList.isEmpty()) {
m_audioThumbMutex.lock();
max = qMax(max, m_audioThumbsList.count());
m_processingAudioThumb = m_audioThumbsList.takeFirst();
count++;
m_audioThumbMutex.unlock();
emitMessage(i18n("Creating audio thumbnails") + QString(" (%1/%2)").arg(count).arg(max), ProcessingJobMessage);
//emitMessage(i18n("Creating audio thumbnails"), (count - 1) * 100 / max, ProcessingJobMessage);
ProjectClip *clip = m_rootFolder->clip(m_processingAudioThumb);
if (clip) clip->slotCreateAudioThumbs();
if (clip) {
clip->slotCreateAudioThumbs();
m_processedAudio += clip->duration().ms();
}
}
m_audioThumbMutex.lock();
m_processingAudioThumb.clear();
m_processedAudio = 0;
m_audioDuration = 0;
m_audioThumbMutex.unlock();
emitMessage(i18n("Audio thumbnails done"), OperationCompletedMessage);
emitMessage(i18n("Audio thumbnails done"), 100, OperationCompletedMessage);
}
bool Bin::eventFilter(QObject *obj, QEvent *event)
......@@ -847,7 +867,7 @@ void Bin::slotLocateClip()
qDebug()<<" / / "+url.toString();
} else {
if(!exists){
emitMessage(i18n("Couldn't locate ") + QString(" ("+url.toString()+")"), ErrorMessage);
emitMessage(i18n("Couldn't locate ") + QString(" ("+url.toString()+")"), 100, ErrorMessage);
}
return;
}
......@@ -3018,9 +3038,9 @@ void Bin::slotResetInfoMessage()
}
}
void Bin::emitMessage(const QString &text, MessageType type)
void Bin::emitMessage(const QString &text, int progress, MessageType type)
{
emit displayMessage(text, type);
emit displayMessage(text, progress, type);
}
void Bin::slotCreateAudioThumb(const QString &id)
......
......@@ -282,23 +282,21 @@ public:
int jobProgress = index.data(AbstractProjectItem::JobProgress).toInt();
if (jobProgress > 0 || jobProgress == JobWaiting) {
// Draw job progress bar
QColor color = option.palette.alternateBase().color();
int progressWidth = option.fontMetrics.averageCharWidth() * 8;
int progressHeight = option.fontMetrics.ascent() / 4;
QRect progress(r1.x() + 1, opt.rect.bottom() - progressHeight - 2, progressWidth , progressHeight);
painter->setPen(Qt::NoPen);
color.setAlpha(180);
painter->setBrush(QBrush(color));
QRect progress(r1.x() + 1, opt.rect.bottom() - 12, r1.width() / 2, 8);
painter->drawRect(progress);
painter->setBrush(option.palette.text());
painter->setBrush(Qt::darkGray);
if (jobProgress > 0) {
progress.adjust(1, 1, 0, -1);
progress.setWidth((progress.width() - 4) * jobProgress / 100);
painter->drawRect(progress);
painter->drawRoundedRect(progress, 2, 2);
painter->setBrush(option.state & QStyle::State_Selected ? option.palette.text() : option.palette.highlight());
progress.setWidth((progressWidth - 2) * jobProgress / 100);
painter->drawRoundedRect(progress, 2, 2);
} else if (jobProgress == JobWaiting) {
// Draw kind of a pause icon
progress.adjust(1, 1, 0, -1);
progress.setWidth(2);
progress.setWidth(3);
painter->drawRect(progress);
progress.moveLeft(progress.right() + 2);
progress.moveLeft(progress.right() + 3);
painter->drawRect(progress);
}
} else if (jobProgress == JobCrashed) {
......@@ -496,13 +494,13 @@ public:
/** @brief Returns current project's folder for storing items. */
QUrl projectFolder() const;
/** @brief Display a message about an operation in status bar. */
void emitMessage(const QString &, MessageType);
void emitMessage(const QString &, int, MessageType);
void rebuildMenu();
void refreshIcons();
/** @brief Update status of disable effects action (when loading a document). */
void setBinEffectsDisabledStatus(bool disabled);
void requestAudioThumbs(const QString &id);
void requestAudioThumbs(const QString &id, long duration);
/** @brief Proxy status for the project changed, update. */
void refreshProxySettings();
/** @brief A clip is ready, update its info panel if displayed. */
......@@ -617,7 +615,7 @@ public slots:
/** @brief Request audio thumbnail for clip with id */
void slotCreateAudioThumb(const QString &id);
/** @brief Abort audio thumbnail for clip with id */
void slotAbortAudioThumb(const QString &id);
void slotAbortAudioThumb(const QString &id, long duration);
/** @brief Add extra data to a clip. */
void slotAddClipExtraData(const QString &id, const QString &key, const QString &data = QString(), QUndoCommand *groupCommand = 0);
void slotUpdateClipProperties(const QString &id, QMap <QString, QString> properties, bool refreshPropertiesPanel);
......@@ -635,6 +633,7 @@ public slots:
/** @brief Select a clip in the Bin from its id. */
void selectClipById(const QString &id, int frame = -1, const QPoint &zone = QPoint());
void slotAddClipToProject(QUrl url);
void doUpdateThumbsProgress(long ms);
protected:
void contextMenuEvent(QContextMenuEvent *event);
......@@ -699,6 +698,10 @@ private:
QStringList m_audioThumbsList;
QString m_processingAudioThumb;
QMutex m_audioThumbMutex;
/** @brief Total number of milliseconds to process for audio thumbnails */
long m_audioDuration;
/** @brief Total number of milliseconds already processed for audio thumbnails */
long m_processedAudio;
/** @brief Indicates whether audio thumbnail creation is running. */
QFuture<void> m_audioThumbsThread;
void showClipProperties(ProjectClip *clip, bool forceRefresh = false);
......@@ -727,7 +730,7 @@ signals:
/** @brief Request updating of the effect stack if currently displayed. */
void masterClipUpdated(ClipController *, Monitor *);
void displayBinMessage(const QString &, KMessageWidget::MessageType);
void displayMessage(const QString &, MessageType);
void displayMessage(const QString &, int, MessageType);
void requesteInvalidRemoval(const QString &, QUrl, const QString &);
/** @brief Markers changed, refresh panel. */
void refreshPanelMarkers();
......
......@@ -65,6 +65,7 @@ ProjectClip::ProjectClip(const QString &id, QIcon thumb, ClipController *control
setParent(parent);
connect(this, &ProjectClip::updateJobStatus, this, &ProjectClip::setJobStatus);
bin()->loadSubClips(id, m_controller->getPropertiesFromPrefix(QStringLiteral("kdenlive:clipzone.")));
connect(this, &ProjectClip::updateThumbProgress, bin(), &Bin::doUpdateThumbsProgress);
createAudioThumbs();
}
......@@ -95,6 +96,7 @@ ProjectClip::ProjectClip(const QDomElement& description, QIcon thumb, ProjectFol
else m_name = i18n("Untitled");
connect(this, &ProjectClip::updateJobStatus, this, &ProjectClip::setJobStatus);
setParent(parent);
connect(this, &ProjectClip::updateThumbProgress, bin(), &Bin::doUpdateThumbsProgress);
}
......@@ -102,7 +104,7 @@ ProjectClip::~ProjectClip()
{
// controller is deleted in bincontroller
abortAudioThumbs();
bin()->slotAbortAudioThumb(m_id);
bin()->slotAbortAudioThumb(m_id, duration().ms());
QMutexLocker audioLock(&m_audioMutex);
m_thumbMutex.lock();
m_requestedThumbs.clear();
......@@ -365,7 +367,8 @@ bool ProjectClip::setProducer(ClipController *controller, bool replaceProducer)
void ProjectClip::createAudioThumbs()
{
if (KdenliveSettings::audiothumbnails() && (m_type == AV || m_type == Audio || m_type == Playlist)) {
bin()->requestAudioThumbs(m_id);
bin()->requestAudioThumbs(m_id, duration().ms());
emit updateJobStatus(AbstractClipJob::THUMBJOB, JobWaiting, 0);
}
}
......@@ -670,7 +673,7 @@ void ProjectClip::setJobStatus(int jobType, int status, int progress, const QStr
m_jobProgress = status;
if ((status == JobAborted || status == JobCrashed || status == JobDone) && !statusMessage.isEmpty()) {
m_jobMessage = statusMessage;
bin()->emitMessage(statusMessage, OperationCompletedMessage);
bin()->emitMessage(statusMessage, 100, OperationCompletedMessage);
}
}
bin()->emitItemUpdated(this);
......@@ -1002,6 +1005,7 @@ void ProjectClip::slotCreateAudioThumbs()
}
}
if (audioLevels.size() > 0) {
emit updateJobStatus(AbstractClipJob::THUMBJOB, JobDone, 0);
updateAudioThumbnail(audioLevels);
return;
}
......@@ -1012,7 +1016,7 @@ void ProjectClip::slotCreateAudioThumbs()
for (int i = 0; i < channels; i++) {
QTemporaryFile *channelTmpfile = new QTemporaryFile;
if (!channelTmpfile->open()) {
bin()->emitMessage(i18n("Cannot create temporary file, check disk space and permissions"), ErrorMessage);
bin()->emitMessage(i18n("Cannot create temporary file, check disk space and permissions"), 100, ErrorMessage);
return;
}
channelTmpfile->close();
......@@ -1053,7 +1057,6 @@ void ProjectClip::slotCreateAudioThumbs()
args << QStringLiteral("-map") << QStringLiteral("[0:%1]").arg(i) << QStringLiteral("-c:a") << QStringLiteral("pcm_s16le") << QStringLiteral("-y") << QStringLiteral("-f") << QStringLiteral("data")<< channelFiles[i]->fileName();
}
}
emit updateJobStatus(AbstractClipJob::THUMBJOB, JobWaiting, 0);
QProcess audioThumbsProcess;
connect(this, SIGNAL(doAbortAudioThumbs()), &audioThumbsProcess, SLOT(kill()), Qt::DirectConnection);
connect(&audioThumbsProcess, &QProcess::readyReadStandardOutput, this, &ProjectClip::updateFfmpegProgress);
......@@ -1084,7 +1087,7 @@ void ProjectClip::slotCreateAudioThumbs()
if (res.isEmpty() || res.size() != dataSize) {
// Something went wrong, abort
emit updateJobStatus(AbstractClipJob::THUMBJOB, JobDone, 0);
bin()->emitMessage(i18n("Error reading audio thumbnail"), ErrorMessage);
bin()->emitMessage(i18n("Error reading audio thumbnail"), 100, ErrorMessage);
return;
}
rawChannels << (const qint16*) res.constData();
......@@ -1118,7 +1121,7 @@ void ProjectClip::slotCreateAudioThumbs()
if (steps) channelsData[k] /= steps;
audioLevels << channelsData[k] * factor;
}
int p = 50 + (i * 50 / lengthInFrames);
int p = 80 + (i * 20 / lengthInFrames);
if (p != progress) {
emit updateJobStatus(AbstractClipJob::THUMBJOB, JobWorking, p);
progress = p;
......@@ -1127,7 +1130,7 @@ void ProjectClip::slotCreateAudioThumbs()
}
jobFinished = true;
} else {
bin()->emitMessage(i18n("Failed to create FFmpeg audio thumbnails, using MLT"), ErrorMessage);
bin()->emitMessage(i18n("Failed to create FFmpeg audio thumbnails, using MLT"), 100, ErrorMessage);
}
}
if (!jobFinished && !m_abortAudioThumb) {
......@@ -1219,7 +1222,11 @@ void ProjectClip::updateFfmpegProgress()
foreach(const QString & data, lines) {
if (data.startsWith(QStringLiteral("out_time_ms"))) {
long ms = data.section(QLatin1Char('='), 1).toLong();
emit updateJobStatus(AbstractClipJob::THUMBJOB, JobWorking, (int) (ms / duration().ms() / 20));
// Update clip progressbar
emit updateJobStatus(AbstractClipJob::THUMBJOB, JobWorking, ms / duration().ms() * 0.08);
// Update general statusbar progressbar
emit updateThumbProgress(ms/1000);
break;
}
}
}
......
......@@ -268,6 +268,7 @@ signals:
void loadPropertiesPanel();
/** @brief Terminate running audio proxy job. */
void doAbortAudioThumbs();
void updateThumbProgress(long);
};
#endif
......@@ -247,7 +247,6 @@ private slots:
signals:
void resetProjectList();
void progressInfo(const QString &, int);
/** @brief Informs that the document status has been changed.
*
......
This diff is collapsed.
......@@ -23,7 +23,6 @@
#include <QDockWidget>
#include <QUndoView>
#include <QProgressBar>
#include <QEvent>
#include <QShortcut>
#include <QMap>
......@@ -133,7 +132,6 @@ public:
QUndoGroup *m_commandStack;
EffectStackView2 *m_effectStack;
QUndoView *m_undoView;
StatusBarMessageLabel *m_messageLabel;
/** @brief holds info about whether movit is available on this system */
bool m_gpuAllowed;
int m_exitCode;
......@@ -164,7 +162,6 @@ protected:
virtual void saveNewToolbarConfig();
private:
QProgressBar *m_statusProgressBar;
/** @brief Sets up all the actions and attaches them to the collection. */
void setupActions();
......@@ -219,7 +216,7 @@ private:
QShortcut* m_shortcutRemoveFocus;
RenderWidget *m_renderWidget;
StatusBarMessageLabel *m_messageLabel;
QList <QAction *>m_transitions;
QAction *m_buttonAudioThumbs;
QAction *m_buttonVideoThumbs;
......@@ -266,8 +263,6 @@ private:
bool m_themeInitialized;
bool m_isDarkTheme;
QListWidget *m_effectBasket;
/** @brief Update statusbar stylesheet (in case of color theme change). */
void setStatusBarStyleSheet(const QPalette &p);
/** @brief Update widget style. */
void doChangeStyle();
......
......@@ -190,7 +190,6 @@ void ProjectManager::newFile(bool showProjectSettings, bool force)
pCore->window()->slotPreferences(6);
return;
}
connect(m_project, SIGNAL(progressInfo(QString,int)), pCore->window(), SLOT(slotGotProgressInfo(QString,int)));
pCore->window()->connectDocument();
bool disabled = m_project->getDocumentProperty(QStringLiteral("disabletimelineeffects")) == QLatin1String("1");
QAction *disableEffects = pCore->window()->actionCollection()->action(QStringLiteral("disable_timeline_effects"));
......@@ -462,8 +461,7 @@ void ProjectManager::openFile(const QUrl &url)
if (checkForBackupFile(url)) {
return;
}
pCore->window()->m_messageLabel->setMessage(i18n("Opening file %1", url.path()), InformationMessage);
pCore->window()->m_messageLabel->repaint();
pCore->window()->slotGotProgressInfo(i18n("Opening file %1", url.path()), 100, InformationMessage);
doOpenFile(url, NULL);
}
......@@ -506,7 +504,6 @@ void ProjectManager::doOpenFile(const QUrl &url, KAutoSaveFile *stale)
stale->setParent(doc);
}
m_progressDialog->setLabelText(i18n("Loading clips"));
connect(doc, SIGNAL(progressInfo(QString,int)), pCore->window(), SLOT(slotGotProgressInfo(QString,int)));
pCore->bin()->setDocument(doc);
QList <QAction*> rulerActions;
......
......@@ -33,38 +33,87 @@
#include <QPainter>
#include <QPushButton>
#include <QPixmap>
#include <QLabel>
#include <QProgressBar>
#include <QMouseEvent>
#include <QHBoxLayout>
FlashLabel::FlashLabel(QWidget *parent) : QWidget(parent)
{
setAutoFillBackground(true);
}
FlashLabel::~FlashLabel()
{
}
void FlashLabel::setColor(const QColor &col)
{
QPalette pal = palette();
pal.setColor(QPalette::Window, col);
setPalette(pal);
update();
}
QColor FlashLabel::color() const
{
return palette().window().color();
}
StatusBarMessageLabel::StatusBarMessageLabel(QWidget* parent) :
QWidget(parent),
m_state(Default),
m_illumination(-64),
FlashLabel(parent),
m_minTextHeight(-1),
m_queueSemaphore(1),
m_closeButton(0)
m_queueSemaphore(1)
{
setMinimumHeight(KIconLoader::SizeSmall);
/*QPalette palette);
palette.setColor(QPalette::Background, Qt::transparent);
setPalette(palette);*/
m_closeButton = new QPushButton(i18nc("@action:button", "Confirm"), this);
m_closeButton->hide();
QHBoxLayout *lay = new QHBoxLayout(this);
m_pixmap = new QLabel(this);
m_pixmap->setAlignment(Qt::AlignCenter);
m_label = new QLabel(this);
m_label->setAlignment(Qt::AlignLeft);
m_progress = new QProgressBar(this);
lay->addWidget(m_pixmap);
lay->addWidget(m_label);
lay->addWidget(m_progress);
setLayout(lay);
m_progress->setVisible(false);
lay->setContentsMargins(BorderGap, 0, BorderGap, 0);
m_animation.setTargetObject(this);
m_animation.setPropertyName("color");
m_queueTimer.setSingleShot(true);
connect(&m_queueTimer, SIGNAL(timeout()), this, SLOT(slotMessageTimeout()));
connect(m_closeButton, SIGNAL(clicked()), this, SLOT(confirmErrorMessage()));
connect(&m_timer, SIGNAL(timeout()), this, SLOT(timerDone()));
}
StatusBarMessageLabel::~StatusBarMessageLabel()
{
}
void StatusBarMessageLabel::setMessage(const QString& text,
MessageType type, int timeoutMS)
void StatusBarMessageLabel::updatePalette()
{
m_animation.setKeyValueAt(1, parentWidget()->palette().window().color());
setColor(parentWidget()->palette().window().color());
}
void StatusBarMessageLabel::mousePressEvent(QMouseEvent *event)
{
QWidget::mousePressEvent(event);
if (m_currentMessage.type == MltError)
confirmErrorMessage();
}
void StatusBarMessageLabel::setMessage(const QString& text, int progress, MessageType type, int timeoutMS)
{
if (type == ProcessingJobMessage) {
m_progress->setValue(progress);
m_progress->setVisible(progress < 100);
}
else if (m_currentMessage.type != ProcessingJobMessage || type == OperationCompletedMessage) {
m_progress->setVisible(progress < 100);
}
if (text == m_currentMessage.text)
return;
StatusBarMessageItem item(text, type, timeoutMS);
if (item.type == ErrorMessage || item.type == MltError) {
......@@ -77,10 +126,9 @@ void StatusBarMessageLabel::setMessage(const QString& text,
qDebug() << item.text;
// Put the new error message at first place and immediately show it
if (item.timeoutMillis < 2000) {
item.timeoutMillis = 2000;
if (item.timeoutMillis < 3000) {
item.timeoutMillis = 3000;
}
if (item.type == ProcessingJobMessage) {
// This is a job progress info, discard previous ones
QList <StatusBarMessageItem> cleanList;
......@@ -97,8 +145,6 @@ void StatusBarMessageLabel::setMessage(const QString& text,
// In case we are already displaying an error message, add a little delay
int delay = 800 * (m_currentMessage.type == ErrorMessage || m_currentMessage.type == MltError);
m_queueTimer.start(delay);
} else {
// Message with normal priority
......@@ -128,14 +174,16 @@ bool StatusBarMessageLabel::slotMessageTimeout()
m_messageQueue.removeFirst();
if (item.type == OperationCompletedMessage || item.type == ErrorMessage || item.type == MltError || item.type == ProcessingJobMessage) {
m_currentMessage = item;
m_label->setText(m_currentMessage.text);
newMessage = true;
break;
}
}
}
}
else if (!m_messageQueue.isEmpty()) {
if (!m_currentMessage.needsConfirmation()) {
m_currentMessage = m_messageQueue.at(0);
m_label->setText(m_currentMessage.text);
m_messageQueue.removeFirst();
newMessage = true;
......@@ -158,52 +206,56 @@ bool StatusBarMessageLabel::slotMessageTimeout()
}
}
m_illumination = -64;
m_state = Default;
m_timer.stop();
QColor bgColor = KStatefulBrush(KColorScheme::Window, KColorScheme::NegativeBackground, KSharedConfig::openConfig(KdenliveSettings::colortheme())).brush(this).color();
const char* iconName = 0;
if (m_animation.state() == QAbstractAnimation::Running) {
m_animation.stop();
}
setColor(parentWidget()->palette().window().color());
switch (m_currentMessage.type) {
case ProcessingJobMessage:
iconName = "chronometer";
m_closeButton->hide();
break;
case OperationCompletedMessage:
iconName = "dialog-ok";
m_closeButton->hide();
break;
case InformationMessage:
iconName = "dialog-information";
m_closeButton->hide();
break;
case ErrorMessage:
iconName = "dialog-warning";
m_timer.start(100);
m_state = Illuminate;
m_closeButton->hide();
m_animation.setKeyValueAt(0, bgColor);
m_animation.setKeyValueAt(0.8, bgColor);
m_animation.setKeyValueAt(1, parentWidget()->palette().window().color());
m_animation.setEasingCurve(QEasingCurve::OutCubic);
m_animation.setDuration(4000);
m_animation.start();
break;
case MltError:
iconName = "dialog-close";
m_timer.start(100);
m_state = Illuminate;
updateCloseButtonPosition();
m_closeButton->show();
m_animation.setKeyValueAt(0, bgColor);
m_animation.setKeyValueAt(1, bgColor);
m_animation.setDuration(1000);
m_animation.start();
break;
case DefaultMessage:
default:
m_closeButton->hide();
break;
}
m_pixmap = (iconName == 0) ? QPixmap() : SmallIcon(iconName);
if (iconName == 0) {
m_pixmap->setVisible(false);
} else {
m_pixmap->setPixmap(SmallIcon(iconName));
m_pixmap->setVisible(true);
}
setCursor(m_currentMessage.type == MltError ? Qt::PointingHandCursor : Qt::ArrowCursor);
m_queueSemaphore.release();
update();
return newMessage;
}
......@@ -213,106 +265,8 @@ void StatusBarMessageLabel::confirmErrorMessage()
m_queueTimer.start(0);
}
void StatusBarMessageLabel::paintEvent(QPaintEvent*)
{
QPainter painter(this);
// draw background
QColor backgroundColor;
if (m_state == Default || m_illumination < 0) backgroundColor = palette().window().color();
else {
backgroundColor = KStatefulBrush(KColorScheme::Window, KColorScheme::NegativeBackground, KSharedConfig::openConfig(KdenliveSettings::colortheme())).brush(this).color();
}
if (m_state == Desaturate && m_illumination > 0) {
backgroundColor.setAlpha(qMin(m_illumination * 2, 255));
}
painter.fillRect(0, 0, width(), height(), backgroundColor);
// draw pixmap
int x = BorderGap;
int y = (height() - m_pixmap.height()) / 2;
if (!m_pixmap.isNull()) {
painter.drawPixmap(x, y, m_pixmap);
x += m_pixmap.width() + BorderGap * 2;
}
// draw text
painter.setPen(palette().text().color());
int flags = Qt::AlignVCenter;
if (height() > m_minTextHeight) {
flags = flags | Qt::TextWordWrap;
}
painter.drawText(QRect(x, 0, availableTextWidth(), height()), flags, m_currentMessage.text);
painter.end();
}
void StatusBarMessageLabel::resizeEvent(QResizeEvent* event)
{
QWidget::resizeEvent(event);
updateCloseButtonPosition();