Non-functional GUI improvements

* Don't include <QtGui>, which is a leftover from Qt4 and causes literally
  everything to be pulled into the TU.
* Use forward declarations instead of includes where possible.
* Replace aggregated Ui* classes with aggregation via pointer, which allows
  these classes to be forward-declared and thus further reduce the number of
  included headers. Aggregation via pointer has been the default in Qt Creator
  for some time now.
* Fix minor warnings reported by Clang.
* Move QnCheckBoxedHeaderView to a separate file.
* Move QtvCodecInfo to a separate file, change initializer list to inline member initialization.
* Create an actual QMake .pro file instead of stuffing it in MXE build scripts.
* Fix 32-bit integers being used as pointers to QtvCodecInfo objects in 64-bit Windows builds.
* Update information in the "About" tab.
This commit is contained in:
Daniel Kamil Kozar 2020-01-11 23:46:04 +01:00 committed by GitHub
parent 1701957c05
commit a4cc39fb10
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 837 additions and 843 deletions

View File

@ -8,28 +8,11 @@ i686-w64-mingw32.static-cmake ../
make
cp tsMuxer/tsmuxer.exe ../bin/tsMuxeR.exe
# cmake with the static Qt5 in MXE has major issues - we have to use qmake as a workaround
cat << EOF > ../tsMuxerGUI/tsMuxerGUI.pro
TEMPLATE = app
TARGET = tsMuxerGUI
QT = core gui widgets multimedia
HEADERS += tsmuxerwindow.h lang_codes.h muxForm.h
SOURCES += main.cpp tsmuxerwindow.cpp muxForm.cpp
FORMS += tsmuxerwindow.ui muxForm.ui
RESOURCES += images.qrc
TRANSLATIONS =
win32 {
RC_FILE += icon.rc
}
EOF
i686-w64-mingw32.static-qmake-qt5 ../tsMuxerGUI
make
cp ./release/tsMuxerGUI.exe ../bin/
cd ..
rm -rf build
rm -f ./tsMuxerGUI/tsMuxerGUI.pro
mkdir ./bin/w32
mv ./bin/tsMuxeR.exe ./bin/w32/tsMuxeR.exe

View File

@ -8,28 +8,11 @@ x86_64-w64-mingw32.static-cmake ../
make
cp tsMuxer/tsmuxer.exe ../bin/tsMuxeR.exe
# cmake with the static Qt5 in MXE has major issues - we have to use qmake as a workaround
cat << EOF > ../tsMuxerGUI/tsMuxerGUI.pro
TEMPLATE = app
TARGET = tsMuxerGUI
QT = core gui widgets multimedia
HEADERS += tsmuxerwindow.h lang_codes.h muxForm.h
SOURCES += main.cpp tsmuxerwindow.cpp muxForm.cpp
FORMS += tsmuxerwindow.ui muxForm.ui
RESOURCES += images.qrc
TRANSLATIONS =
win32 {
RC_FILE += icon.rc
}
EOF
x86_64-w64-mingw32.static-qmake-qt5 ../tsMuxerGUI
make
cp ./release/tsMuxerGUI.exe ../bin/
cd ..
rm -rf build
rm -f ./tsMuxerGUI/tsMuxerGUI.pro
mkdir ./bin/w64
mv ./bin/tsMuxeR.exe ./bin/w64/tsMuxeR.exe

View File

@ -17,6 +17,7 @@ set(tsmuxer_gui_sources
muxForm.cpp
tsmuxerwindow.ui
muxForm.ui
checkboxedheaderview.cpp
images.qrc
)

View File

@ -0,0 +1,76 @@
#include "checkboxedheaderview.h"
#include <QPainter>
QnCheckBoxedHeaderView::QnCheckBoxedHeaderView(QWidget *parent)
: base_type(Qt::Horizontal, parent), m_checkState(Qt::Unchecked),
m_checkColumnIndex(0) {
connect(this, &QnCheckBoxedHeaderView::sectionClicked, this,
&QnCheckBoxedHeaderView::at_sectionClicked);
}
void QnCheckBoxedHeaderView::setCheckState(Qt::CheckState state) {
if (state == m_checkState)
return;
m_checkState = state;
emit checkStateChanged(state);
viewport()->update();
}
void QnCheckBoxedHeaderView::paintSection(QPainter *painter, const QRect &rect,
int logicalIndex) const {
painter->save();
base_type::paintSection(painter, rect, logicalIndex);
painter->restore();
if (logicalIndex == m_checkColumnIndex) {
if (!rect.isValid())
return;
QStyleOptionButton opt;
opt.initFrom(this);
QStyle::State state = QStyle::State_Raised;
if (isEnabled())
state |= QStyle::State_Enabled;
if (window()->isActiveWindow())
state |= QStyle::State_Active;
switch (m_checkState) {
case Qt::Checked:
state |= QStyle::State_On;
break;
case Qt::Unchecked:
state |= QStyle::State_Off;
break;
default:
state |= QStyle::State_NoChange;
break;
}
opt.rect = rect.adjusted(4, 0, 0, 0);
opt.state |= state;
opt.text = QString();
painter->save();
style()->drawControl(QStyle::CE_CheckBox, &opt, painter, this);
painter->restore();
}
}
QSize QnCheckBoxedHeaderView::sectionSizeFromContents(int logicalIndex) const {
QSize size = base_type::sectionSizeFromContents(logicalIndex);
if (logicalIndex != m_checkColumnIndex)
return size;
size.setWidth(15);
return size;
}
void QnCheckBoxedHeaderView::at_sectionClicked(int logicalIndex) {
if (logicalIndex != m_checkColumnIndex)
return;
if (m_checkState != Qt::Checked)
setCheckState(Qt::Checked);
else
setCheckState(Qt::Unchecked);
}

View File

@ -0,0 +1,27 @@
#ifndef CHECKBOXEDHEADERVIEW_H
#define CHECKBOXEDHEADERVIEW_H
#include <QHeaderView>
class QnCheckBoxedHeaderView: public QHeaderView {
Q_OBJECT
typedef QHeaderView base_type;
public:
explicit QnCheckBoxedHeaderView(QWidget *parent = nullptr);
Qt::CheckState checkState() const {
return m_checkState;
}
void setCheckState(Qt::CheckState state);
signals:
void checkStateChanged(Qt::CheckState state);
protected:
void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const override;
QSize sectionSizeFromContents(int logicalIndex) const override;
private:
void at_sectionClicked(int logicalIndex);
Qt::CheckState m_checkState;
int m_checkColumnIndex;
};
#endif

44
tsMuxerGUI/codecinfo.h Normal file
View File

@ -0,0 +1,44 @@
#ifndef CODECINFO_H
#define CODECINFO_H
#include <QString>
#include <QList>
struct QtvCodecInfo
{
QtvCodecInfo() = default;
QtvCodecInfo(const QtvCodecInfo&) = default;
int trackID = 0;
int width = 0;
int height = 0;
QString displayName;
QString programName;
QString descr;
QString lang;
int delay = 0;
int subTrack = 0;
bool dtsDownconvert = false;
bool isSecondary = false;
int offsetId = -1;
int maxPgOffsets = 0;
QList<QString> fileList;
bool checkFPS = false;
bool checkLevel = false;
int addSEIMethod = 1;
bool addSPS = true;
int delPulldown = -1;
QString fpsText;
QString fpsTextOrig;
QString levelText;
// for append
int nested = 0;
QtvCodecInfo* parent = nullptr;
QtvCodecInfo* child = nullptr;
bool bindFps = true;
QStringList mplsFiles;
QString arText;
bool enabledByDefault = true;
};
#endif

View File

@ -1,7 +1,8 @@
#include <QtGui>
#include "tsmuxerwindow.h"
#include <QApplication>
#include <QUrl>
int main(int argc, char *argv[]) {
Q_INIT_RESOURCE(images);
QApplication app(argc, argv);

View File

@ -1,14 +1,18 @@
#include "muxForm.h"
#include "ui_muxForm.h"
#include <QCloseEvent>
#include <QProcess>
const static int MAX_ERRORS_CNT = 10000;
MuxForm::MuxForm(QWidget *parent)
: QDialog(parent, Qt::WindowMaximizeButtonHint), muxProcess(0) {
ui.setupUi(this);
connect(ui.progressBar, &QProgressBar::valueChanged, this,
: QDialog(parent, Qt::WindowMaximizeButtonHint), ui(new Ui_muxForm),
muxProcess(0) {
ui->setupUi(this);
connect(ui->progressBar, &QProgressBar::valueChanged, this,
&MuxForm::onProgressChanged);
connect(ui.abortBtn, &QPushButton::clicked, this, &MuxForm::onAbort);
connect(ui.okBtn, &QPushButton::clicked, this, &MuxForm::close);
connect(ui->abortBtn, &QPushButton::clicked, this, &MuxForm::onAbort);
connect(ui->okBtn, &QPushButton::clicked, this, &MuxForm::close);
}
void MuxForm::closeEvent(QCloseEvent *event) {
@ -20,63 +24,62 @@ void MuxForm::prepare(const QString &label) {
muxProcess = 0;
errCnt = 0;
setWindowTitle(label);
ui.muxLabel->setText(label + '.');
ui.progressBar->setValue(0);
ui.stdoutText->clear();
ui.stderrText->clear();
ui.abortBtn->setEnabled(true);
ui.okBtn->setEnabled(false);
ui->muxLabel->setText(label + '.');
ui->progressBar->setValue(0);
ui->stdoutText->clear();
ui->stderrText->clear();
ui->abortBtn->setEnabled(true);
ui->okBtn->setEnabled(false);
}
void MuxForm::onProgressChanged() {
ui.progressLabel->setText(
ui->progressLabel->setText(
QString("Progress: ") +
QString::number(ui.progressBar->value() / 10.0, 'f', 1) + '%');
QString::number(ui->progressBar->value() / 10.0, 'f', 1) + '%');
}
void MuxForm::setProgress(int value) { ui.progressBar->setValue(value); }
void MuxForm::setProgress(int value) { ui->progressBar->setValue(value); }
void MuxForm::addStdOutLine(const QString &line) {
ui.stdoutText->append(line);
QTextCursor c = ui.stdoutText->textCursor();
ui->stdoutText->append(line);
QTextCursor c = ui->stdoutText->textCursor();
c.movePosition(QTextCursor::End);
ui.stdoutText->setTextCursor(c);
ui->stdoutText->setTextCursor(c);
}
void MuxForm::addStdErrLine(const QString &line) {
if (errCnt >= MAX_ERRORS_CNT)
return;
ui.stderrText->append(line);
errCnt = ui.stderrText->document()->blockCount();
ui->stderrText->append(line);
errCnt = ui->stderrText->document()->blockCount();
if (errCnt >= MAX_ERRORS_CNT) {
ui.stderrText->append("---------------------------------------");
ui.stderrText->append("Too many errors! tsMuxeR is terminated.");
ui->stderrText->append("---------------------------------------");
ui->stderrText->append("Too many errors! tsMuxeR is terminated.");
onAbort();
}
QTextCursor c = ui.stderrText->textCursor();
QTextCursor c = ui->stderrText->textCursor();
c.movePosition(QTextCursor::End);
ui.stderrText->setTextCursor(c);
ui->stderrText->setTextCursor(c);
}
void MuxForm::muxFinished(int exitCode, const QString &prefix) {
Q_UNUSED(prefix);
if (muxProcess && ui.abortBtn->isEnabled()) {
void MuxForm::muxFinished(int exitCode, const QString &) {
if (muxProcess && ui->abortBtn->isEnabled()) {
if (exitCode == 0)
setWindowTitle("tsMuxeR successfully finished");
else
setWindowTitle("tsMuxeR finished with error code " +
QString::number(exitCode));
ui.muxLabel->setText(windowTitle() + '.');
ui.abortBtn->setEnabled(false);
ui.okBtn->setEnabled(true);
ui->muxLabel->setText(windowTitle() + '.');
ui->abortBtn->setEnabled(false);
ui->okBtn->setEnabled(true);
}
}
void MuxForm::onAbort() {
if (muxProcess == nullptr)
return;
ui.abortBtn->setEnabled(false);
ui.okBtn->setEnabled(true);
ui->abortBtn->setEnabled(false);
ui->okBtn->setEnabled(true);
setWindowTitle("terminating tsMuxeR...");
muxProcess->kill();
muxProcess->waitForFinished();

View File

@ -1,8 +1,9 @@
#ifndef MUX_FORM_H_
#define MUX_FORM_H_
#include <QtGui>
#include "ui_muxForm.h"
#include <QDialog>
class QProcess;
class Ui_muxForm;
class MuxForm: public QDialog//QWidget
{
@ -22,7 +23,7 @@ private slots:
void onAbort();
private:
int errCnt;
Ui_muxForm ui;
Ui_muxForm* ui;
QProcess* muxProcess;
};

21
tsMuxerGUI/tsMuxerGUI.pro Normal file
View File

@ -0,0 +1,21 @@
# this file exists only because of the problems with running CMake with Qt
# projects under MXE.
# you're free to use it for compiling the GUI if you don't want to use CMake for
# whatever reason, but keep in mind that it will be removed once the relevant
# bugs in MXE are resolved.
TEMPLATE = app
TARGET = tsMuxerGUI
QT = core gui widgets multimedia
CONFIG += c++14 strict_c++
HEADERS += tsmuxerwindow.h lang_codes.h muxForm.h checkboxedheaderview.h \
codecinfo.h
SOURCES += main.cpp tsmuxerwindow.cpp muxForm.cpp checkboxedheaderview.cpp
FORMS += tsmuxerwindow.ui muxForm.ui
RESOURCES += images.qrc
TRANSLATIONS =
win32 {
RC_FILE += icon.rc
}

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,25 @@
#ifndef TSMUXER_H_
#define TSMUXER_H_
#include <QtGui>
#include <QFileDialog>
#include <QProcess>
#include <QSound>
#include "codecinfo.h"
#include "ui_tsmuxerwindow.h"
#include "muxForm.h"
#include <QWidget>
#include <QHeaderView>
#include <QProcess>
#include <QTimer>
class QFileDialog;
class QTemporaryFile;
class QSound;
class QTableWidgetItem;
class QComboBox;
class MuxForm;
namespace Ui {
class TsMuxerWindow;
}
class QnCheckBoxedHeaderView;
typedef QList<double> ChapterList;
@ -17,93 +29,6 @@ enum MplsType {
MPLS_M2TS,
};
class QnCheckBoxedHeaderView: public QHeaderView {
Q_OBJECT
typedef QHeaderView base_type;
public:
explicit QnCheckBoxedHeaderView(QWidget *parent = nullptr);
Qt::CheckState checkState() const;
void setCheckState(Qt::CheckState state);
signals:
void checkStateChanged(Qt::CheckState state);
protected:
void paintEvent(QPaintEvent *e) override;
void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const override;
QSize sectionSizeFromContents(int logicalIndex) const override;
private slots:
void at_sectionClicked(int logicalIndex);
private:
Qt::CheckState m_checkState;
int m_checkColumnIndex;
};
struct QtvCodecInfo
{
QtvCodecInfo():
trackID(0),
width(0),
height(0),
displayName(),
programName(),
descr(),
lang(),
delay(0),
subTrack(0),
dtsDownconvert(false),
isSecondary(false),
offsetId(-1),
maxPgOffsets(0),
fileList(),
checkFPS(false),
checkLevel(false),
addSEIMethod(1),
addSPS(true),
delPulldown(-1),
fpsText(),
fpsTextOrig(),
levelText(),
nested(0),
parent(nullptr),
child(nullptr),
bindFps(true),
mplsFiles(),
arText(),
enabledByDefault(true) {}
int trackID;
int width;
int height;
QString displayName;
QString programName;
QString descr;
QString lang;
int delay;
int subTrack;
bool dtsDownconvert;
bool isSecondary;
int offsetId;
int maxPgOffsets;
QList<QString> fileList;
bool checkFPS;
bool checkLevel;
int addSEIMethod;
bool addSPS;
int delPulldown;
QString fpsText;
QString fpsTextOrig;
QString levelText;
// for append
int nested;
QtvCodecInfo* parent;
QtvCodecInfo* child;
bool bindFps;
QStringList mplsFiles;
QString arText;
bool enabledByDefault;
};
class TsMuxerWindow: public QWidget
{
Q_OBJECT
@ -151,7 +76,7 @@ private slots:
void saveMetaFileBtnClick();
void continueAppendFile();
void continueAddFile();
void getCodecInfo();
void onTsMuxerCodecInfoReceived();
void addFile();
void appendFile();
void onOpacityTimer();
@ -191,6 +116,7 @@ private:
QString getSrtParams();
int findLangByCode(const QString& code);
void setComboBoxText(QComboBox* comboBox, const QString& text);
QtvCodecInfo* getCodecInfo(int idx);
QtvCodecInfo* getCurrentCodec();
void delTracksByFileName(const QString& fileName);
void deleteTrack(int idx);
@ -209,7 +135,7 @@ private:
//QTemporaryFile* tempFile;
//QString tempFileName;
QString metaName;
Ui::TsMuxerWindow ui;
Ui::TsMuxerWindow* ui;
QFileDialog* openFileDialog;
int disableUpdatesCnt;
bool processFinished;
@ -224,7 +150,7 @@ private:
QString oldFileName;
bool outFileNameDisableChange;
QString saveDialogFilter;
MuxForm muxForm;
MuxForm* muxForm;
QString newFileName;
QList<QtvCodecInfo> codecList;
ChapterList chapters;

View File

@ -2550,6 +2550,7 @@ p, li { white-space: pre-wrap; }
&lt;li style=&quot; font-size:8pt;&quot; style=&quot; margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Demux option. &lt;/li&gt;&lt;/ul&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Supported videocodecs: &lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;&quot;&gt;&lt;li style=&quot; font-size:8pt;&quot; style=&quot; margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;H.264/MVC &lt;/li&gt;
&lt;li style=&quot; font-size:8pt;&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;H.265/HEVC; &lt;/li&gt;
&lt;li style=&quot; font-size:8pt;&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Microsoft VC-1; &lt;/li&gt;
&lt;li style=&quot; font-size:8pt;&quot; style=&quot; margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;MPEG-2. &lt;/li&gt;&lt;/ul&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Supported audiocodecs: &lt;/span&gt;&lt;/p&gt;
@ -2569,9 +2570,11 @@ p, li { white-space: pre-wrap; }
&lt;li style=&quot; font-size:8pt;&quot; style=&quot; margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;MP4/MOV. &lt;/li&gt;&lt;/ul&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Main features: &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;&quot;&gt;&lt;/p&gt;
&lt;ul style=&quot;margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;&quot;&gt;&lt;li style=&quot; font-size:8pt;&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;3D blu-ray support;&lt;/li&gt;
&lt;li style=&quot; font-size:8pt;&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Automatic or manual fps adjustment while mixing; &lt;/li&gt;&lt;/ul&gt;
&lt;ul style=&quot;margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;&quot;&gt;&lt;li style=&quot; font-size:8pt;&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Level changing as well as SEI, SPS/PPS elements and NAL unit delimiter cycle insertion while mixing H.264; &lt;/li&gt;
&lt;ul style=&quot;margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;&quot;&gt;
&lt;li style=&quot; font-size:8pt;&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;3D blu-ray support;&lt;/li&gt;
&lt;li style=&quot; font-size:8pt;&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;UHD HDR10 and HDR10+ support; &lt;/li&gt;
&lt;li style=&quot; font-size:8pt;&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Automatic or manual fps adjustment while mixing; &lt;/li&gt;
&lt;li style=&quot; font-size:8pt;&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Level changing as well as SEI, SPS/PPS elements and NAL unit delimiter cycle insertion while mixing H.264; &lt;/li&gt;
&lt;li style=&quot; font-size:8pt;&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Audio tracks and subtitles time shifting; &lt;/li&gt;
&lt;li style=&quot; font-size:8pt;&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Ability to extract DTS core from DTS-HD; &lt;/li&gt;
&lt;li style=&quot; font-size:8pt;&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Ability to extract AC3 core from True-HD; &lt;/li&gt;