diff --git a/LameXP.vcproj b/LameXP.vcproj index 3a1fb594..7643831f 100644 --- a/LameXP.vcproj +++ b/LameXP.vcproj @@ -374,6 +374,10 @@ RelativePath=".\src\Thread_MessageProducer.cpp" > + + + + + + + + + + + + + + + + + + + + + + + + @@ -920,6 +992,10 @@ RelativePath=".\tmp\MOC_Thread_MessageProducer.cpp" > + + diff --git a/etc/Deployment/_build.bat b/etc/Deployment/_build.bat index 4062c915..2344d19f 100644 --- a/etc/Deployment/_build.bat +++ b/etc/Deployment/_build.bat @@ -16,6 +16,9 @@ if not "%ERRORLEVEL%"=="0" GOTO:EOF echo ---------------------------------------------------------------- set "LAMEXP_ERROR=1" msbuild.exe /property:Configuration=%2 /property:Platform=Win32 /target:Rebuild /verbosity:detailed %1 -if not "%ERRORLEVEL%"=="0" GOTO:EOF +if not "%ERRORLEVEL%"=="0" ( + msbuild.exe /property:Configuration=%2 /property:Platform=Win32 /target:Build /verbosity:detailed %1 + if not "%ERRORLEVEL%"=="0" GOTO:EOF +) echo ---------------------------------------------------------------- set "LAMEXP_ERROR=0" diff --git a/gui/ProcessingDialog.ui b/gui/ProcessingDialog.ui index abdaf584..372b6ade 100644 --- a/gui/ProcessingDialog.ui +++ b/gui/ProcessingDialog.ui @@ -7,7 +7,7 @@ 0 0 663 - 458 + 454 @@ -30,13 +30,13 @@ 0 - 72 + 64 16777215 - 72 + 64 @@ -138,14 +138,14 @@ - 60 - 56 + 48 + 45 - 60 - 56 + 48 + 45 @@ -283,6 +283,18 @@ false + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + false + + + false + @@ -335,6 +347,9 @@ true + + PointingHandCursor + (VERSION_TAG) @@ -405,6 +420,14 @@ + + + + + + + + @@ -423,21 +446,5 @@ - - button_AbortProcess - clicked() - ProcessingDialog - reject() - - - 453 - 422 - - - 331 - 228 - - - diff --git a/res/Icons.qrc b/res/Icons.qrc index 6d14a856..610629ab 100644 --- a/res/Icons.qrc +++ b/res/Icons.qrc @@ -36,6 +36,7 @@ icons/folder_page.png icons/house.png icons/information.png + icons/media_play.png icons/monitor.png icons/music.png icons/package.png @@ -47,6 +48,7 @@ icons/sound.png icons/star.png icons/table_edit.png + icons/tick.png icons/timeline_marker.png icons/transmit_blue.png icons/user.png diff --git a/src/Config.h b/src/Config.h index 0cc442aa..8f40093f 100644 --- a/src/Config.h +++ b/src/Config.h @@ -25,7 +25,7 @@ #define VER_LAMEXP_MAJOR 4 #define VER_LAMEXP_MINOR_HI 0 #define VER_LAMEXP_MINOR_LO 0 -#define VER_LAMEXP_BUILD 34 +#define VER_LAMEXP_BUILD 38 #define VER_LAMEXP_SUFFIX TechPreview /* diff --git a/src/Dialog_Processing.cpp b/src/Dialog_Processing.cpp index 71df808e..755a4c2b 100644 --- a/src/Dialog_Processing.cpp +++ b/src/Dialog_Processing.cpp @@ -22,11 +22,23 @@ #include "Dialog_Processing.h" #include "Global.h" +#include "Model_Progress.h" +#include "Thread_Process.h" #include #include #include #include +#include +#include +#include +#include +#include +#include + +//////////////////////////////////////////////////////////// +// Constructor +//////////////////////////////////////////////////////////// ProcessingDialog::ProcessingDialog(void) { @@ -34,6 +46,7 @@ ProcessingDialog::ProcessingDialog(void) setupUi(this); setWindowFlags(windowFlags() ^ Qt::WindowContextHelpButtonHint); label_versionInfo->setText(QString().sprintf("v%d.%02d %s (Build %d)", lamexp_version_major(), lamexp_version_minor(), lamexp_version_release(), lamexp_version_build())); + label_versionInfo->installEventFilter(this); //Center window in screen QRect desktopRect = QApplication::desktop()->screenGeometry(); @@ -41,14 +54,158 @@ ProcessingDialog::ProcessingDialog(void) move((desktopRect.width() - thisRect.width()) / 2, (desktopRect.height() - thisRect.height()) / 2); setMinimumSize(thisRect.width(), thisRect.height()); + //Enable buttons + connect(button_AbortProcess, SIGNAL(clicked()), this, SLOT(abortEncoding())); + //Init progress indicator m_progressIndicator = new QMovie(":/images/Working.gif"); label_headerWorking->setMovie(m_progressIndicator); - m_progressIndicator->start(); + progressBar->setRange(0, 4); + progressBar->setValue(0); + + //Init progress model + m_progressModel = new ProgressModel(); + view_log->setModel(m_progressModel); + view_log->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents); + view_log->verticalHeader()->hide(); + view_log->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents); + view_log->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch); + + //Init member vars + for(int i = 0; i < 4; i++) m_thread[i] = NULL; } +//////////////////////////////////////////////////////////// +// Destructor +//////////////////////////////////////////////////////////// + ProcessingDialog::~ProcessingDialog(void) { + view_log->setModel(NULL); if(m_progressIndicator) m_progressIndicator->stop(); LAMEXP_DELETE(m_progressIndicator); + LAMEXP_DELETE(m_progressModel); +} + +//////////////////////////////////////////////////////////// +// EVENTS +//////////////////////////////////////////////////////////// + +void ProcessingDialog::showEvent(QShowEvent *event) +{ + setCloseButtonEnabled(false); + button_closeDialog->setEnabled(false); + button_AbortProcess->setEnabled(false); + + QTimer::singleShot(1000, this, SLOT(initEncoding())); +} + +void ProcessingDialog::closeEvent(QCloseEvent *event) +{ + if(!button_closeDialog->isEnabled() || m_thread) event->ignore(); +} + +bool ProcessingDialog::eventFilter(QObject *obj, QEvent *event) +{ + static QColor defaultColor = QColor(); + + if(obj == label_versionInfo) + { + if(event->type() == QEvent::Enter) + { + QPalette palette = label_versionInfo->palette(); + defaultColor = palette.color(QPalette::Normal, QPalette::WindowText); + palette.setColor(QPalette::Normal, QPalette::WindowText, Qt::red); + label_versionInfo->setPalette(palette); + } + else if(event->type() == QEvent::Leave) + { + QPalette palette = label_versionInfo->palette(); + palette.setColor(QPalette::Normal, QPalette::WindowText, defaultColor); + label_versionInfo->setPalette(palette); + } + else if(event->type() == QEvent::MouseButtonPress) + { + QUrl url("http://mulder.dummwiedeutsch.de/"); + QDesktopServices::openUrl(url); + } + } + + return false; +} + +//////////////////////////////////////////////////////////// +// SLOTS +//////////////////////////////////////////////////////////// + +void ProcessingDialog::initEncoding(void) +{ + label_progress->setText("Encoding files, please wait..."); + m_progressIndicator->start(); + + m_pendingJobs = 4; + + for(int i = 0; i < 4; i++) + { + m_thread[i] = new ProcessThread(); + connect(m_thread[i], SIGNAL(finished()), this, SLOT(doneEncoding()), Qt::QueuedConnection); + connect(m_thread[i], SIGNAL(processStateInitialized(QString,QString,QString,int)), m_progressModel, SLOT(addJob(QString,QString,QString,int)), Qt::QueuedConnection); + connect(m_thread[i], SIGNAL(processStateChanged(QString,QString,int)), m_progressModel, SLOT(updateJob(QString,QString,int)), Qt::QueuedConnection); + m_thread[i]->start(); + } + + button_closeDialog->setEnabled(false); + button_AbortProcess->setEnabled(true); +} + +void ProcessingDialog::abortEncoding(void) +{ + button_AbortProcess->setEnabled(false); + + for(int i = 0; i < 4; i++) + { + if(m_thread[i]) + { + m_thread[i]->abort(); + } + } +} + +void ProcessingDialog::doneEncoding(void) +{ + progressBar->setValue(progressBar->value() + 1); + + if(--m_pendingJobs > 0) + { + return; + } + + label_progress->setText("Completed."); + m_progressIndicator->stop(); + + setCloseButtonEnabled(true); + button_closeDialog->setEnabled(true); + button_AbortProcess->setEnabled(false); + + for(int i = 0; i < 4; i++) + { + if(m_thread[i]) + { + m_thread[i]->terminate(); + m_thread[i]->wait(); + LAMEXP_DELETE(m_thread[i]); + } + } + + progressBar->setValue(100); +} + +//////////////////////////////////////////////////////////// +// Private Functions +//////////////////////////////////////////////////////////// + +void ProcessingDialog::setCloseButtonEnabled(bool enabled) +{ + HMENU hMenu = GetSystemMenu((HWND) winId(), FALSE); + EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | (enabled ? MF_ENABLED : MF_GRAYED)); } diff --git a/src/Dialog_Processing.h b/src/Dialog_Processing.h index 59efbc8c..7129d773 100644 --- a/src/Dialog_Processing.h +++ b/src/Dialog_Processing.h @@ -24,6 +24,8 @@ #include "../tmp/UIC_ProcessingDialog.h" class QMovie; +class ProgressModel; +class ProcessThread; class ProcessingDialog : public QDialog, private Ui::ProcessingDialog { @@ -33,6 +35,21 @@ public: ProcessingDialog(void); ~ProcessingDialog(void); +private slots: + void initEncoding(void); + void doneEncoding(void); + void abortEncoding(void); + +protected: + void showEvent(QShowEvent *event); + void closeEvent(QCloseEvent *event); + bool eventFilter(QObject *obj, QEvent *event); + private: + void setCloseButtonEnabled(bool enabled); + + int m_pendingJobs; QMovie *m_progressIndicator; + ProgressModel *m_progressModel; + ProcessThread *m_thread[4]; }; diff --git a/src/Model_Progress.cpp b/src/Model_Progress.cpp index d2fada1e..3467e031 100644 --- a/src/Model_Progress.cpp +++ b/src/Model_Progress.cpp @@ -22,9 +22,9 @@ #include "Model_Progress.h" ProgressModel::ProgressModel(void) : - m_iconRunning(":/icons/resultset_next.png"), + m_iconRunning(":/icons/media_play.png"), m_iconPaused(":/icons/control_pause_blue.png"), - m_iconComplete(":/icons/accept.png"), + m_iconComplete(":/icons/tick.png"), m_iconFailed(":/icons/exclamation.png") { } @@ -67,12 +67,16 @@ QVariant ProgressModel::data(const QModelIndex &index, int role) const switch(m_jobState.value(m_jobList.at(index.row()))) { case JobRunning: + return m_iconRunning; break; case JobPaused: + return m_iconPaused; break; case JobComplete: + return m_iconComplete; break; default: + return m_iconFailed; break; } } diff --git a/src/Model_Progress.h b/src/Model_Progress.h index 14759c4c..6abf4ca2 100644 --- a/src/Model_Progress.h +++ b/src/Model_Progress.h @@ -30,6 +30,8 @@ class ProgressModel : public QAbstractTableModel { + Q_OBJECT + public: ProgressModel(void); ~ProgressModel(void); diff --git a/src/Thread_Process.cpp b/src/Thread_Process.cpp new file mode 100644 index 00000000..2829d6ab --- /dev/null +++ b/src/Thread_Process.cpp @@ -0,0 +1,77 @@ +/////////////////////////////////////////////////////////////////////////////// +// LameXP - Audio Encoder Front-End +// Copyright (C) 2004-2010 LoRd_MuldeR +// +// This program 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. +// +// This program 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 this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// http://www.gnu.org/licenses/gpl-2.0.txt +/////////////////////////////////////////////////////////////////////////////// + +#include "Thread_Process.h" + +#include "Global.h" +#include "Model_Progress.h" + +#include +#include +#include + +//////////////////////////////////////////////////////////// +// Constructor +//////////////////////////////////////////////////////////// + +ProcessThread::ProcessThread(void) + : m_jobId(QUuid::createUuid().toString()), m_aborted(false) +{ +} + +ProcessThread::~ProcessThread(void) +{ +} + +void ProcessThread::run() +{ + m_aborted = false; + + qDebug("Process thread %s has started.", m_jobId.toLatin1().constData()); + emit processStateInitialized(m_jobId, "Slime - Der Tod Ist Ein Meister Aus Deutschland.mp3", "Starting...", ProgressModel::JobRunning); + + QUuid uuid = QUuid::createUuid(); + qsrand(uuid.data1 * uuid.data2 * uuid.data3); + unsigned long delay = 250 + (qrand() % 500); + + + for(int i = 1; i <= 100; i++) + { + if(m_aborted) + { + emit processStateChanged(m_jobId, "Aborted.", ProgressModel::JobFailed); + return; + } + + QThread::msleep(delay); + emit processStateChanged(m_jobId, QString("Encoding (%1%)").arg(i), ProgressModel::JobRunning); + qDebug("Process thread is alive."); + } + + emit processStateChanged(m_jobId, "Done (100%)", ProgressModel::JobComplete); + qDebug("Process thread is about to die..."); +} + +//////////////////////////////////////////////////////////// +// EVENTS +//////////////////////////////////////////////////////////// + +/*NONE*/ \ No newline at end of file diff --git a/src/Thread_Process.h b/src/Thread_Process.h new file mode 100644 index 00000000..551fe8e7 --- /dev/null +++ b/src/Thread_Process.h @@ -0,0 +1,43 @@ +/////////////////////////////////////////////////////////////////////////////// +// LameXP - Audio Encoder Front-End +// Copyright (C) 2004-2010 LoRd_MuldeR +// +// This program 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. +// +// This program 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 this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// http://www.gnu.org/licenses/gpl-2.0.txt +/////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include + +class ProcessThread: public QThread +{ + Q_OBJECT + +public: + ProcessThread(void); + ~ProcessThread(void); + void run(); + void abort() { m_aborted = true; } + +signals: + void processStateInitialized(const QString &jobId, const QString &jobName, const QString &jobInitialStatus, int jobInitialState); + void processStateChanged(const QString &jobId, const QString &newStatus, int newState); + +private: + const QString m_jobId; + volatile bool m_aborted; +};