added FileInfoModel as alternative to webview-based file info
This commit is contained in:
parent
0ac33e333c
commit
6f6b410a8c
|
@ -49,6 +49,7 @@ set(WIDGETS_HEADER_FILES
|
|||
gui/tagedit.h
|
||||
gui/tagfieldedit.h
|
||||
gui/tageditorwidget.h
|
||||
gui/fileinfomodel.h
|
||||
dbquery/dbquery.h
|
||||
gui/dbquerywidget.h
|
||||
misc/networkaccessmanager.h
|
||||
|
@ -78,6 +79,7 @@ set(WIDGETS_SRC_FILES
|
|||
gui/tagedit.cpp
|
||||
gui/tagfieldedit.cpp
|
||||
gui/tageditorwidget.cpp
|
||||
gui/fileinfomodel.cpp
|
||||
dbquery/dbquery.cpp
|
||||
gui/dbquerywidget.cpp
|
||||
misc/networkaccessmanager.cpp
|
||||
|
|
|
@ -7,10 +7,7 @@
|
|||
#elif defined(GUI_QTQUICK)
|
||||
#endif
|
||||
|
||||
// include configuration from separate header file when building with CMake
|
||||
#ifndef APP_METADATA_AVAIL
|
||||
#include "resources/config.h"
|
||||
#endif
|
||||
|
||||
#if defined(GUI_QTWIDGETS) || defined(GUI_QTQUICK)
|
||||
# include <qtutilities/resources/qtconfigarguments.h>
|
||||
|
|
|
@ -0,0 +1,593 @@
|
|||
#include "./fileinfomodel.h"
|
||||
|
||||
#include <tagparser/signature.h>
|
||||
#include <tagparser/mediafileinfo.h>
|
||||
#include <tagparser/abstractcontainer.h>
|
||||
#include <tagparser/matroska/matroskacontainer.h>
|
||||
#include <tagparser/matroska/matroskaeditionentry.h>
|
||||
#include <tagparser/mp4/mp4container.h>
|
||||
#include <tagparser/abstracttrack.h>
|
||||
#include <tagparser/abstractattachment.h>
|
||||
#include <tagparser/notification.h>
|
||||
|
||||
#include <c++utilities/chrono/datetime.h>
|
||||
#include <c++utilities/conversion/stringconversion.h>
|
||||
|
||||
#if defined(GUI_QTWIDGETS)
|
||||
# include <QApplication>
|
||||
# include <QStyle>
|
||||
# include <QIcon>
|
||||
#elif defined(GUI_QTQUICK)
|
||||
# include <QGuiApplication>
|
||||
# include <QIcon>
|
||||
#elif !defined(GUI_NONE)
|
||||
# define GUI_NONE
|
||||
#endif
|
||||
#include <QStringBuilder>
|
||||
|
||||
using namespace std;
|
||||
using namespace ChronoUtilities;
|
||||
using namespace ConversionUtilities;
|
||||
using namespace Media;
|
||||
|
||||
namespace QtGui {
|
||||
|
||||
/*!
|
||||
* \cond
|
||||
*/
|
||||
|
||||
// helper functions and methods
|
||||
|
||||
QStandardItem *defaultItem(const QString &text)
|
||||
{
|
||||
auto *item = new QStandardItem(text);
|
||||
item->setEditable(false);
|
||||
return item;
|
||||
}
|
||||
|
||||
class ItemHelper
|
||||
{
|
||||
public:
|
||||
ItemHelper(QStandardItem *item) :
|
||||
m_item(item)
|
||||
{
|
||||
m_item->setEditable(false);
|
||||
}
|
||||
|
||||
void appendRow(const QString &label, const QString &text)
|
||||
{
|
||||
if(!text.isEmpty()) {
|
||||
m_item->appendRow(QList<QStandardItem *>()
|
||||
<< defaultItem(label)
|
||||
<< defaultItem(text));
|
||||
}
|
||||
}
|
||||
|
||||
void appendRow(const QString &label, const char *text)
|
||||
{
|
||||
appendRow(label, QString::fromLocal8Bit(text));
|
||||
}
|
||||
|
||||
void appendRow(const QString &label, const string &text)
|
||||
{
|
||||
if(!text.empty()) {
|
||||
appendRow(label, text.data());
|
||||
}
|
||||
}
|
||||
|
||||
void appendRow(const QString &label, DateTime dateTime)
|
||||
{
|
||||
if(!dateTime.isNull()) {
|
||||
appendRow(label, dateTime.toString());
|
||||
}
|
||||
}
|
||||
|
||||
void appendRow(const QString &label, TimeSpan timeSpan)
|
||||
{
|
||||
if(!timeSpan.isNull()) {
|
||||
appendRow(label, timeSpan.toString(TimeSpanOutputFormat::WithMeasures));
|
||||
}
|
||||
}
|
||||
|
||||
void appendRow(const QString &label, uint64 number)
|
||||
{
|
||||
if(number) {
|
||||
appendRow(label, QString::number(number));
|
||||
}
|
||||
}
|
||||
|
||||
void appendRow(const QString &label, const Margin &margin)
|
||||
{
|
||||
if(!margin.isNull()) {
|
||||
appendRow(label, margin.toString());
|
||||
}
|
||||
}
|
||||
|
||||
void appendRow(const QString &label, const Size &size)
|
||||
{
|
||||
if(!size.isNull()) {
|
||||
appendRow(label, size.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
QStandardItem *m_item;
|
||||
};
|
||||
|
||||
void addNotifications(Media::NotificationList *notifications, QStandardItem *parent)
|
||||
{
|
||||
Notification::sortByTime(*notifications);
|
||||
for(Notification ¬ification : *notifications) {
|
||||
QList<QStandardItem *> notificationRow;
|
||||
notificationRow.reserve(3);
|
||||
|
||||
auto *firstItem = defaultItem(QString::fromLocal8Bit(notification.creationTime().toString().data()));
|
||||
switch(notification.type()) {
|
||||
case NotificationType::Critical:
|
||||
firstItem->setIcon(FileInfoModel::errorIcon());
|
||||
break;
|
||||
case NotificationType::Warning:
|
||||
firstItem->setIcon(FileInfoModel::warningIcon());
|
||||
break;
|
||||
case NotificationType::Information:
|
||||
firstItem->setIcon(FileInfoModel::informationIcon());
|
||||
break;
|
||||
case NotificationType::Debug:
|
||||
firstItem->setIcon(FileInfoModel::debugIcon());
|
||||
break;
|
||||
}
|
||||
parent->appendRow(QList<QStandardItem *>()
|
||||
<< firstItem
|
||||
<< defaultItem(QString::fromLocal8Bit(notification.context().data()))
|
||||
<< defaultItem(QString::fromLocal8Bit(notification.message().data())));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<class ElementType, bool isAdditional = false> void addElementNode(ElementType *element, QStandardItem *parent)
|
||||
{
|
||||
while(element) {
|
||||
if(element->isParsed()) {
|
||||
auto *firstItem = defaultItem(QString::fromLatin1(element->idToString().data()));
|
||||
parent->appendRow(QList<QStandardItem *>()
|
||||
<< firstItem
|
||||
<< defaultItem(QStringLiteral("offset: 0x") + QString::number(element->startOffset(), 16))
|
||||
<< defaultItem(QStringLiteral("size: 0x") + QString::number(element->totalSize(), 16)));
|
||||
if(element->firstChild()) {
|
||||
addElementNode(element->firstChild(), firstItem);
|
||||
}
|
||||
element = element->nextSibling();
|
||||
} else {
|
||||
if(!isAdditional) {
|
||||
auto *notAnalyzedItem = defaultItem(QStringLiteral("not analyzed"));
|
||||
notAnalyzedItem->setForeground(QBrush(QColor(Qt::red)));
|
||||
parent->appendRow(notAnalyzedItem);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \endcond
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \class FileInfoModel
|
||||
* \brief The FileInfoModel displays overall information from a Media::MediaFileInfo instance.
|
||||
*
|
||||
* The model assumes that the specified Media::MediaFileInfo instance has been parsed already.
|
||||
* The model is not updated automatically when the state of the Media::MediaFileInfo changes.
|
||||
* To update the model, just call setFileInfo() again.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Constructs a new instance with the specified \a fileInfo which might be nullptr.
|
||||
*/
|
||||
FileInfoModel::FileInfoModel(Media::MediaFileInfo *fileInfo, QObject *parent) :
|
||||
QStandardItemModel(parent)
|
||||
{
|
||||
setFileInfo(fileInfo);
|
||||
}
|
||||
|
||||
QVariant FileInfoModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
switch(orientation) {
|
||||
case Qt::Horizontal:
|
||||
switch(role) {
|
||||
case Qt::DisplayRole:
|
||||
switch(section) {
|
||||
case 0:
|
||||
tr("Property");
|
||||
break;
|
||||
case 1:
|
||||
tr("Value");
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns the currently assigned Media::MediaFileInfo.
|
||||
*/
|
||||
const MediaFileInfo *FileInfoModel::fileInfo() const
|
||||
{
|
||||
return m_file;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Assigns a Media::MediaFileInfo.
|
||||
* \remarks Causes updating the internal cache and resets the model.
|
||||
*/
|
||||
void FileInfoModel::setFileInfo(MediaFileInfo *fileInfo, Media::NotificationList *originalNotifications)
|
||||
{
|
||||
m_file = fileInfo;
|
||||
m_originalNotifications = originalNotifications;
|
||||
updateCache();
|
||||
}
|
||||
|
||||
#if defined(GUI_QTWIDGETS)
|
||||
const QIcon &FileInfoModel::informationIcon()
|
||||
{
|
||||
static const QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation);
|
||||
return icon;
|
||||
}
|
||||
|
||||
const QIcon &FileInfoModel::warningIcon()
|
||||
{
|
||||
static const QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning);
|
||||
return icon;
|
||||
}
|
||||
|
||||
const QIcon &FileInfoModel::errorIcon()
|
||||
{
|
||||
static const QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical);
|
||||
return icon;
|
||||
}
|
||||
|
||||
const QIcon &FileInfoModel::debugIcon()
|
||||
{
|
||||
static const QIcon icon = QIcon(QStringLiteral("/images/bug"));
|
||||
return icon;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Internally called to create to cache the items.
|
||||
*/
|
||||
void FileInfoModel::updateCache()
|
||||
{
|
||||
beginResetModel();
|
||||
clear();
|
||||
if(m_file) {
|
||||
// get container
|
||||
AbstractContainer *container = m_file->container();
|
||||
|
||||
// get root item from model
|
||||
QStandardItem *rootItem = invisibleRootItem();
|
||||
ItemHelper rootHelper(rootItem);
|
||||
|
||||
// add general information
|
||||
rootHelper.appendRow(tr("Path"), m_file->path());
|
||||
rootHelper.appendRow(tr("Size"), dataSizeToString(m_file->size()));
|
||||
const TimeSpan duration = m_file->duration();
|
||||
if(!duration.isNull()) {
|
||||
rootHelper.appendRow(tr("Duration"), duration);
|
||||
rootHelper.appendRow(tr("Overall avg. bitrate"), bitrateToString(0.0078125 * m_file->size() / duration.totalSeconds()));
|
||||
}
|
||||
const char *const mimeType = m_file->mimeType();
|
||||
if(*mimeType) {
|
||||
rootHelper.appendRow(tr("Mime-type"), mimeType);
|
||||
}
|
||||
|
||||
// 3 columns
|
||||
setItem(0, 2, new QStandardItem);
|
||||
|
||||
int currentRow;
|
||||
|
||||
// add container item (last top-level-item which is always present)
|
||||
auto *containerItem = defaultItem(tr("Container"));
|
||||
ItemHelper containerHelper(containerItem);
|
||||
setItem(currentRow = rowCount(), containerItem);
|
||||
|
||||
// -> add container name
|
||||
QString containerName;
|
||||
const char *const subversion = m_file->containerFormatSubversion();
|
||||
if(*subversion) {
|
||||
containerName = QString::fromLocal8Bit(m_file->containerFormatName()) % QChar(' ') % QString::fromLocal8Bit(m_file->containerFormatSubversion());
|
||||
} else {
|
||||
containerName = QString::fromLocal8Bit(m_file->containerFormatName());
|
||||
}
|
||||
setItem(currentRow, 1, defaultItem(containerName));
|
||||
|
||||
// container details
|
||||
if(container) {
|
||||
size_t segmentIndex = 0;
|
||||
for(const auto &title : container->titles()) {
|
||||
if(segmentIndex) {
|
||||
containerHelper.appendRow(tr("Title (segment %1)").arg(++segmentIndex), title);
|
||||
} else {
|
||||
++segmentIndex;
|
||||
containerHelper.appendRow(tr("Title"), title);
|
||||
}
|
||||
}
|
||||
containerHelper.appendRow(tr("Version"), container->version());
|
||||
containerHelper.appendRow(tr("Read version"), container->readVersion());
|
||||
containerHelper.appendRow(tr("Document type"), container->documentType());
|
||||
containerHelper.appendRow(tr("Document version"), container->doctypeVersion());
|
||||
containerHelper.appendRow(tr("Document read version"), container->doctypeReadVersion());
|
||||
}
|
||||
containerHelper.appendRow(tr("Padding size"), m_file->paddingSize());
|
||||
|
||||
// tags
|
||||
{
|
||||
const auto tags = m_file->tags();
|
||||
if(!tags.empty()) {
|
||||
auto *tagsItem = defaultItem(tr("Tags"));
|
||||
setItem(++currentRow, tagsItem);
|
||||
setItem(currentRow, 1, defaultItem(tr("%1 tag(s) assigned", 0, tags.size()).arg(tags.size())));
|
||||
|
||||
for(const Tag *tag : tags) {
|
||||
auto *tagItem = defaultItem(tag->typeName());
|
||||
ItemHelper tagHelper(tagItem);
|
||||
tagHelper.appendRow(tr("Version"), tag->version());
|
||||
tagHelper.appendRow(tr("Target level"), tag->target().toString());
|
||||
tagHelper.appendRow(tr("Size"), dataSizeToString(tag->size()));
|
||||
tagHelper.appendRow(tr("Field count"), tag->fieldCount());
|
||||
tagsItem->appendRow(tagItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// tracks
|
||||
{
|
||||
const auto tracks = m_file->tracks();
|
||||
if(!tracks.empty()) {
|
||||
auto *tracksItem = defaultItem(tr("Tracks"));
|
||||
setItem(++currentRow, tracksItem);
|
||||
setItem(currentRow, 1, defaultItem(tr("%1 track(s) contained", 0, tracks.size()).arg(tracks.size())));
|
||||
|
||||
size_t number = 0;
|
||||
for(const AbstractTrack *track : tracks) {
|
||||
auto *trackItem = defaultItem(tr("Track #%1").arg(++number));
|
||||
ItemHelper trackHelper(trackItem);
|
||||
trackHelper.appendRow(tr("ID"), track->id());
|
||||
trackHelper.appendRow(tr("Number"), track->trackNumber());
|
||||
trackHelper.appendRow(tr("Name"), track->name());
|
||||
trackHelper.appendRow(tr("Type"), track->mediaTypeName());
|
||||
const char *fmtName = track->formatName(), *fmtAbbr = track->formatAbbreviation();
|
||||
trackHelper.appendRow(tr("Format"), fmtName);
|
||||
if(strcmp(fmtName, fmtAbbr)) { // format name and abbreviation differ
|
||||
trackHelper.appendRow(tr("Abbreviation"), fmtAbbr);
|
||||
}
|
||||
if(track->version()) {
|
||||
switch(track->format().general) {
|
||||
case GeneralMediaFormat::Mpeg4Video:
|
||||
case GeneralMediaFormat::Avc:
|
||||
trackHelper.appendRow(tr("Level"), QChar('L') + QString::number(track->version()));
|
||||
break;
|
||||
default:
|
||||
trackHelper.appendRow(tr("Version"), QString::number(track->version()));
|
||||
}
|
||||
}
|
||||
fmtName = track->format().extensionName();
|
||||
trackHelper.appendRow(tr("Extension"), fmtName);
|
||||
trackHelper.appendRow(tr("Format/codec ID"), track->formatId());
|
||||
trackHelper.appendRow(tr("Size"), track->size());
|
||||
trackHelper.appendRow(tr("Duration"), track->duration());
|
||||
trackHelper.appendRow(tr("Avg. bitrate"), bitrateToString(track->bitrate()));
|
||||
trackHelper.appendRow(tr("Max. bitrate"), bitrateToString(track->maxBitrate()));
|
||||
trackHelper.appendRow(tr("Creation time"), track->creationTime());
|
||||
trackHelper.appendRow(tr("Modification time"), track->modificationTime());
|
||||
trackHelper.appendRow(tr("Language"), track->language());
|
||||
trackHelper.appendRow(tr("Compressor name"), track->compressorName());
|
||||
if(track->samplingFrequency()) {
|
||||
trackHelper.appendRow(tr("Sampling frequency"), track->extensionSamplingFrequency()
|
||||
? QString::number(track->extensionSamplingFrequency()) % QStringLiteral(" Hz / ") % QString::number(track->samplingFrequency()) % QStringLiteral(" Hz")
|
||||
: QString::number(track->samplingFrequency()) + QStringLiteral(" Hz"));
|
||||
}
|
||||
trackHelper.appendRow(tr("Sample count"), track->sampleCount());
|
||||
trackHelper.appendRow(tr("Bits per sample"), track->bitsPerSample());
|
||||
trackHelper.appendRow(tr("Quality"), track->quality());
|
||||
trackHelper.appendRow(tr("Pixel size"), track->pixelSize());
|
||||
trackHelper.appendRow(tr("Display size"), track->displaySize());
|
||||
if(track->pixelAspectRatio().isValid()) {
|
||||
trackHelper.appendRow(tr("Pixel Aspect Ratio"), QString::number(track->pixelAspectRatio().numerator) % QStringLiteral(" : ") % QString::number(track->pixelAspectRatio().denominator));
|
||||
}
|
||||
trackHelper.appendRow(tr("Cropping"), track->cropping());
|
||||
trackHelper.appendRow(tr("Resolution"), track->resolution());
|
||||
if(track->channelConfigString()) {
|
||||
trackHelper.appendRow(tr("Channel config"), track->extensionChannelConfigString()
|
||||
? QString::fromLocal8Bit(track->extensionChannelConfigString()) % QStringLiteral(" / ") % QString::fromLocal8Bit(track->channelConfigString())
|
||||
: QString::fromLocal8Bit(track->channelConfigString()));
|
||||
} else {
|
||||
trackHelper.appendRow(tr("Channel count"), track->channelCount());
|
||||
}
|
||||
trackHelper.appendRow(tr("Bit depth"), track->depth());
|
||||
trackHelper.appendRow(tr("Frames per second"), track->fps());
|
||||
trackHelper.appendRow(tr("Chroma format"), track->chromaFormat());
|
||||
QStringList labels;
|
||||
if(track->isInterlaced()) {
|
||||
labels << tr("interlaced");
|
||||
}
|
||||
if(!track->isEnabled()) {
|
||||
labels << tr("disabled");
|
||||
}
|
||||
if(track->isDefault()) {
|
||||
labels << tr("default");
|
||||
}
|
||||
if(track->isForced()) {
|
||||
labels << tr("forced");
|
||||
}
|
||||
if(track->hasLacing()) {
|
||||
labels << tr("has lacing");
|
||||
}
|
||||
if(track->isEncrypted()) {
|
||||
labels << tr("encrypted");
|
||||
}
|
||||
if(!labels.isEmpty()) {
|
||||
trackHelper.appendRow(tr("Labeled as"), labels.join(QStringLiteral(", ")));
|
||||
}
|
||||
tracksItem->appendRow(trackItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// attachments
|
||||
{
|
||||
const auto attachments = m_file->attachments();
|
||||
if(!attachments.empty()) {
|
||||
auto *attachmentsItem = defaultItem(tr("Attachments"));
|
||||
setItem(++currentRow, attachmentsItem);
|
||||
setItem(currentRow, 1, defaultItem(tr("%1 attachment(s) present", 0, attachments.size()).arg(attachments.size())));
|
||||
|
||||
size_t number = 0;
|
||||
for(const AbstractAttachment *attachment : attachments) {
|
||||
auto *attachmentItem = defaultItem(tr("Attachment #%1").arg(++number));
|
||||
ItemHelper attachHelper(attachmentItem);
|
||||
attachHelper.appendRow(tr("ID"), attachment->id());
|
||||
attachHelper.appendRow(tr("Name"), attachment->name());
|
||||
attachHelper.appendRow(tr("Size"), dataSizeToString(attachment->data()->size()));
|
||||
attachHelper.appendRow(tr("Mime-type"), attachment->mimeType());
|
||||
attachHelper.appendRow(tr("Description"), attachment->description());
|
||||
attachmentsItem->appendRow(attachmentItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// chapters/editions
|
||||
{
|
||||
size_t number = 0;
|
||||
function<void(const AbstractChapter *, QStandardItem *)> addChapter;
|
||||
addChapter = [&addChapter, &number] (const AbstractChapter *chapter, QStandardItem *parent) {
|
||||
auto *chapterItem = defaultItem(tr("Chapter #%1").arg(++number));
|
||||
ItemHelper chapterHelper(chapterItem);
|
||||
chapterHelper.appendRow(tr("ID"), chapter->id());
|
||||
for(const LocaleAwareString &name : chapter->names()) {
|
||||
static const string delim(", ");
|
||||
const string locale = joinStrings(initializer_list<string>{joinStrings(name.languages(), delim, true), joinStrings(name.countries(), delim, true)}, delim, true);
|
||||
chapterHelper.appendRow(tr("Name (%1)").arg(QString::fromLocal8Bit(locale.data())), name);
|
||||
}
|
||||
chapterHelper.appendRow(tr("Start time"), chapter->startTime());
|
||||
chapterHelper.appendRow(tr("End time"), chapter->endTime());
|
||||
QStringList labels;
|
||||
if(chapter->isHidden()) {
|
||||
labels << tr("hidden");
|
||||
}
|
||||
if(!chapter->isEnabled()) {
|
||||
labels << tr("disabled");
|
||||
}
|
||||
if(!labels.empty()) {
|
||||
chapterHelper.appendRow(tr("Labeled as"), labels.join(QStringLiteral(", ")));
|
||||
}
|
||||
if(!chapter->tracks().empty()) {
|
||||
QStringList trackIds;
|
||||
for(const uint64 id : chapter->tracks()) {
|
||||
trackIds << QString::number(id);
|
||||
}
|
||||
chapterHelper.appendRow(tr("Tracks"), trackIds.join(QStringLiteral(", ")));
|
||||
}
|
||||
for(size_t i = 0, nestedChapters = chapter->nestedChapterCount(); i < nestedChapters; ++i) {
|
||||
addChapter(chapter->nestedChapter(i), chapterItem);
|
||||
}
|
||||
parent->appendRow(chapterItem);
|
||||
};
|
||||
|
||||
if(m_file->containerFormat() == ContainerFormat::Matroska) {
|
||||
const auto &editionEntries = static_cast<const MatroskaContainer *>(container)->editionEntires();
|
||||
if(!editionEntries.empty()) {
|
||||
auto *editionsItem = defaultItem(tr("Editions"));
|
||||
setItem(++currentRow, editionsItem);
|
||||
setItem(currentRow, 1, defaultItem(tr("%1 edition(s) present", 0, editionEntries.size()).arg(editionEntries.size())));
|
||||
size_t editionNumber = 0;
|
||||
for(const auto &edition : editionEntries) {
|
||||
auto *editionItem = defaultItem(tr("Edition #%1").arg(++editionNumber));
|
||||
ItemHelper editionHelper(editionItem);
|
||||
editionHelper.appendRow(tr("ID"), edition->id());
|
||||
QStringList labels;
|
||||
if(edition->isHidden()) {
|
||||
labels << tr("hidden");
|
||||
}
|
||||
if(edition->isDefault()) {
|
||||
labels << tr("default");
|
||||
}
|
||||
if(edition->isOrdered()) {
|
||||
labels << tr("ordered");
|
||||
}
|
||||
if(!labels.isEmpty()) {
|
||||
editionHelper.appendRow(tr("Labeled as"), labels.join(QStringLiteral(", ")));
|
||||
}
|
||||
for(const auto &chapter : edition->chapters()) {
|
||||
addChapter(chapter.get(), editionItem);
|
||||
}
|
||||
editionsItem->appendRow(editionItem);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const auto chapters = m_file->chapters();
|
||||
if(!chapters.empty()) {
|
||||
auto *chaptersItem = defaultItem(tr("Chapters"));
|
||||
setItem(++currentRow, chaptersItem);
|
||||
setItem(currentRow, 1, defaultItem(tr("%1 chapter(s) present", 0, chapters.size()).arg(chapters.size())));
|
||||
for(const AbstractChapter *chapter : chapters) {
|
||||
addChapter(chapter, chaptersItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// structure
|
||||
switch(m_file->containerFormat()) {
|
||||
case ContainerFormat::Mp4:
|
||||
case ContainerFormat::QuickTime:
|
||||
case ContainerFormat::Matroska:
|
||||
case ContainerFormat::Webm:
|
||||
case ContainerFormat::Ebml: {
|
||||
auto *structureItem = defaultItem(tr("Structure"));
|
||||
switch(m_file->containerFormat()) {
|
||||
case ContainerFormat::Mp4:
|
||||
case ContainerFormat::QuickTime:
|
||||
addElementNode(static_cast<Mp4Container *>(container)->firstElement(), structureItem);
|
||||
break;
|
||||
case ContainerFormat::Matroska:
|
||||
case ContainerFormat::Webm:
|
||||
case ContainerFormat::Ebml:
|
||||
addElementNode(static_cast<MatroskaContainer *>(container)->firstElement(), structureItem);
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
setItem(++currentRow, structureItem);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
// notifications
|
||||
auto currentNotifications = m_file->gatherRelatedNotifications();
|
||||
if(!currentNotifications.empty()) {
|
||||
auto *notificationsItem= defaultItem(m_originalNotifications ? tr("Notifications (reparsing after saving)") : tr("Notifications"));
|
||||
addNotifications(¤tNotifications, notificationsItem);
|
||||
setItem(++currentRow, notificationsItem);
|
||||
}
|
||||
if(m_originalNotifications && !m_originalNotifications->empty()) {
|
||||
auto *notificationsItem = defaultItem(tr("Notifications"));
|
||||
addNotifications(m_originalNotifications, notificationsItem);
|
||||
setItem(++currentRow, notificationsItem);
|
||||
}
|
||||
|
||||
}
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
#ifndef FILEINFOMODEL_H
|
||||
#define FILEINFOMODEL_H
|
||||
|
||||
#include <QStandardItemModel>
|
||||
|
||||
#include <list>
|
||||
|
||||
namespace Media {
|
||||
class MediaFileInfo;
|
||||
class Notification;
|
||||
typedef std::list<Notification> NotificationList;
|
||||
}
|
||||
|
||||
namespace QtGui {
|
||||
|
||||
class FileInfoModel : public QStandardItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit FileInfoModel(Media::MediaFileInfo *fileInfo = nullptr, QObject *parent = nullptr);
|
||||
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||
|
||||
const Media::MediaFileInfo *fileInfo() const;
|
||||
void setFileInfo(Media::MediaFileInfo *fileInfo, Media::NotificationList *originalNotifications = nullptr);
|
||||
|
||||
#if defined(GUI_QTWIDGETS)
|
||||
static const QIcon &informationIcon();
|
||||
static const QIcon &warningIcon();
|
||||
static const QIcon &errorIcon();
|
||||
static const QIcon &debugIcon();
|
||||
#endif
|
||||
|
||||
private:
|
||||
void updateCache();
|
||||
|
||||
private:
|
||||
Media::MediaFileInfo *m_file;
|
||||
Media::NotificationList *m_originalNotifications;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FILEINFOMODEL_H
|
|
@ -4,10 +4,7 @@
|
|||
|
||||
#include "../application/settings.h"
|
||||
|
||||
// include configuration from separate header file when building with CMake
|
||||
#ifndef APP_METADATA_AVAIL
|
||||
# include "resources/config.h"
|
||||
#endif
|
||||
#include "resources/config.h"
|
||||
|
||||
#include <qtutilities/resources/qtconfigarguments.h>
|
||||
#include <qtutilities/resources/resources.h>
|
||||
|
|
|
@ -6,9 +6,7 @@
|
|||
|
||||
#include "../application/settings.h"
|
||||
#include "../misc/utility.h"
|
||||
#ifdef TAGEDITOR_NO_WEBVIEW
|
||||
# include "../misc/htmlinfo.h"
|
||||
#endif
|
||||
#include "../misc/htmlinfo.h"
|
||||
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
|
@ -322,6 +320,7 @@ void MainWindow::showSettingsDlg()
|
|||
}
|
||||
if(m_settingsDlg->exec() == QDialog::Accepted) {
|
||||
applySettingsFromDialog();
|
||||
m_ui->tagEditorWidget->applySettingsFromDialog();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -444,10 +443,10 @@ void MainWindow::saveFileInformation()
|
|||
TryLocker<> locker(fileOperationMutex());
|
||||
if(locker) {
|
||||
if(fileInfo().isOpen()) {
|
||||
const QByteArray &htmlData =
|
||||
const QByteArray htmlData =
|
||||
#ifndef TAGEDITOR_NO_WEBVIEW
|
||||
!Settings::noWebView() ?
|
||||
m_ui->tagEditorWidget->fileInfoHtml().size() :
|
||||
!m_ui->tagEditorWidget->fileInfoHtml().isEmpty() ?
|
||||
m_ui->tagEditorWidget->fileInfoHtml() :
|
||||
#endif
|
||||
HtmlInfo::generateInfo(fileInfo(), m_ui->tagEditorWidget->originalNotifications());
|
||||
if(!htmlData.isEmpty()) {
|
||||
|
|
|
@ -132,7 +132,7 @@ QWidget *EditorTempOptionPage::setupWidget()
|
|||
{
|
||||
auto *widget = EditorTempOptionPageBase::setupWidget();
|
||||
QObject::connect(ui()->selectPushButton, &QPushButton::clicked, std::bind(&EditorTempOptionPage::showDirectorySelection, this));
|
||||
ui()->notificationLabel->setText(QApplication::tr("Currently this directory must be on the same partition as the files you want to edit."));
|
||||
ui()->notificationLabel->setText(QCoreApplication::translate("QtGui::EditorTempOptionPage", "Currently this directory must be on the same partition as the files you want to edit."));
|
||||
ui()->notificationLabel->setNotificationType(NotificationType::Information);
|
||||
return widget;
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ void EditorTempOptionPage::showDirectorySelection()
|
|||
QFileDialog dlg(parentWindow());
|
||||
dlg.setModal(true);
|
||||
dlg.setFileMode(QFileDialog::DirectoryOnly);
|
||||
dlg.setWindowTitle(QApplication::translate("QtGui::EditorTempOptionPage", "Select directory to store temporary files"));
|
||||
dlg.setWindowTitle(QCoreApplication::translate("QtGui::EditorTempOptionPage", "Select directory to store temporary files"));
|
||||
dlg.setDirectory(ui()->pathLineEdit->text());
|
||||
if(dlg.exec() == QFileDialog::Accepted && dlg.selectedFiles().size() == 1) {
|
||||
ui()->pathLineEdit->setText(dlg.selectedFiles().front());
|
||||
|
|
|
@ -3,21 +3,21 @@
|
|||
|
||||
#include "./previousvaluehandling.h"
|
||||
|
||||
#include <c++utilities/application/global.h>
|
||||
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QWidget>
|
||||
|
||||
#include <initializer_list>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QFormLayout;
|
||||
class QVBoxLayout;
|
||||
QT_END_NAMESPACE
|
||||
QT_FORWARD_DECLARE_CLASS(QFormLayout)
|
||||
QT_FORWARD_DECLARE_CLASS(QVBoxLayout)
|
||||
|
||||
namespace Media {
|
||||
class Tag;
|
||||
class TagValue;
|
||||
enum class KnownField : unsigned int;
|
||||
DECLARE_ENUM(KnownField, unsigned int)
|
||||
}
|
||||
|
||||
namespace QtGui {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "./tagedit.h"
|
||||
#include "./attachmentsedit.h"
|
||||
#include "./entertargetdialog.h"
|
||||
#include "./fileinfomodel.h"
|
||||
|
||||
#include "../application/settings.h"
|
||||
#include "../misc/htmlinfo.h"
|
||||
|
@ -38,6 +39,7 @@
|
|||
#include <QFileSystemWatcher>
|
||||
#include <QMenu>
|
||||
#include <QCheckBox>
|
||||
#include <QTreeView>
|
||||
#include <QtConcurrent>
|
||||
#if defined(TAGEDITOR_NO_WEBVIEW)
|
||||
#elif defined(TAGEDITOR_USE_WEBENGINE)
|
||||
|
@ -79,6 +81,11 @@ enum LoadingResult : char
|
|||
TagEditorWidget::TagEditorWidget(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
m_ui(new Ui::TagEditorWidget),
|
||||
#ifndef TAGEDITOR_NO_WEBVIEW
|
||||
m_infoWebView(nullptr),
|
||||
#endif
|
||||
m_infoModel(nullptr),
|
||||
m_infoTreeView(nullptr),
|
||||
m_nextFileAfterSaving(false),
|
||||
m_makingResultsAvailable(false),
|
||||
m_abortClicked(false)
|
||||
|
@ -444,6 +451,9 @@ void TagEditorWidget::updateFileStatusStatus()
|
|||
m_infoWebView->setEnabled(opened);
|
||||
}
|
||||
#endif
|
||||
if(m_infoTreeView) {
|
||||
m_infoTreeView->setEnabled(opened);
|
||||
}
|
||||
// inform the main window about the file status change as well
|
||||
emit fileStatusChange(opened, hasTag);
|
||||
}
|
||||
|
@ -542,14 +552,34 @@ void TagEditorWidget::initInfoView()
|
|||
{
|
||||
#ifndef TAGEDITOR_NO_WEBVIEW
|
||||
if(!Settings::noWebView() && !m_infoWebView) {
|
||||
if(m_infoTreeView) {
|
||||
m_infoTreeView->deleteLater();
|
||||
m_infoTreeView = nullptr;
|
||||
}
|
||||
if(m_infoModel) {
|
||||
m_infoModel->deleteLater();
|
||||
m_infoModel = nullptr;
|
||||
}
|
||||
m_infoWebView = new WEB_VIEW_PROVIDER(m_ui->tagSplitter);
|
||||
m_infoWebView->setAcceptDrops(false);
|
||||
m_infoWebView->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(m_infoWebView, &QWidget::customContextMenuRequested, this, &TagEditorWidget::showInfoWebViewContextMenu);
|
||||
m_ui->tagSplitter->addWidget(m_infoWebView);
|
||||
} else if(Settings::noWebView() && m_infoWebView) {
|
||||
m_infoWebView->deleteLater();
|
||||
m_infoWebView = nullptr;
|
||||
} else if(Settings::noWebView() && !m_infoTreeView) {
|
||||
if(m_infoWebView) {
|
||||
m_infoWebView->deleteLater();
|
||||
m_infoWebView = nullptr;
|
||||
}
|
||||
#endif
|
||||
if(!m_infoTreeView) {
|
||||
m_infoTreeView = new QTreeView(this);
|
||||
m_ui->tagSplitter->addWidget(m_infoTreeView);
|
||||
}
|
||||
if(!m_infoModel) {
|
||||
m_infoModel = new FileInfoModel(m_fileInfo.isOpen() ? &m_fileInfo : nullptr, this);
|
||||
m_infoTreeView->setModel(m_infoModel);
|
||||
}
|
||||
#ifndef TAGEDITOR_NO_WEBVIEW
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -570,6 +600,9 @@ void TagEditorWidget::updateInfoView()
|
|||
}
|
||||
}
|
||||
#endif
|
||||
if(m_infoModel) {
|
||||
m_infoModel->setFileInfo(m_fileInfo.isOpen() ? &m_fileInfo : nullptr); // resets the model
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef TAGEDITOR_NO_WEBVIEW
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
QT_FORWARD_DECLARE_CLASS(QFileSystemWatcher)
|
||||
QT_FORWARD_DECLARE_CLASS(QMenu)
|
||||
QT_FORWARD_DECLARE_CLASS(QTreeView)
|
||||
#ifndef TAGEDITOR_NO_WEBVIEW
|
||||
QT_FORWARD_DECLARE_CLASS(WEB_VIEW_PROVIDER)
|
||||
#endif
|
||||
|
@ -37,6 +38,7 @@ class TagEditorWidget;
|
|||
}
|
||||
|
||||
class TagEdit;
|
||||
class FileInfoModel;
|
||||
|
||||
class TagEditorWidget : public QWidget
|
||||
{
|
||||
|
@ -73,6 +75,8 @@ public slots:
|
|||
bool applyEntriesAndSaveChangings();
|
||||
bool deleteAllTagsAndSave();
|
||||
void closeFile();
|
||||
// misc
|
||||
void applySettingsFromDialog();
|
||||
|
||||
signals:
|
||||
/*!
|
||||
|
@ -104,7 +108,6 @@ private slots:
|
|||
void showFile(char result);
|
||||
void handleReturnPressed();
|
||||
void handleKeepPreviousValuesActionTriggered(QAction *action);
|
||||
void applySettingsFromDialog();
|
||||
void addTag(const std::function<Media::Tag *(Media::MediaFileInfo &)> &createTag);
|
||||
void removeTag(Media::Tag *tag);
|
||||
void changeTarget(Media::Tag *tag);
|
||||
|
@ -139,6 +142,8 @@ private:
|
|||
#ifndef TAGEDITOR_NO_WEBVIEW
|
||||
WEB_VIEW_PROVIDER *m_infoWebView;
|
||||
#endif
|
||||
FileInfoModel *m_infoModel;
|
||||
QTreeView *m_infoTreeView;
|
||||
// tag, file, directory management
|
||||
QString m_currentPath;
|
||||
QFileSystemWatcher *m_fileWatcher;
|
||||
|
|
|
@ -17,17 +17,17 @@
|
|||
#include <c++utilities/conversion/stringconversion.h>
|
||||
|
||||
#if defined(GUI_QTWIDGETS)
|
||||
#include <QApplication>
|
||||
#include <QStyle>
|
||||
# include <QApplication>
|
||||
# include <QStyle>
|
||||
#elif defined(GUI_QTQUICK)
|
||||
#include <QGuiApplication>
|
||||
# include <QGuiApplication>
|
||||
#elif !defined(GUI_NONE)
|
||||
#define GUI_NONE
|
||||
# define GUI_NONE
|
||||
#endif
|
||||
#ifndef GUI_NONE
|
||||
#include <QFont>
|
||||
#include <QFontMetrics>
|
||||
#include <QIcon>
|
||||
# include <QFont>
|
||||
# include <QFontMetrics>
|
||||
# include <QIcon>
|
||||
#endif
|
||||
#include <QString>
|
||||
#include <QStringBuilder>
|
||||
|
@ -36,7 +36,7 @@
|
|||
#include <QByteArray>
|
||||
#include <QXmlStreamWriter>
|
||||
#ifdef QT_DEBUG
|
||||
#include <QFile>
|
||||
# include <QFile>
|
||||
#endif
|
||||
|
||||
#include <list>
|
||||
|
@ -512,8 +512,7 @@ public:
|
|||
rowMaker.mkRow(QCoreApplication::translate("HtmlInfo", "Type"), qstr(track->mediaTypeName()));
|
||||
const char *fmtName = track->formatName(), *fmtAbbr = track->formatAbbreviation();
|
||||
rowMaker.mkRow(QCoreApplication::translate("HtmlInfo", "Format"), QCoreApplication::translate("HtmlInfo", "The unabbreviated name of the track's format."), qstr(fmtName));
|
||||
if(strcmp(fmtName, fmtAbbr)) {
|
||||
// format name and abbreviation differ
|
||||
if(strcmp(fmtName, fmtAbbr)) { // format name and abbreviation differ
|
||||
rowMaker.mkRow(QCoreApplication::translate("HtmlInfo", "Abbreviation"), QCoreApplication::translate("HtmlInfo", "The abbreviated name of the track's format."), qstr(fmtAbbr));
|
||||
}
|
||||
if(track->version()) {
|
||||
|
@ -579,7 +578,7 @@ public:
|
|||
if(!track->displaySize().isNull()) {
|
||||
rowMaker.mkRow(QCoreApplication::translate("HtmlInfo", "Display size"), qstr(track->displaySize().toString()));
|
||||
}
|
||||
if(!track->pixelAspectRatio().isValid()) {
|
||||
if(track->pixelAspectRatio().isValid()) {
|
||||
rowMaker.mkRow(QCoreApplication::translate("HtmlInfo", "Pixel Aspect Ratio"), QString::number(track->pixelAspectRatio().numerator) % QStringLiteral(" : ") % QString::number(track->pixelAspectRatio().denominator));
|
||||
}
|
||||
if(!track->cropping().isNull()) {
|
||||
|
@ -606,27 +605,27 @@ public:
|
|||
if(track->chromaFormat()) {
|
||||
rowMaker.mkRow(QCoreApplication::translate("HtmlInfo", "Chroma format"), qstr(track->chromaFormat()));
|
||||
}
|
||||
list<string> labels;
|
||||
QStringList labels;
|
||||
if(track->isInterlaced()) {
|
||||
labels.push_back("interlaced");
|
||||
labels << QCoreApplication::translate("HtmlInfo", "interlaced");
|
||||
}
|
||||
if(!track->isEnabled()) {
|
||||
labels.push_back("disabled");
|
||||
labels << QCoreApplication::translate("HtmlInfo", "disabled");
|
||||
}
|
||||
if(track->isDefault()) {
|
||||
labels.push_back("default");
|
||||
labels << QCoreApplication::translate("HtmlInfo", "default");
|
||||
}
|
||||
if(track->isForced()) {
|
||||
labels.push_back("forced");
|
||||
labels << QCoreApplication::translate("HtmlInfo", "forced");
|
||||
}
|
||||
if(track->hasLacing()) {
|
||||
labels.push_back("has lacing");
|
||||
labels << QCoreApplication::translate("HtmlInfo", "has lacing");
|
||||
}
|
||||
if(track->isEncrypted()) {
|
||||
labels.push_back("encrypted");
|
||||
labels << QCoreApplication::translate("HtmlInfo", "encrypted");
|
||||
}
|
||||
if(labels.size()) {
|
||||
rowMaker.mkRow(QCoreApplication::translate("HtmlInfo", "Labeled as"), qstr(joinStrings(labels, ", ")));
|
||||
if(!labels.isEmpty()) {
|
||||
rowMaker.mkRow(QCoreApplication::translate("HtmlInfo", "Labeled as"), labels.join(QStringLiteral(", ")));
|
||||
}
|
||||
rowMaker.endSubTab();
|
||||
}
|
||||
|
@ -662,26 +661,26 @@ public:
|
|||
}
|
||||
for(const LocaleAwareString &name : chapter.names()) {
|
||||
static const string delim(", ");
|
||||
string locale = joinStrings(initializer_list<string>{joinStrings(name.languages(), delim, true), joinStrings(name.countries(), delim, true)}, delim, true);
|
||||
const string locale = joinStrings(initializer_list<string>{joinStrings(name.languages(), delim, true), joinStrings(name.countries(), delim, true)}, delim, true);
|
||||
rowMaker.mkRow(QCoreApplication::translate("HtmlInfo", "Name (%1)").arg(qstr(locale)), qstr(name));
|
||||
}
|
||||
if(chapter.startTime().totalTicks() > 0) {
|
||||
if(!chapter.startTime().isNull()) {
|
||||
rowMaker.mkRow(QCoreApplication::translate("HtmlInfo", "Start time"), qstr(chapter.startTime().toString(TimeSpanOutputFormat::WithMeasures)));
|
||||
}
|
||||
if(chapter.endTime().totalTicks() > 0) {
|
||||
if(!chapter.endTime().isNull()) {
|
||||
rowMaker.mkRow(QCoreApplication::translate("HtmlInfo", "End time"), qstr(chapter.endTime().toString(TimeSpanOutputFormat::WithMeasures)));
|
||||
}
|
||||
list<string> labels;
|
||||
QStringList labels;
|
||||
if(chapter.isHidden()) {
|
||||
labels.push_back("hidden");
|
||||
labels << QCoreApplication::translate("HtmlInfo", "hidden");
|
||||
}
|
||||
if(!chapter.isEnabled()) {
|
||||
labels.push_back("disabled");
|
||||
labels << QCoreApplication::translate("HtmlInfo", "disabled");
|
||||
}
|
||||
if(labels.size()) {
|
||||
rowMaker.mkRow(QCoreApplication::translate("HtmlInfo", "Labeled as"), qstr(joinStrings(labels, ", ")));
|
||||
if(!labels.empty()) {
|
||||
rowMaker.mkRow(QCoreApplication::translate("HtmlInfo", "Labeled as"), labels.join(QStringLiteral(", ")));
|
||||
}
|
||||
if(chapter.tracks().size()) {
|
||||
if(!chapter.tracks().empty()) {
|
||||
QStringList trackIds;
|
||||
for(uint64 id : chapter.tracks()) {
|
||||
trackIds << QString::number(id);
|
||||
|
@ -702,18 +701,18 @@ public:
|
|||
if(edition.id()) {
|
||||
rowMaker.mkRow(QCoreApplication::translate("HtmlInfo", "ID"), QString::number(edition.id()));
|
||||
}
|
||||
list<string> labels;
|
||||
QStringList labels;
|
||||
if(edition.isHidden()) {
|
||||
labels.push_back("hidden");
|
||||
labels << QCoreApplication::translate("HtmlInfo", "hidden");
|
||||
}
|
||||
if(edition.isDefault()) {
|
||||
labels.push_back("default");
|
||||
labels << QCoreApplication::translate("HtmlInfo", "default");
|
||||
}
|
||||
if(edition.isOrdered()) {
|
||||
labels.push_back("ordered");
|
||||
labels << QCoreApplication::translate("HtmlInfo", "ordered");
|
||||
}
|
||||
if(labels.size()) {
|
||||
rowMaker.mkRow(QCoreApplication::translate("HtmlInfo", "Labeled as"), qstr(joinStrings(labels, ", ")));
|
||||
if(!labels.isEmpty()) {
|
||||
rowMaker.mkRow(QCoreApplication::translate("HtmlInfo", "Labeled as"), labels.join(QStringLiteral(", ")));
|
||||
}
|
||||
rowMaker.mkRow(QCoreApplication::translate("HtmlInfo", "Chapters"),
|
||||
QCoreApplication::translate("HtmlInfo", "edition contains %1 chapter(s)", nullptr, edition.chapters().size()).arg(edition.chapters().size()));
|
||||
|
@ -792,7 +791,7 @@ public:
|
|||
if(notifications.size()) {
|
||||
startTableSection();
|
||||
const QString moreId(reparsing ? QStringLiteral("notificationsReparsingMore") : QStringLiteral("notificationsMore"));
|
||||
m_rowMaker.startRow(reparsing ? QCoreApplication::translate("HtmlInfo", "Notifications (reparsing)") : QCoreApplication::translate("HtmlInfo", "Notifications"));
|
||||
m_rowMaker.startRow(reparsing ? QCoreApplication::translate("HtmlInfo", "Notifications (reparsing after saving)") : QCoreApplication::translate("HtmlInfo", "Notifications"));
|
||||
m_writer.writeCharacters(QCoreApplication::translate("HtmlInfo", "%1 notification(s) available", 0, notifications.size()).arg(notifications.size()));
|
||||
mkSpace();
|
||||
mkDetailsLink(moreId, QCoreApplication::translate("HtmlInfo", "show notifications"));
|
||||
|
@ -850,22 +849,22 @@ public:
|
|||
m_writer.writeStartElement(QStringLiteral("body"));
|
||||
startVerticalTable();
|
||||
|
||||
// general
|
||||
// general information
|
||||
startTableSection(QStringLiteral("general"));
|
||||
m_rowMaker.mkRow(QCoreApplication::translate("HtmlInfo", "Path"), qstr(m_file.path()));
|
||||
m_rowMaker.mkRow(QCoreApplication::translate("HtmlInfo", "Size"), qstr(dataSizeToString(m_file.size(), true)));
|
||||
TimeSpan duration = m_file.duration();
|
||||
const TimeSpan duration = m_file.duration();
|
||||
if(!duration.isNull()) {
|
||||
m_rowMaker.mkRow(QCoreApplication::translate("HtmlInfo", "Duration"), qstr(duration.toString(TimeSpanOutputFormat::WithMeasures)));
|
||||
m_rowMaker.mkRow(QCoreApplication::translate("HtmlInfo", "Overall avg. bitrate"), qstr(bitrateToString(0.0078125 * m_file.size() / duration.totalSeconds())));
|
||||
}
|
||||
const char *mimeType = m_file.mimeType();
|
||||
const char *const mimeType = m_file.mimeType();
|
||||
if(*mimeType) {
|
||||
m_rowMaker.mkRow(QCoreApplication::translate("HtmlInfo", "Mime-type"), qstr(mimeType));
|
||||
}
|
||||
m_rowMaker.startRow(QCoreApplication::translate("HtmlInfo", "Container"));
|
||||
m_writer.writeCharacters(qstr(m_file.containerFormatName()));
|
||||
const char *subversion = m_file.containerFormatSubversion();
|
||||
const char *const subversion = m_file.containerFormatSubversion();
|
||||
if(*subversion) {
|
||||
mkSpace();
|
||||
m_writer.writeCharacters(qstr(subversion));
|
||||
|
@ -946,7 +945,7 @@ public:
|
|||
}
|
||||
|
||||
// tracks
|
||||
auto tracks = m_file.tracks();
|
||||
const auto tracks = m_file.tracks();
|
||||
if(!tracks.empty()) {
|
||||
startTableSection();
|
||||
const QString moreId(QStringLiteral("tracksMore"));
|
||||
|
@ -990,11 +989,12 @@ public:
|
|||
// chapters
|
||||
if(container) {
|
||||
if(m_file.containerFormat() == ContainerFormat::Matroska) {
|
||||
if(size_t editionCount = static_cast<const MatroskaContainer *>(container)->editionEntires().size()) {
|
||||
const auto &editionEntries = static_cast<const MatroskaContainer *>(container)->editionEntires();
|
||||
if(!editionEntries.empty()) {
|
||||
startTableSection();
|
||||
const QString moreId(QStringLiteral("editionsMore"));
|
||||
m_rowMaker.startRow(QCoreApplication::translate("HtmlInfo", "Editions/chapters"));
|
||||
m_writer.writeCharacters(QCoreApplication::translate("HtmlInfo", "file has %1 edition(s)", 0, editionCount).arg(editionCount));
|
||||
m_writer.writeCharacters(QCoreApplication::translate("HtmlInfo", "file has %1 edition(s)", 0, editionEntries.size()).arg(editionEntries.size()));
|
||||
mkSpace();
|
||||
mkDetailsLink(moreId, QCoreApplication::translate("HtmlInfo", "show details"));
|
||||
m_rowMaker.endRow();
|
||||
|
@ -1105,8 +1105,6 @@ private:
|
|||
NotificationList &originalNotifications;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Generates technical information for the specified \a file.
|
||||
*
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue