diff options
author | Arno <arno@disconnect.de> | 2016-09-03 21:03:34 +0200 |
---|---|---|
committer | Arno <arno@disconnect.de> | 2016-09-03 21:03:34 +0200 |
commit | e11e257f88726fd04774bf0ca4584d1678bc7f9b (patch) | |
tree | 848c1f16d09f1a06afd7d638f40b6e39e4cd6ead | |
parent | b49c6828a92590311712d766d54c15596f13addf (diff) | |
download | ShemovCleaner-e11e257f88726fd04774bf0ca4584d1678bc7f9b.tar.gz ShemovCleaner-e11e257f88726fd04774bf0ca4584d1678bc7f9b.tar.bz2 ShemovCleaner-e11e257f88726fd04774bf0ca4584d1678bc7f9b.zip |
Add detailed video dialog
Show each and everything ffprobe can extract from a video file and
display it as a tree.
-rw-r--r-- | filedisplay.cpp | 98 | ||||
-rw-r--r-- | filedisplay.h | 20 | ||||
-rw-r--r-- | helper.cpp | 67 | ||||
-rw-r--r-- | helper.h | 17 |
4 files changed, 202 insertions, 0 deletions
diff --git a/filedisplay.cpp b/filedisplay.cpp index bce77d9..fe832b1 100644 --- a/filedisplay.cpp +++ b/filedisplay.cpp @@ -11,13 +11,23 @@ #include <QPushButton> #include <QGroupBox> #include <QDir> +#include <QTreeView> +#include <QStandardItemModel> +#include <QJsonDocument> +#include <QJsonObject> +#include <QJsonArray> +#include <QSettings> +#include <QHeaderView> #include "filedisplay.h" +#include "helper.h" FileDisplay::FileDisplay(QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f) { mTab = new QTabWidget; mDBData = new DBData; + mFileData = new FileData; mTab->addTab(mDBData, tr("Database")); + mTab->addTab(mFileData, tr("File")); //button layout QHBoxLayout *buttonL = new QHBoxLayout; @@ -39,6 +49,7 @@ void FileDisplay::setFileData(const QString &fullPath, const QString &md5Sum) { mFullPath = fullPath; mMd5 = md5Sum; mDBData->setFileData(fullPath, md5Sum); + mFileData->setFileData(fullPath); } DBData::DBData(QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f) { @@ -153,3 +164,90 @@ void DBData::gatherData(){ QString genresText = genres.join("\n"); mGenres->setText(genresText); } + +FileData::FileData(QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f){ + mView = new QTreeView; + mModel = new QStandardItemModel; + mView->setModel(mModel); + QGroupBox *gb = new QGroupBox(tr("ffprobe Output")); + QHBoxLayout *gbLayout = new QHBoxLayout; + gbLayout->addWidget(mView); + gb->setLayout(gbLayout); + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addWidget(gb); + setLayout(mainLayout); +} + +FileData::~FileData(){ + writeHeaderData(); +} + +void FileData::setFileData(const QString &fullPath){ + mModel->clear(); + mModel->setHorizontalHeaderLabels(QStringList() << tr("Key") << tr("Value")); + readHeaderData(); + QJsonDocument jDoc = Helper::ffpmegData(fullPath); + QStandardItem *rootItem = mModel->invisibleRootItem(); + rootItem->setColumnCount(2); + QStandardItem *streamItem = new QStandardItem(tr("Stream")); + streamItem->setEditable(false); + rootItem->appendRow(streamItem); + QStandardItem *formatItem = new QStandardItem(tr("Format")); + formatItem->setEditable(false); + rootItem->appendRow(formatItem); + + QJsonObject jObject = jDoc.object(); + FileDataRecursive(jObject.value("format"), formatItem); + QJsonArray streams = jObject.value("streams").toArray(); + for(int i = 0; i < streams.size(); ++i){ + QString itemName = QString(tr("Stream %1 [%2]")).arg(QString::number(i + 1)).arg(streams.at(i).toObject().value("codec_type").toString()); + QStandardItem *item = new QStandardItem(itemName); + item->setEditable(false); + QStandardItem *item2 = new QStandardItem; + item2->setEditable(false); + streamItem->appendRow(QList<QStandardItem*>() << item << item2); + QStandardItem *next = streamItem->child(i, 0); + FileDataRecursive(streams.at(i), next); + } + QModelIndex i1 = mModel->indexFromItem(streamItem); + mView->expand(i1); + QModelIndex i2 = mModel->indexFromItem(formatItem); + mView->expand(i2); +} + +void FileData::FileDataRecursive(QJsonValue start, QStandardItem *appendTo){ + QJsonObject startObject = start.toObject(); + QJsonObject::const_iterator it; + for(it = startObject.constBegin(); it != startObject.constEnd(); ++it){ + QVariantList data = QVariantList() << it.key() << it.value().toVariant(); + if(it.key() == "duration"){ + qint64 seconds = it.value().toString().toDouble(); + Helper::Duration dur(seconds); + data[1] = dur.toString(); + } + if(it.key() == "bit_rate"){ + qint64 br = it.value().toString().toInt() / 1000; + data[1] = QString("%1 kb/s").arg(QString::number(br)); + } + QStandardItem *key = new QStandardItem(data.at(0).toString()); + key->setEditable(false); + QStandardItem *value = new QStandardItem(data.at(1).toString()); + value->setEditable(false); + appendTo->appendRow(QList<QStandardItem*>() << key << value); + QStandardItem *newItem = appendTo->child(0, 0); + FileDataRecursive(*it, newItem); + } +} + +void FileData::writeHeaderData(){ + QSettings s; + s.setValue("fd/fileheaders", mView->header()->saveState()); +} + +void FileData::readHeaderData(){ + QSettings s; + QByteArray headers = s.value("fd/fileheaders").toByteArray(); + if(!headers.isEmpty()){ + mView->header()->restoreState(headers); + } +} diff --git a/filedisplay.h b/filedisplay.h index 93b6a4a..10d93d6 100644 --- a/filedisplay.h +++ b/filedisplay.h @@ -7,7 +7,11 @@ class QLineEdit; class QTextEdit; class QTabWidget; +class QTreeView; +class QStandardItemModel; +class QStandardItem; class DBData; +class FileData; class FileDisplay : public QDialog { Q_OBJECT @@ -18,6 +22,7 @@ class FileDisplay : public QDialog { private: QTabWidget *mTab; DBData *mDBData; + FileData *mFileData; QString mFullPath; QString mMd5; }; @@ -37,4 +42,19 @@ class DBData : public QWidget { QTextEdit *mGenres; }; +class FileData : public QWidget { + Q_OBJECT + public: + explicit FileData(QWidget *parent = 0, Qt::WindowFlags f = 0); + ~FileData(); + void setFileData(const QString &fullPath); + + private: + void FileDataRecursive(QJsonValue start, QStandardItem *appendTo); + void writeHeaderData(); + void readHeaderData(); + QTreeView *mView; + QStandardItemModel *mModel; +}; + #endif // FILEDISPLAY_H @@ -2,6 +2,8 @@ #include <QFileInfo> #include <QCryptographicHash> #include <QByteArray> +#include <QSettings> +#include <QProcess> #include "helper.h" @@ -47,4 +49,69 @@ namespace Helper { } return retval; } + + const QJsonDocument ffpmegData(const QString &path){ + QSettings s; + QString ffProbe = s.value("ext/ffprobe").toString(); + QStringList args; + args << "-v" << "quiet" << "-print_format" << "json" << "-show_format" << "-show_streams" << path; + QProcess ffproc; + ffproc.start(ffProbe, args); + if(!ffproc.waitForStarted()){ + return QJsonDocument(); + } + ffproc.waitForFinished(); + QByteArray ffData = ffproc.readAllStandardOutput(); + + return QJsonDocument::fromJson(ffData); + } + + Duration::Duration() : mHours(0), mMinutes(0), mSeconds(0) {} + + Duration::Duration(qint64 seconds){ + int sec(0), min(0), h(0); + // get hours + h = (seconds / 60 / 60); + // remaining minutes + min = (seconds / 60) % 60; + // seconds + sec = seconds % 60; + mHours = h; + mMinutes = min; + mSeconds = sec; + } + + Duration::Duration(const QString &dur) : mHours(0), mMinutes(0), mSeconds(0){ + QStringList parts = dur.split(':'); + if(parts.size() == 3){ + mHours = parts.at(0).toInt(); + mMinutes = parts.at(1).toInt(); + mSeconds = parts.at(2).toInt(); + } + } + + Duration Duration::operator+(const Duration &dur) const{ + Duration retval; + retval.mSeconds = mSeconds + dur.mSeconds; + retval.mMinutes = mMinutes + dur.mMinutes + retval.mSeconds / 60; + retval.mSeconds %= 60; + retval.mHours = mHours + dur.mHours + retval.mMinutes / 60; + retval.mMinutes %= 60; + return retval; + } + + const QString Duration::toString() const { + QString retval = QString("%1:%2:%3").arg(QString::number(mHours), 2, '0').arg(QString::number(mMinutes), 2, '0').arg(QString::number(mSeconds), 2, '0'); + return retval; + } + + bool Duration::isNull() const { + return mHours == 0 && mMinutes == 0 && mSeconds == 0; + } + + qint64 Duration::toSeconds() const { + qint64 retval; + retval = mHours * 60 * 60 + mMinutes * 60 + mSeconds; + return retval; + } } @@ -2,9 +2,26 @@ #define HELPER_H #include <QString> +#include <QJsonDocument> namespace Helper { const QString md5Sum(const QString &path); + const QJsonDocument ffpmegData(const QString &path); + class Duration { + public: + Duration(); + Duration(qint64 seconds); + Duration(const QString &dur); + Duration operator+(const Duration &dur) const; + const QString toString() const; + bool isNull() const; + qint64 toSeconds() const; + + private: + int mHours; + int mMinutes; + int mSeconds; + }; } #endif // HELPER_H |