improved project files

This commit is contained in:
Martchus 2015-12-08 08:40:03 +01:00
parent c3417c5d2a
commit 11ad156131
13 changed files with 292 additions and 1024 deletions

View File

@ -5,43 +5,156 @@ set(META_PROJECT_NAME tageditor)
set(META_APP_NAME "Tag Editor")
set(META_APP_AUTHOR "Martchus")
set(META_APP_URL "https://github.com/${META_APP_AUTHOR}/${META_PROJECT_NAME}")
set(META APP_DESCRIPTION "A tageditor with Qt GUI and command line interface. Supports MP4 (iTunes), ID3, Vorbis and Matroska.")
set(META_APP_DESCRIPTION "A tageditor with Qt GUI and command line interface. Supports MP4 (iTunes), ID3, Vorbis and Matroska.")
set(META_VERSION_MAJOR 1)
set(META_VERSION_MINOR 2)
set(META_VERSION_MINOR 3)
set(META_VERSION_PATCH 0)
# define project
project(${META_PROJECT_NAME})
# stringification of meta data
set(META_PROJECT_NAME_STR "\"${META_PROJECT_NAME}\"")
set(META_APP_NAME_STR "\"${META_APP_NAME}\"")
set(META_APP_AUTHOR_STR "\"${META_APP_AUTHOR}\"")
set(META_APP_URL_STR "\"${META_APP_URL}\"")
set(APP_DESCRIPTION_STR "\"${APP_DESCRIPTION}\"")
set(META_APP_VERSION_STR "\"${META_VERSION_MAJOR}.${META_VERSION_MINOR}.${META_VERSION_PATCH}\"")
set(META_APP_DESCRIPTION_STR "\"${META_APP_DESCRIPTION}\"")
set(META_APP_VERSION ${META_VERSION_MAJOR}.${META_VERSION_MINOR}.${META_VERSION_PATCH})
set(META_APP_VERSION_STR "\"${META_APP_VERSION}\"")
# add project files
set(HEADER_FILES
application/knownfieldmodel.h
application/main.h
application/settings.h
cli/mainfeatures.h
misc/htmlinfo.h
misc/utility.h
)
set(SRC_FILES
application/knownfieldmodel.cpp
application/main.cpp
application/settings.cpp
cli/mainfeatures.cpp
misc/htmlinfo.cpp
misc/utility.cpp
)
set(WIDGETS_HEADER_FILES
gui/entertargetdialog.h
gui/javascripthighlighter.h
gui/attachmentsedit.h
gui/attachmentsmodel.h
gui/codeedit.h
gui/mainwindow.h
gui/minimumemptyspinbox.h
gui/notificationlabel.h
gui/notificationmodel.h
gui/pathlineedit.h
gui/picturepreviewselection.h
gui/filefilterproxymodel.h
gui/infowidgetbase.h
gui/initiate.h
gui/previousvaluehandling.h
gui/renamefilesdialog.h
gui/settingsdialog.h
gui/tagedit.h
gui/tagfieldedit.h
renamingutility/filesystemitem.h
renamingutility/filesystemitemmodel.h
renamingutility/filteredfilesystemitemmodel.h
renamingutility/renamingengine.h
renamingutility/scriptfunctions.h
)
set(WIDGETS_SRC_FILES
gui/attachmentsedit.cpp
gui/attachmentsmodel.cpp
gui/codeedit.cpp
gui/entertargetdialog.cpp
gui/mainwindow.cpp
gui/minimumemptyspinbox.cpp
gui/notificationlabel.cpp
gui/notificationmodel.cpp
gui/pathlineedit.cpp
gui/picturepreviewselection.cpp
gui/filefilterproxymodel.cpp
gui/infowidgetbase.cpp
gui/initiate.cpp
gui/javascripthighlighter.cpp
gui/previousvaluehandling.cpp
gui/renamefilesdialog.cpp
gui/settingsdialog.cpp
gui/tagedit.cpp
gui/tagfieldedit.cpp
renamingutility/filesystemitem.cpp
renamingutility/filesystemitemmodel.cpp
renamingutility/filteredfilesystemitemmodel.cpp
renamingutility/renamingengine.cpp
renamingutility/scriptfunctions.cpp
resources/icons.qrc
)
#set(QUICK_HEADER_FILES
#)
#set(QUICK_SRC_FILES
# resources/icons.qrc
#)
set(TS_FILES
translations/${META_PROJECT_NAME}_de_DE.ts
translations/${META_PROJECT_NAME}_en_US.ts
)
# define project
project(${META_PROJECT_NAME})
# add configuration header
configure_file (
"${PROJECT_SOURCE_DIR}/config.h.in"
"${PROJECT_BINARY_DIR}/config.h"
configure_file(
"${PROJECT_SOURCE_DIR}/resources/config.h.in"
"${PROJECT_BINARY_DIR}/resources/config.h"
)
include_directories("${PROJECT_BINARY_DIR}")
# add source and header files
file(GLOB_RECURSE SRC_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "application/*.cpp" "cli/*.cpp" "misc/*.cpp")
file(GLOB_RECURSE WIDGETS_SRC_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "gui/*.cpp" "renamingutility/*.cpp" "resources/icons.qrc")
file(GLOB_RECURSE HEADER_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "application/*.h" "cli/*.h" "misc/*.h")
file(GLOB_RECURSE WIDGETS_HEADER_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "gui/*.h" "renamingutility/*.cpp")
# set "GUI-type" to WIN32 to hide console under windows
if(WIN32)
set(GUI_TYPE WIN32)
endif(WIN32)
# enable only Qt Widgets GUI
add_definitions(-DGUI_QTWIDGETS -DMODEL_UNDO_SUPPORT)
# add windows resource file
if(MINGW)
# creation windows icon from png with ffmpeg if available
find_program(FFMPEG_BIN ffmpeg avconv)
if(FFMPEG_BIN)
set(PNG_ICON_PATH "${PROJECT_SOURCE_DIR}/resources/icons/hicolor/128x128/apps/${META_PROJECT_NAME}.png")
if(EXISTS ${PNG_ICON_PATH})
set(WINDOWS_ICON_PATH "${PROJECT_BINARY_DIR}/${META_PROJECT_NAME}.ico")
set(WINDOWS_ICON_RC_ENTRY "IDI_ICON1 ICON DISCARDABLE \"${WINDOWS_ICON_PATH}\"")
add_custom_command(
OUTPUT "${WINDOWS_ICON_PATH}"
COMMAND ${FFMPEG_BIN} -y -i "${PNG_ICON_PATH}" -vf crop=iw-20:ih-20:10:10,scale=64:64 "${WINDOWS_ICON_PATH}"
)
endif()
endif(FFMPEG_BIN)
# create windows rc file from template
set(WINDOWS_EXT "exe")
configure_file(
"${PROJECT_SOURCE_DIR}/resources/windows.rc.in"
"${PROJECT_BINARY_DIR}/resources/windows.rc"
)
# set windres as resource compiler
set(RES_FILES "${PROJECT_BINARY_DIR}/resources/windows.rc")
set(CMAKE_RC_COMPILER_INIT windres)
set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> <FLAGS> -O coff <DEFINES> -i <SOURCE> -o <OBJECT>")
enable_language(RC)
endif(MINGW)
# enable Qt Widgets GUI
add_definitions(
-DGUI_QTWIDGETS
-DMODEL_UNDO_SUPPORT
)
# check required Qt 5 modules
find_package(Qt5Core REQUIRED)
find_package(Qt5Gui REQUIRED)
find_package(Qt5Widgets REQUIRED)
find_package(Qt5WebKit REQUIRED)
find_package(Qt5LinguistTools REQUIRED)
find_package(Qt5WebKitWidgets REQUIRED)
find_package(Qt5Script REQUIRED)
# enable moc, uic and rcc
set(CMAKE_AUTOMOC ON)
@ -49,22 +162,53 @@ set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# executable and linking
add_executable(${META_PROJECT_NAME} ${HEADER_FILES} ${SRC_FILES} ${WIDGETS_HEADER_FILES} ${WIDGETS_SRC_FILES})
target_link_libraries(${META_PROJECT_NAME} c++utilities qtutilities tagparser Qt5::Core Qt5::Widgets Qt5::WebKit)
# enable lrelease
qt5_add_translation(QM_FILES ${TS_FILES})
ADD_CUSTOM_TARGET(translations ALL DEPENDS ${QM_FILES})
# enable C++11
set_property(TARGET ${META_PROJECT_NAME} PROPERTY CXX_STANDARD 11)
# executable and linking
add_executable(${META_PROJECT_NAME} ${GUI_TYPE} ${HEADER_FILES} ${SRC_FILES} ${WIDGETS_HEADER_FILES} ${WIDGETS_SRC_FILES} ${QM_FILES} ${RES_FILES} ${WINDOWS_ICON_PATH})
target_link_libraries(${META_PROJECT_NAME} c++utilities qtutilities tagparser pthread Qt5::Core Qt5::Widgets Qt5::WebKitWidgets Qt5::Script)
set_target_properties(${META_PROJECT_NAME} PROPERTIES
CXX_STANDARD 11
)
# add install target
install(TARGETS ${META_PROJECT_NAME}
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
COMPONENT binary
)
install(FILES resources/icons/hicolor/scalable/apps/${META_PROJECT_NAME}.svg
DESTINATION share/icons/hicolor/scalable/apps
COMPONENT desktop
)
install(FILES resources/desktop/applications/${META_PROJECT_NAME}.desktop
DESTINATION share/applications
COMPONENT desktop
)
install(FILES ${QM_FILES}
DESTINATION share/${META_PROJECT_NAME}/translations
COMPONENT localization
)
add_custom_target(install-binary
DEPENDS ${META_PROJECT_NAME}
COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=binary -P "${CMAKE_BINARY_DIR}/cmake_install.cmake"
)
add_custom_target(install-desktop
DEPENDS ${META_PROJECT_NAME}
COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=desktop -P "${CMAKE_BINARY_DIR}/cmake_install.cmake"
)
add_custom_target(install-localization
DEPENDS ${META_PROJECT_NAME}
COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=localization -P "${CMAKE_BINARY_DIR}/cmake_install.cmake"
)
add_custom_target(install-mingw-w64
DEPENDS install-binary install-localization
)
add_custom_target(install-binary-strip
DEPENDS ${META_PROJECT_NAME}
COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_DO_STRIP=1 -DCMAKE_INSTALL_COMPONENT=binary -P "${CMAKE_BINARY_DIR}/cmake_install.cmake"
)
add_custom_target(install-mingw-w64-strip
DEPENDS install-binary-strip install-localization
)

View File

@ -9,7 +9,7 @@
// include configuration from separate header file when building with CMake
#ifndef APP_METADATA_AVAIL
#include "config.h"
#include "resources/config.h"
#endif
#if defined(GUI_QTWIDGETS) || defined(GUI_QTQUICK)

View File

@ -1,28 +1,12 @@
#dirs
# specify build directories for moc, object and rcc files
MOC_DIR = ./moc
OBJECTS_DIR = ./obj
RCC_DIR = ./res
# compiler flags
# compiler flags: enable C++11
QMAKE_CXXFLAGS += -std=c++11
QMAKE_LFLAGS += -std=c++11
# prefix
targetprefix = $$(TARGET_PREFIX)
message("Using target prefix \"$${targetprefix}\".")
# print install root
message("Using install root \"$$(INSTALL_ROOT)\".")
# target
CONFIG(debug, debug|release) {
TARGET = $${targetprefix}$${projectname}d
} else {
TARGET = $${targetprefix}$${projectname}
}
# add defines
DEFINES += "APP_METADATA_AVAIL"
DEFINES += "'PROJECT_NAME=\"$${projectname}\"'"
DEFINES += "'APP_NAME=\"$${appname}\"'"
DEFINES += "'APP_AUTHOR=\"$${appauthor}\"'"
DEFINES += "'APP_URL=\"$${appurl}\"'"
DEFINES += "'APP_VERSION=\"$${VERSION}\"'"
# variables to check target architecture
win32-g++:QMAKE_TARGET.arch = $$QMAKE_HOST.arch
win32-g++-32:QMAKE_TARGET.arch = x86
@ -30,7 +14,30 @@ win32-g++-64:QMAKE_TARGET.arch = x86_64
linux-g++:QMAKE_TARGET.arch = $$QMAKE_HOST.arch
linux-g++-32:QMAKE_TARGET.arch = x86
linux-g++-64:QMAKE_TARGET.arch = x86_64
# configuration
# determine and print target prefix
targetprefix = $$(TARGET_PREFIX)
message("Using target prefix \"$${targetprefix}\".")
# print install root
message("Using install root \"$$(INSTALL_ROOT)\".")
# set target
CONFIG(debug, debug|release) {
TARGET = $${targetprefix}$${projectname}d
} else {
TARGET = $${targetprefix}$${projectname}
}
# add defines for meta data
DEFINES += "APP_METADATA_AVAIL"
DEFINES += "'PROJECT_NAME=\"$${projectname}\"'"
DEFINES += "'APP_NAME=\"$${appname}\"'"
DEFINES += "'APP_AUTHOR=\"$${appauthor}\"'"
DEFINES += "'APP_URL=\"$${appurl}\"'"
DEFINES += "'APP_VERSION=\"$${VERSION}\"'"
# configure Qt modules and defines
mobile {
DEFINES += CONFIG_MOBILE
} else:desktop {
@ -61,7 +68,7 @@ no-gui {
}
guiqtquick {
message("Configured for Qt Quick GUI support.")
greaterThan(QT_MAJOR_VERSION, 4): QT += quick
QT += quick
CONFIG(debug, debug|release) {
CONFIG += qml_debug
}
@ -69,11 +76,12 @@ guiqtquick {
}
guiqtwidgets {
message("Configured for Qt widgets GUI support.")
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
QT += widgets
DEFINES += GUI_QTWIDGETS
DEFINES += MODEL_UNDO_SUPPORT
}
# Windows stuff: configuration for cross compliation with mingw-w64
# configuration for cross compliation with mingw-w64
win32 {
QMAKE_TARGET_PRODUCT = "$${appname}"
QMAKE_TARGET_COPYRIGHT = "by $${appauthor}"

View File

@ -1,94 +0,0 @@
#include "containerinfowidget.h"
#include <taginfo/mediafileinfo.h>
#include <taginfo/abstractcontainer.h>
#include <QLabel>
#include <QLineEdit>
using namespace std;
using namespace Media;
namespace QtGui {
ContainerInfoWidget::ContainerInfoWidget(QWidget *parent) :
InfoWidgetBase(parent),
m_nameLabel(nullptr),
m_abbreviationLabel(nullptr),
m_versionLabel(nullptr),
m_readVersionLabel(nullptr),
m_docTypeLabel(nullptr),
m_docVersionLabel(nullptr),
m_docReadVersionLabel(nullptr),
m_titleLabel(nullptr)
{}
ContainerInfoWidget::~ContainerInfoWidget()
{}
void ContainerInfoWidget::update(const Media::MediaFileInfo &fileInfo, const Media::AbstractContainer &container)
{
int row = 0;
// use container format name as name
string name(fileInfo.containerFormatName());
const char *subversion = fileInfo.containerFormatSubversion();
if(*subversion) {
name.append(" ");
name.append(subversion);
}
setupName(name);
setupRow(row, "Name", m_nameLabel, name);
++row;
// notifications
setupNotifications(container);
// abbreviation
const char *abbreviation = fileInfo.containerFormatAbbreviation();
if(*abbreviation) {
setupRow(row, "Abbreviation", m_abbreviationLabel, QString::fromLocal8Bit(abbreviation));
++row;
} else {
removeRow(m_abbreviationLabel);
}
// version
if(container.version()) {
setupRow(row, "Version", m_versionLabel, QString::number(container.version()));
++row;
} else {
removeRow(m_versionLabel);
}
if(container.readVersion()) {
setupRow(row, "Read version", m_readVersionLabel, QString::number(container.readVersion()));
++row;
} else {
removeRow(m_docReadVersionLabel);
}
// document
if(!container.documentType().empty()) {
setupRow(row, "Document type", m_docTypeLabel, container.documentType());
++row;
} else {
removeRow(m_docTypeLabel);
}
if(container.doctypeVersion()) {
setupRow(row, "Document version", m_docVersionLabel, QString::number(container.doctypeVersion()));
++row;
} else {
removeRow(m_docVersionLabel);
}
if(container.doctypeReadVersion()) {
setupRow(row, "Document read version", m_docReadVersionLabel, QString::number(container.doctypeReadVersion()));
++row;
} else {
removeRow(m_docReadVersionLabel);
}
setupRow(row, "Title", m_titleLabel, container.title());
m_titleLabel->setReadOnly(fileInfo.containerFormat() != ContainerFormat::Matroska);
}
}

View File

@ -1,41 +0,0 @@
#ifndef CONTAINERINFOWIDGET_H
#define CONTAINERINFOWIDGET_H
#include "infowidgetbase.h"
QT_BEGIN_NAMESPACE
class QLabel;
class QLineEdit;
QT_END_NAMESPACE
namespace Media {
class MediaFileInfo;
class AbstractContainer;
}
namespace QtGui {
class ContainerInfoWidget : public InfoWidgetBase
{
Q_OBJECT
public:
explicit ContainerInfoWidget(QWidget *parent = nullptr);
~ContainerInfoWidget();
void update(const Media::MediaFileInfo &fileInfo, const Media::AbstractContainer &container);
private:
QLabel *m_nameLabel;
QLabel *m_abbreviationLabel;
QLabel *m_versionLabel;
QLabel *m_readVersionLabel;
QLabel *m_docTypeLabel;
QLabel *m_docVersionLabel;
QLabel *m_docReadVersionLabel;
QLineEdit *m_titleLabel;
};
}
#endif // CONTAINERINFOWIDGET_H

View File

@ -1,577 +0,0 @@
#include "fileinfomodel.h"
#include <taginfo/parsingexception.h>
#include <taginfo/tag.h>
#include <taginfo/abstractcontainer.h>
#include <taginfo/abstracttrack.h>
#include <taginfo/id3/id3v1tag.h>
#include <taginfo/id3/id3v2tag.h>
#include <taginfo/mp4/mp4atom.h>
#include <taginfo/mp4/mp4container.h>
#include <taginfo/matroska/matroskaid.h>
#include <taginfo/matroska/ebmlelement.h>
#include <taginfo/matroska/matroskacontainer.h>
#include <martchusutilities/misc/misc.h>
#include <martchusutilities/conversion/stringconversion.h>
using namespace std;
using namespace ChronoUtilities;
using namespace Media;
namespace QtGui {
TreeItem::TreeItem(const QList<QVariant> &data, TreeItem *parent) :
m_itemData(data),
m_parentItem(parent)
{}
TreeItem::TreeItem(const QString &data0, const QString &data1, TreeItem *parent) :
m_itemData(QList<QVariant>() << data0 << data1),
m_parentItem(parent)
{}
TreeItem::TreeItem(const QString &data0, const string &data1, TreeItem *parent) :
m_itemData(QList<QVariant>() << data0 << QString::fromLocal8Bit(data1.c_str())),
m_parentItem(parent)
{}
TreeItem::TreeItem(const std::string &data0, const std::string &data1, TreeItem *parent) :
m_itemData(QList<QVariant>() << QString::fromLocal8Bit(data0.c_str()) << QString::fromLocal8Bit(data1.c_str())),
m_parentItem(parent)
{}
TreeItem::~TreeItem()
{
qDeleteAll(m_childItems);
}
void TreeItem::appendChild(TreeItem *item)
{
m_childItems.append(item);
}
TreeItem *TreeItem::appendChild(const QList<QVariant> &data)
{
TreeItem *item = new TreeItem(data, this);
m_childItems.append(item);
return item;
}
TreeItem *TreeItem::appendChild(const QString &data)
{
TreeItem *item = new TreeItem(data, QString(), this);
m_childItems.append(item);
return item;
}
TreeItem *TreeItem::appendChild(const QString &data0, const QString &data1)
{
TreeItem *item = new TreeItem(data0, data1, this);
m_childItems.append(item);
return item;
}
TreeItem *TreeItem::appendChild(const QString &data0, const string &data1)
{
TreeItem *item = new TreeItem(data0, data1, this);
m_childItems.append(item);
return item;
}
TreeItem *TreeItem::appendChild(const string &data)
{
TreeItem *item = new TreeItem(data, string(), this);
m_childItems.append(item);
return item;
}
TreeItem *TreeItem::appendChild(const std::string &data0, const std::string &data1)
{
TreeItem *item = new TreeItem(data0, data1, this);
m_childItems.append(item);
return item;
}
TreeItem *TreeItem::appendChild(const QString &data0, int data1)
{
TreeItem *item = new TreeItem(data0, QString::number(data1), this);
m_childItems.append(item);
return item;
}
TreeItem *TreeItem::child(int row)
{
return m_childItems.value(row);
}
int TreeItem::childCount() const
{
return m_childItems.count();
}
int TreeItem::row() const
{
if (m_parentItem)
return m_parentItem->m_childItems.indexOf(const_cast<TreeItem *>(this));
return 0;
}
int TreeItem::columnCount() const
{
return m_itemData.count();
}
QVariant TreeItem::data(int column) const
{
return m_itemData.value(column);
}
TreeItem *TreeItem::parent()
{
return m_parentItem;
}
void TreeItem::clearChilds()
{
qDeleteAll(m_childItems);
m_childItems.clear();
}
void TreeItem::clearData()
{
m_itemData.clear();
}
const QIcon &TreeItem::icon() const
{
return m_icon;
}
void TreeItem::setIcon(const QIcon &value)
{
m_icon = value;
}
FileInfoModel::FileInfoModel(QObject *parent) :
QAbstractItemModel(parent),
m_fileInfo(0),
m_anyNotifications(false),
m_criticalNotifications(false)
{
m_rootItem = new TreeItem(QList<QVariant>() << "Property" << "Value");
m_generalItem = m_rootItem->appendChild(QStringLiteral("General information and container/main format"));
m_generalItem->setIcon(QIcon::fromTheme(QStringLiteral("document-properties")));
m_audioTracksItem = m_rootItem->appendChild(QStringLiteral("Audio tracks"));
m_audioTracksItem->setIcon(QIcon::fromTheme(QStringLiteral("audio-x-generic"), QIcon(QStringLiteral("/images/music"))));
m_videoTracksItem = m_rootItem->appendChild(QStringLiteral("Video tracks"));
m_videoTracksItem->setIcon(QIcon::fromTheme(QStringLiteral("video-x-generic"), QIcon(QStringLiteral("/images/video"))));
m_subtitleTracksItem = m_rootItem->appendChild(QStringLiteral("Subtitle tracks"));
m_otherTracksItem = m_rootItem->appendChild(QStringLiteral("Other tracks"));
m_tagItem = m_rootItem->appendChild(QStringLiteral("Tag(s)"));
m_tagItem->setIcon(QIcon::fromTheme(QStringLiteral("multimedia-player"), QIcon(QStringLiteral("/images/tag"))));
}
FileInfoModel::FileInfoModel(MediaFileInfo *fileInfo, QObject *parent) :
FileInfoModel(parent)
{
show(fileInfo);
}
FileInfoModel::~FileInfoModel()
{
delete m_rootItem;
}
QVariant FileInfoModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid()) {
return QVariant();
}
switch(role) {
case Qt::DisplayRole:
return static_cast<TreeItem *>(index.internalPointer())->data(index.column());
case Qt::DecorationRole:
if(index.column() == 0) {
TreeItem *item = static_cast<TreeItem *>(index.internalPointer());
if(!item->icon().isNull())
return item->icon();
}
default:
;
}
return QVariant();
}
Qt::ItemFlags FileInfoModel::flags(const QModelIndex &index) const
{
if (!index.isValid()) {
return 0;
}
return QAbstractItemModel::flags(index);
}
QVariant FileInfoModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
return m_rootItem->data(section);
}
return QVariant();
}
QModelIndex FileInfoModel::index(int row, int column, const QModelIndex &parent) const
{
if (!hasIndex(row, column, parent)) {
return QModelIndex();
}
TreeItem *parentItem;
if (!parent.isValid()) {
parentItem = m_rootItem;
} else {
parentItem = static_cast<TreeItem *>(parent.internalPointer());
}
if (TreeItem *childItem = parentItem->child(row)) {
return createIndex(row, column, childItem);
} else {
return QModelIndex();
}
}
QModelIndex FileInfoModel::parent(const QModelIndex &index) const
{
if (!index.isValid()) {
return QModelIndex();
}
TreeItem *childItem = static_cast<TreeItem*>(index.internalPointer());
TreeItem *parentItem = childItem->parent();
if (parentItem == m_rootItem) {
return QModelIndex();
}
return createIndex(parentItem->row(), 0, parentItem);
}
int FileInfoModel::rowCount(const QModelIndex &parent) const
{
TreeItem *parentItem;
if (parent.column() > 0) {
return 0;
}
if (!parent.isValid()) {
parentItem = m_rootItem;
} else {
parentItem = static_cast<TreeItem *>(parent.internalPointer());
}
return parentItem->childCount();
}
int FileInfoModel::columnCount(const QModelIndex &parent) const
{
if (parent.isValid()) {
return static_cast<TreeItem *>(parent.internalPointer())->columnCount();
} else {
return m_rootItem->columnCount();
}
}
const MediaFileInfo *FileInfoModel::shownFileInfo() const
{
return m_fileInfo;
}
MediaFileInfo *FileInfoModel::shownFileInfo()
{
return m_fileInfo;
}
void FileInfoModel::show(MediaFileInfo *fileInfo)
{
m_fileInfo = fileInfo;
update();
}
void FileInfoModel::update()
{
beginResetModel();
m_anyNotifications = false;
m_criticalNotifications = false;
m_generalItem->clearChilds();
m_audioTracksItem->clearChilds();
m_videoTracksItem->clearChilds();
m_otherTracksItem->clearChilds();
m_tagItem->clearChilds();
showGeneralInformation();
showTracks();
showTagInformation();
endResetModel();
}
bool FileInfoModel::containsAnyNotifications() const
{
return m_anyNotifications;
}
bool FileInfoModel::containsCriticalNotifications() const
{
return m_criticalNotifications;
}
void FileInfoModel::showGeneralInformation()
{
if(m_fileInfo && m_fileInfo->isContainerParsed()) {
AbstractContainer *container = m_fileInfo->container();
m_generalItem->appendChild(tr("Path"), m_fileInfo->path());
m_generalItem->appendChild(tr("Extension"), m_fileInfo->extension());
m_generalItem->appendChild(tr("Size"), ConversionUtilities::dataSizeToString(m_fileInfo->size()));
TreeItem *containerItem = m_generalItem->appendChild("Container format", QString::fromLocal8Bit(m_fileInfo->containerFormatName()));
QString version;
if(container) {
if(!container->duration().isNull()) {
m_generalItem->appendChild(tr("Duration"), container->duration().toString(TimeSpanOutputFormat::WithMeasures));
}
if(!container->title().empty()) {
m_generalItem->appendChild(tr("Title"), container->title());
}
if(!container->documentType().empty()) {
containerItem->appendChild(tr("Document type"), container->documentType());
}
version = QString::number(container->version());
} else {
version = QString::fromLocal8Bit(m_fileInfo->containerFormatSubversion());
}
containerItem->appendChild(tr("Version"), version);
containerItem->appendChild(tr("Abbreviation"), QString::fromLocal8Bit(m_fileInfo->containerFormatAbbreviation()));
if(Mp4Container *container = m_fileInfo->mp4Container()) { // show atom structure if its an MP4 file
if(Mp4Atom *atom = container->firstElement()) {
TreeItem *atomsItem = containerItem->appendChild(tr("Atom structure"));
showAtoms(atomsItem, atom);
}
}
if(MatroskaContainer *container = m_fileInfo->matroskaContainer()) { // show EBML elements if its an EBML/Matroska file
if(EbmlElement *element = container->firstElement()) {
TreeItem *elementItem = containerItem->appendChild(tr("EBML element structure (to first cluster)"));
showEbmlElements(elementItem, element);
}
}
showNotifications(m_fileInfo->lastParsingNotifications(), m_generalItem, tr("General parsing notifications"));
showNotifications(m_fileInfo->lastMakingNotifications(), m_generalItem, tr("Last saving notifications"));
}
}
void FileInfoModel::showAtoms(TreeItem *item, Mp4Atom *atom)
{
while(atom) {
try {
atom->parse();
if(atom->lastParsingNotifications().size())
showNotifications(atom->lastParsingNotifications(), item, tr("Expand to display parsing warnings"));
showAtoms(item->appendChild(
QString::fromLatin1(atom->idToString().c_str()),
tr("@%1, size: %2").arg(atom->startOffset()).arg(atom->totalSize())),
atom->firstChild());
atom = atom->nextSibling();
} catch(ParsingException &) {
showNotifications(atom->lastParsingNotifications(), item, tr("Invalid atom found, expand for detail."));
return;
} catch(ios_base::failure &) {
showNotifications(atom->lastParsingNotifications(), item, tr("IO error occured when parsing atom."));
return;
}
}
}
void FileInfoModel::showEbmlElements(TreeItem *item, EbmlElement *element)
{
while(element) {
try {
element->parse();
if(element->lastParsingNotifications().size())
showNotifications(element->lastParsingNotifications(), item, tr("Expand to display parsing warnings"));
showEbmlElements(item->appendChild(
QString::fromLatin1(element->idToString().c_str()),
tr("@%1, size: %2").arg(element->startOffset()).arg(element->totalSize())),
element->firstChild());
if(element->id() == MatroskaId::Cluster) {
break; // cluster reached; just display the first cluster
}
element = element->nextSibling();
} catch(ParsingException &) {
showNotifications(element->lastParsingNotifications(), item, tr("Invalid EBML element found, expand for detail."));
return;
} catch(ios_base::failure &) {
showNotifications(element->lastParsingNotifications(), item, tr("IO error occured when parsing atom."));
return;
}
}
}
void FileInfoModel::showTracks()
{
TreeItem *item, *formatItem;
int i = 1;
for(AbstractTrack *track : m_fileInfo->tracks()) {
list<string> identifiers;
identifiers.push_back(track->name());
identifiers.push_back("ID: " + ConversionUtilities::numberToString<uint32>(track->id()));
QString name = QString::fromLocal8Bit(ConversionUtilities::concateStrings(identifiers, ", ", true).c_str());
if(name.isEmpty()) {
name = tr("Unnamed track");
}
switch(track->mediaType()) {
case MediaType::Audio:
item = m_audioTracksItem->appendChild(name);
break;
case MediaType::Video:
item = m_videoTracksItem->appendChild(name);
break;
case MediaType::Subtitle:
item = m_subtitleTracksItem->appendChild(name);
break;
default:
item = m_otherTracksItem->appendChild(name);
}
if(track->isHeaderValid()) {
formatItem = item->appendChild(tr("Format"), QString::fromLocal8Bit(track->formatName()));
formatItem->appendChild(tr("Version"), QStringLiteral("%1").arg(track->version()));
formatItem->appendChild(tr("Abbreviation"), QString::fromLocal8Bit(track->formatAbbreviation()));
if(track->bitrate() > 0.0)
item->appendChild(tr("Bitrate"), ConversionUtilities::bitrateToString(track->bitrate()));
if(!track->duration().isNull())
item->appendChild(tr("Duration"), track->duration().toString(TimeSpanOutputFormat::WithMeasures));
if(track->size())
item->appendChild(tr("Size"), ConversionUtilities::dataSizeToString(track->size()));
if(!track->compressorName().empty())
item->appendChild(tr("Compressor"), track->compressorName());
if(!track->creationTime().isNull())
item->appendChild(tr("Creation time"), track->creationTime().toString());
if(!track->modificationTime().isNull())
item->appendChild(tr("Modification time"), track->modificationTime().toString());
if(track->sampleCount())
item->appendChild(tr("Sample count"), track->sampleCount());
if(track->samplesPerSecond())
item->appendChild(tr("Samples per second"), track->samplesPerSecond());
if(track->quality())
item->appendChild(tr("Quality"), track->quality());
if(!track->language().empty())
item->appendChild(tr("Language"), track->language());
list<string> labels;
if(!track->isEnabled())
labels.push_back("disabled");
if(track->isDefault())
labels.push_back("default");
if(track->isForced())
labels.push_back("forced");
if(track->isEncrypted())
labels.push_back("encrypted");
string concatedLabels = ConversionUtilities::concateStrings(labels, ", ");
if(!concatedLabels.empty())
item->appendChild(tr("Language"), concatedLabels);
switch(track->mediaType()) {
case MediaType::Audio:
if(track->bitsPerSample())
item->appendChild(tr("Bits per sample"), track->bitsPerSample());
if(track->channelCount())
item->appendChild(tr("Channel count"), track->channelCount());
break;
case MediaType::Video:
if(!track->pixelSize().isNull())
item->appendChild(tr("Size in px"), track->pixelSize().toString());
if(!track->displaySize().isNull())
item->appendChild(tr("Display size in px"), track->displaySize().toString());
if(!track->cropping().isNull())
item->appendChild(tr("Cropping in px"), track->cropping().toString());
if(track->depth())
item->appendChild(tr("Depth"), track->depth());
if(track->fps())
item->appendChild(tr("Frames per second"), track->fps());
break;
default:
;
}
} else {
item = m_otherTracksItem->appendChild(tr("Invalid/unsupported segment %1").arg(i));
item->appendChild(tr("Unable to parse file segment."), tr("See notifications for details."));
}
showNotifications(track->lastParsingNotifications(), item, tr("Parsing notifications"));
++i;
}
}
void FileInfoModel::showTagInformation()
{
if(m_fileInfo) {
static const QString expand(tr("expand for details"));
if(m_fileInfo->hasMp4Tag()) {
showTagDetails(m_fileInfo->mp4Tag(), m_tagItem->appendChild(tr("MP4 atoms store tag information"), expand));
} else if(m_fileInfo->hasMatroskaTag()) {
for(const auto &tag : m_fileInfo->matroskaTags()) {
showTagDetails(tag.get(), m_tagItem->appendChild(tr("Matroska container stores tag information"), expand));
}
}
const vector<unique_ptr<Id3v2Tag>> &id3v2Tags = m_fileInfo->id3v2Tags();
for(vector<unique_ptr<Id3v2Tag>>::const_iterator i = id3v2Tags.begin(), end = id3v2Tags.end();
i != end; ++i) {
showTagDetails((*i).get(), m_tagItem->appendChild(tr("ID3v2 tag"), expand));
}
if(m_fileInfo->hasId3v1Tag())
showTagDetails(m_fileInfo->id3v1Tag(), m_tagItem->appendChild(tr("ID3v1 tag"), expand));
}
}
void FileInfoModel::showTagDetails(const Tag *tag, TreeItem *item)
{
// display version
//static const QString version(QStringLiteral("%1"));
//static const QString unknownVersion(QStringLiteral("unknown or invalid tag"));
item->appendChild(tr("Version"), QString::fromLocal8Bit(tag->version().c_str()));
item->appendChild(tr("Size"), ConversionUtilities::dataSizeToString(tag->size())); // size
item->appendChild(tr("Field count"), tag->fieldCount()); // field count
showNotifications(tag->lastParsingNotifications(), item, tr("Parsing notifications"));
showNotifications(tag->lastMakingNotifications(), item, tr("Saving notifications"));
}
void FileInfoModel::showNotifications(const list<Notification> &notifications, TreeItem *item, const QString &label, bool showEmptyEntry)
{
static const QIcon informationIcon = QIcon::fromTheme(QStringLiteral("dialog-information"), QIcon(QStringLiteral("/images/information")));
static const QIcon warningIcon = QIcon::fromTheme(QStringLiteral("dialog-warning"), QIcon(QStringLiteral("/images/warning")));
static const QIcon errorIcon = QIcon::fromTheme(QStringLiteral("dialog-error"), QIcon(QStringLiteral("/images/error")));
static const QIcon debugIcon = QIcon::fromTheme(QStringLiteral("utilities-terminal"), QIcon(QStringLiteral("/images/bug")));
if(notifications.size()) {
m_anyNotifications = true;
TreeItem *notificationsItem = item->appendChild(label, QStringLiteral("%1").arg(notifications.size()));
TreeItem *notificationItem;
for(list<Notification>::const_iterator i = notifications.cbegin(), end = notifications.cend(); i != end; ++i) {
notificationItem = notificationsItem->appendChild(i->message());
switch(i->type()) {
case NotificationType::Warning:
notificationItem->setIcon(warningIcon);
break;
case NotificationType::Critical:
m_criticalNotifications = true;
notificationItem->setIcon(errorIcon);
break;
case NotificationType::Information:
notificationItem->setIcon(informationIcon);
break;
case NotificationType::Debug:
notificationItem->setIcon(debugIcon);
break;
default:
;
}
}
} else if(showEmptyEntry) {
item->appendChild(label, tr("none"));
}
}
}

View File

@ -1,97 +0,0 @@
#ifndef FILEINFOMODEL_H
#define FILEINFOMODEL_H
#include <taginfo/mediafileinfo.h>
#include <QAbstractItemModel>
#include <QIcon>
namespace QtGui {
class TreeItem
{
public:
explicit TreeItem(const QList<QVariant> &data, TreeItem *parent = nullptr);
explicit TreeItem(const QString &data0, const QString &data1, TreeItem *parent = nullptr);
explicit TreeItem(const QString &data0, const std::string &data1, TreeItem *parent = nullptr);
explicit TreeItem(const std::string &data0, const std::string &data1, TreeItem *parent = nullptr);
~TreeItem();
void appendChild(TreeItem *child);
TreeItem *appendChild(const QList<QVariant> &data);
TreeItem *appendChild(const QString &data);
TreeItem *appendChild(const QString &data0, const QString &data1);
TreeItem *appendChild(const QString &data0, const std::string &data1);
TreeItem *appendChild(const std::string &data);
TreeItem *appendChild(const std::string &data0, const std::string &data1);
TreeItem *appendChild(const QString &data0, int data1);
TreeItem *child(int row);
int childCount() const;
int columnCount() const;
QVariant data(int column) const;
int row() const;
TreeItem *parent();
void clearChilds();
void clearData();
const QIcon &icon() const;
void setIcon(const QIcon &value);
private:
QList<TreeItem *> m_childItems;
QList<QVariant> m_itemData;
QIcon m_icon;
TreeItem *m_parentItem;
};
class FileInfoModel : public QAbstractItemModel
{
Q_OBJECT
public:
explicit FileInfoModel(QObject *parent = nullptr);
explicit FileInfoModel(Media::MediaFileInfo *fileInfo, QObject *parent = nullptr);
~FileInfoModel();
const Media::MediaFileInfo *shownFileInfo() const;
Media::MediaFileInfo *shownFileInfo();
void show(Media::MediaFileInfo *fileInfo);
void update();
bool containsAnyNotifications() const;
bool containsCriticalNotifications() const;
QVariant data(const QModelIndex &index, int role) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const;
QModelIndex index(int row, int column,
const QModelIndex &parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex &index) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
private:
void showGeneralInformation();
void showAtoms(TreeItem *item, Media::Mp4Atom *atom);
void showEbmlElements(TreeItem *item, Media::EbmlElement *element);
void showTracks();
void showTagInformation();
void showTagDetails(const Media::Tag *tag, TreeItem *item);
void showNotifications(const std::list<Media::Notification> &notifications, TreeItem *item, const QString &label = tr("Notifications"), bool showEmptyEntry = true);
TreeItem *m_rootItem;
TreeItem *m_generalItem;
TreeItem *m_audioTracksItem;
TreeItem *m_videoTracksItem;
TreeItem *m_subtitleTracksItem;
TreeItem *m_otherTracksItem;
TreeItem *m_tagItem;
Media::MediaFileInfo *m_fileInfo;
bool m_anyNotifications;
bool m_criticalNotifications;
};
}
#endif // FILEINFOMODEL_H

View File

@ -1,85 +0,0 @@
#include "generalfileinfowidget.h"
#include <martchusutilities/conversion/stringconversion.h>
#include <martchusutilities/chrono/timespan.h>
#include <taginfo/mediafileinfo.h>
#include <QApplication>
#include <QPushButton>
#include <QMessageBox>
#include <QTreeView>
#include <QLabel>
using namespace std;
using namespace ConversionUtilities;
using namespace ChronoUtilities;
using namespace Media;
namespace QtGui {
GeneralFileInfoWidget::GeneralFileInfoWidget(QWidget *parent) :
InfoWidgetBase(parent),
m_pathLabel(nullptr),
m_sizeLabel(nullptr),
m_durationLabel(nullptr),
m_bitrateLabel(nullptr),
m_containerLabel(nullptr),
m_mimeTypeLabel(nullptr)
{}
GeneralFileInfoWidget::~GeneralFileInfoWidget()
{}
void GeneralFileInfoWidget::update(const MediaFileInfo &fileInfo)
{
int row = 0;
// use file name as name
setupName(fileInfo.fileName());
// notifications
setupNotifications(fileInfo);
// path
setupRow(row, "Path", m_pathLabel, fileInfo.path());
++row;
// size
setupRow(row, "Size", m_sizeLabel, dataSizeToString(fileInfo.size()));
++row;
// overall duration and bitrate
TimeSpan duration = fileInfo.duration();
if(duration.isNull()) {
removeRow(m_durationLabel);
removeRow(m_bitrateLabel);
} else {
setupRow(row, "Duration", m_durationLabel, duration.toString(TimeSpanOutputFormat::WithMeasures));
++row;
setupRow(row, "Overall avg. bitrate", m_bitrateLabel, bitrateToString(0.0078125 * fileInfo.size() / duration.totalSeconds()));
++row;
}
// container format
string container(fileInfo.containerFormatName());
const char *subversion = fileInfo.containerFormatSubversion();
if(*subversion) {
container.append(" ");
container.append(subversion);
}
setupRow(row, "Container format", m_containerLabel, container);
++row;
// mime type
const char *mimeType = fileInfo.containerMimeType();
if(*mimeType) {
setupRow(row, "Mime-type", m_mimeTypeLabel, QString::fromLocal8Bit(mimeType));
++row;
} else {
removeRow(m_mimeTypeLabel);
}
}
}

View File

@ -1,38 +0,0 @@
#ifndef GENERALFILEINFOWIDGET_H
#define GENERALFILEINFOWIDGET_H
#include "infowidgetbase.h"
#include <string>
QT_BEGIN_NAMESPACE
class QLabel;
QT_END_NAMESPACE
namespace Media {
class MediaFileInfo;
}
namespace QtGui {
class GeneralFileInfoWidget : public InfoWidgetBase
{
Q_OBJECT
public:
explicit GeneralFileInfoWidget(QWidget *parent = nullptr);
~GeneralFileInfoWidget();
void update(const Media::MediaFileInfo &fileInfo);
private:
QLabel *m_pathLabel;
QLabel *m_sizeLabel;
QLabel *m_durationLabel;
QLabel *m_bitrateLabel;
QLabel *m_containerLabel;
QLabel *m_mimeTypeLabel;
};
}
#endif // GENERALFILEINFOWIDGET_H

View File

@ -5,7 +5,7 @@
// include configuration from separate header file when building with CMake
#ifndef APP_METADATA_AVAIL
#include "config.h"
#include "resources/config.h"
#endif
#include <qtutilities/resources/qtconfigarguments.h>

40
resources/windows.rc.in Normal file
View File

@ -0,0 +1,40 @@
# if defined(UNDER_CE)
# include <winbase.h>
# else
# include <windows.h>
# endif
@WINDOWS_ICON_RC_ENTRY@
VS_VERSION_INFO VERSIONINFO
FILEVERSION @META_VERSION_MAJOR@,@META_VERSION_MINOR@,@META_VERSION_PATCH@,0
PRODUCTVERSION @META_VERSION_MAJOR@,@META_VERSION_MINOR@,@META_VERSION_PATCH@,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS VS_FF_DEBUG
#else
FILEFLAGS 0x0L
#endif
FILEOS VOS__WINDOWS32
FILETYPE VFT_DLL
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "@META_APP_AUTHOR@\0"
VALUE "FileDescription", "@META_APP_DESCRIPTION@.\0"
VALUE "FileVersion", "@META_APP_VERSION@\0"
VALUE "LegalCopyright", "by @META_APP_AUTHOR@\0"
VALUE "OriginalFilename", "@META_PROJECT_NAME@.@WINDOWS_EXT@\0"
VALUE "ProductName", "@META_APP_NAME@\0"
VALUE "ProductVersion", "@META_APP_VERSION@\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0409, 1200
END
END
/* End of Version info */

View File

@ -1,9 +1,10 @@
# meta data
projectname = tageditor
appname = "Tag Editor"
appauthor = Martchus
appurl = "https://github.com/$${appauthor}/$${projectname}"
QMAKE_TARGET_DESCRIPTION = "A tageditor with Qt GUI and command line interface. Supports MP4 (iTunes), ID3, Vorbis and Matroska."
VERSION = 1.2.0
VERSION = 1.3.0
# include ../../common.pri when building as part of a subdirs project; otherwise include general.pri
!include(../../common.pri) {
@ -12,12 +13,10 @@ VERSION = 1.2.0
}
}
# basic configuration: application
TEMPLATE = app
QT += core gui script
greaterThan(QT_MAJOR_VERSION, 4) {
QT += widgets
}
QT += core gui widgets script
# use webenginewidgets if available; otherwise use webkitwidgets
!forcewebkit:qtHaveModule(webenginewidgets) {
QT += webenginewidgets
DEFINES += TAGEDITOR_USE_WEBENGINE
@ -25,6 +24,37 @@ greaterThan(QT_MAJOR_VERSION, 4) {
QT += webkitwidgets
}
# add project files
HEADERS += application/main.h \
application/knownfieldmodel.h \
application/settings.h \
gui/filefilterproxymodel.h \
gui/tagfieldedit.h \
gui/tagedit.h \
gui/mainwindow.h \
gui/pathlineedit.h \
gui/notificationlabel.h \
gui/renamefilesdialog.h \
gui/javascripthighlighter.h \
gui/picturepreviewselection.h \
gui/notificationmodel.h \
gui/infowidgetbase.h \
gui/settingsdialog.h \
renamingutility/filesystemitem.h \
renamingutility/filesystemitemmodel.h \
renamingutility/filteredfilesystemitemmodel.h \
renamingutility/renamingengine.h \
renamingutility/scriptfunctions.h \
misc/htmlinfo.h \
gui/previousvaluehandling.h \
gui/initiate.h \
cli/mainfeatures.h \
misc/utility.h \
gui/entertargetdialog.h \
gui/attachmentsmodel.h \
gui/attachmentsedit.h \
gui/codeedit.h
SOURCES += application/main.cpp \
application/knownfieldmodel.cpp \
application/settings.cpp \
@ -55,36 +85,6 @@ SOURCES += application/main.cpp \
gui/attachmentsedit.cpp \
gui/codeedit.cpp
HEADERS += application/main.h \
application/knownfieldmodel.h \
application/settings.h \
gui/filefilterproxymodel.h \
gui/tagfieldedit.h \
gui/tagedit.h \
gui/mainwindow.h \
gui/pathlineedit.h \
gui/notificationlabel.h \
gui/renamefilesdialog.h \
gui/javascripthighlighter.h \
gui/picturepreviewselection.h \
gui/notificationmodel.h \
gui/infowidgetbase.h \
gui/settingsdialog.h \
renamingutility/filesystemitem.h \
renamingutility/filesystemitemmodel.h \
renamingutility/filteredfilesystemitemmodel.h \
renamingutility/renamingengine.h \
renamingutility/scriptfunctions.h \
misc/htmlinfo.h \
gui/previousvaluehandling.h \
gui/initiate.h \
cli/mainfeatures.h \
misc/utility.h \
gui/entertargetdialog.h \
gui/attachmentsmodel.h \
gui/attachmentsedit.h \
gui/codeedit.h
FORMS += \
gui/id3v2optionpage.ui \
gui/id3v1optionpage.ui \
@ -102,19 +102,27 @@ FORMS += \
gui/editortempoptionpage.ui \
gui/filelayout.ui
RESOURCES += resources/icons.qrc \
RESOURCES += \
resources/icons.qrc \
resources/scripts.qrc
TRANSLATIONS = translations/tageditor_en_US.ts \
translations/tageditor_de_DE.ts
include(translations.pri)
win32:include(windowsicon.pri)
OTHER_FILES += \
README.md \
LICENSE
LICENSE \
CMakeLists.txt \
resources/config.h.in \
resources/windows.rc.in
# release translations
include(translations.pri)
# make windows icon
win32:include(windowsicon.pri)
# add libs
CONFIG(debug, debug|release) {
LIBS += -lc++utilitiesd -ltagparserd
!no-gui {