#include "toonzqt/infoviewer.h"
#include "toonzqt/intfield.h"
#include "tsystem.h"
#include "tlevel.h"
#include "tpalette.h"
#include "tlevel_io.h"
#include "tsound_io.h"
#include "tiio.h"
#include "tstream.h"
#include "ttoonzimage.h"
#include "trasterimage.h"
#include "tvectorimage.h"
#include "toonz/toonzscene.h"
#include "toonzqt/gutil.h"
#include "toonzqt/dvdialog.h"
#include "toutputproperties.h"
#include "toonz/sceneproperties.h"
#include "toonz/tcamera.h"
#include "toonz/levelset.h"
#include "tcontenthistory.h"
#include "tfiletype.h"
#include <QSlider>
#include <QLabel>
#include <QTextEdit>
#include <QDateTime>
using namespace DVGui;
//----------------------------------------------------------------
class InfoViewerImp
{
public:
enum {
eFullpath = 0,
eFileType,
eFrames,
eOwner,
eSize,
eCreated,
eModified,
eLastAccess,
eImageSize,
eSaveBox,
eBitsSample,
eSamplePixel,
eDpi,
eOrientation,
eCompression,
eQuality,
eSmoothing,
eCodec,
eAlphaChannel,
eByteOrdering,
eHPos,
ePalettePages,
ePaletteStyles,
eCamera,
eCameraDpi,
eFrameCount,
eLevelCount,
eOutputPath,
eEndianess,
//sound info
eLength,
eChannels,
eSampleRate,
eSampleSize,
eHowMany
};
TFilePath m_path;
TLevelP m_level;
std::vector<TFrameId> m_fids;
QStringList m_formats;
int m_currentIndex;
int m_frameCount;
TPalette *m_palette;
QLabel m_framesLabel;
IntField m_framesSlider;
std::vector<std::pair<QLabel *, QLabel *>> m_labels;
QLabel m_historyLabel;
QTextEdit m_history;
Separator m_separator1, m_separator2;
void setFileInfo(const TFileStatus &status);
void setImageInfo();
void setSoundInfo();
//void cleanFileInfo();
void cleanLevelInfo();
void setToonzSceneInfo();
void setPaletteInfo();
void setGeneralFileInfo(const TFilePath &path);
QString getTypeString();
void onSliderChanged();
InfoViewerImp();
~InfoViewerImp();
void clear();
bool setLabel(TPropertyGroup *pg, int index, std::string type);
void create(int index, QString str);
void loadPalette(const TFilePath &path);
inline void setVal(int index, const QString &str)
{
m_labels[index].second->setText(str);
}
public slots:
bool setItem(const TLevelP &level, TPalette *palette, const TFilePath &path);
};
//----------------------------------------------------------------
InfoViewer::InfoViewer(QWidget *parent)
: Dialog()
, m_imp(new InfoViewerImp())
{
setWindowTitle(tr("File Info"));
setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
//setAttribute(Qt::WA_DeleteOnClose);
m_parent = parent;
int i;
for (i = 0; i < (int)m_imp->m_labels.size(); i++) {
addWidgets(m_imp->m_labels[i].first, m_imp->m_labels[i].second);
if (i == InfoViewerImp::eLastAccess)
addWidget(&m_imp->m_separator1);
}
addWidget(&m_imp->m_separator2);
addWidget(&m_imp->m_historyLabel);
addWidget(&m_imp->m_history);
addWidgets(&m_imp->m_framesLabel, &m_imp->m_framesSlider);
connect(&m_imp->m_framesSlider, SIGNAL(valueChanged(bool)), this, SLOT(onSliderChanged(bool)));
hide();
}
InfoViewer::~InfoViewer()
{
}
//----------------------------------------------------------------
void InfoViewer::hideEvent(QHideEvent *)
{
m_imp->m_level = TLevelP();
if (m_parent) {
m_parent->setWindowModality(Qt::ApplicationModal);
//setWindowModality(Qt::NonModal);
}
}
void InfoViewer::showEvent(QShowEvent *)
{
if (m_parent) {
m_parent->setWindowModality(Qt::NonModal);
//setWindowModality(Qt::WindowModal);
}
}
//----------------------------------------------------------------
void InfoViewer::onSliderChanged(bool)
{
m_imp->onSliderChanged();
}
//----------------------------------------------------------------
void InfoViewerImp::onSliderChanged()
{
if (m_framesSlider.getValue() - 1 == m_currentIndex)
return;
m_currentIndex = m_framesSlider.getValue() - 1;
setImageInfo();
}
//----------------------------------------------------------------
namespace
{
void setLabelStyle(QLabel *l)
{
l->setFrameStyle(QFrame::StyledPanel);
l->setStyleSheet("color: rgb(0, 0, 200);");
}
}
//----------------------------------------------------------------
void InfoViewerImp::create(int index, QString str)
{
m_labels[index] = std::pair<QLabel *, QLabel *>(new QLabel(str), new QLabel(""));
setLabelStyle(m_labels[index].first);
}
//----------------------------------------------------------------
InfoViewerImp::InfoViewerImp()
: m_palette(0), m_framesLabel("Current Frame: "), m_framesSlider(), m_history(), m_historyLabel("File History")
{
setLabelStyle(&m_framesLabel);
TLevelReader::getSupportedFormats(m_formats);
TSoundTrackReader::getSupportedFormats(m_formats);
m_labels.resize(eHowMany);
create(eFullpath, QObject::tr("Fullpath: "));
create(eFileType, QObject::tr("File Type: "));
create(eFrames, QObject::tr("Frames: "));
create(eOwner, QObject::tr("Owner: "));
create(eSize, QObject::tr("Size: "));
create(eCreated, QObject::tr("Created: "));
create(eModified, QObject::tr("Modified: "));
create(eLastAccess, QObject::tr("Last Access: "));
//level info
create(eImageSize, QObject::tr("Image Size: "));
create(eSaveBox, QObject::tr("SaveBox: "));
create(eBitsSample, QObject::tr("Bits/Sample: "));
create(eSamplePixel, QObject::tr("Sample/Pixel: "));
create(eDpi, QObject::tr("Dpi: "));
create(eOrientation, QObject::tr("Orientation: "));
create(eCompression, QObject::tr("Compression: "));
create(eQuality, QObject::tr("Quality: "));
create(eSmoothing, QObject::tr("Smoothing: "));
create(eCodec, QObject::tr("Codec: "));
create(eAlphaChannel, QObject::tr("Alpha Channel:"));
create(eByteOrdering, QObject::tr("Byte Ordering:"));
create(eHPos, QObject::tr("H Pos:"));
create(ePalettePages, QObject::tr("Palette Pages:"));
create(ePaletteStyles, QObject::tr("Palette Styles:"));
create(eCamera, QObject::tr("Camera Size: "));
create(eCameraDpi, QObject::tr("Camera Dpi: "));
create(eFrameCount, QObject::tr("Number of Frames: "));
create(eLevelCount, QObject::tr("Number of Levels: "));
create(eOutputPath, QObject::tr("Output Path: "));
create(eEndianess, QObject::tr("Endianess: "));
//sound info
create(eLength, QObject::tr("Length: "));
create(eChannels, QObject::tr("Channels: "));
create(eSampleRate, QObject::tr("Sample Rate: "));
create(eSampleSize, QObject::tr("Sample Size: "));
m_historyLabel.setStyleSheet("color: rgb(0, 0, 200);");
m_history.setStyleSheet("font-size: 12px; font-family: \"courier\";");
//m_history.setStyleSheet("font-family: \"courier\";");
m_history.setReadOnly(true);
m_history.setFixedWidth(490);
}
//----------------------------------------------------------------
void InfoViewerImp::clear()
{
int i;
for (i = 0; i < (int)m_labels.size(); i++)
setVal(i, "");
m_history.clear();
}
//----------------------------------------------------------------
InfoViewerImp::~InfoViewerImp()
{
int i;
for (i = 0; i < (int)m_labels.size(); i++) {
delete m_labels[i].first;
delete m_labels[i].second;
}
m_labels.clear();
}
//----------------------------------------------------------------
void InfoViewerImp::setFileInfo(const TFileStatus &status)
{
//m_fPath.setText(status.
}
//----------------------------------------------------------------
QString InfoViewerImp::getTypeString()
{
QString ext = QString::fromStdString(m_path.getType());
if (ext == "tlv" || ext == "tzp" || ext == "tzu")
return "Toonz Cmapped Raster Level";
else if (ext == "pli" || ext == "svg")
return "Toonz Vector Level";
else if (ext == "mov" || ext == "avi" || ext == "3gp")
return "Movie File";
else if (ext == "tnz")
return "Toonz Scene";
else if (ext == "tab")
return "Tab Scene";
else if (ext == "plt")
return "Toonz Palette";
else if (ext == "wav" || ext == "aiff" || ext == "mp3")
return "Audio File";
else if (ext == "mesh")
return "Toonz Mesh Level";
else if (ext == "pic")
return "Pic File";
else if (Tiio::makeReader(ext.toStdString()))
return (m_fids.size() == 1) ? "Single Raster Image" : "Raster Image Level";
else if (ext == "psd")
return "Photoshop Image";
else
return "Unmanaged File Type";
}
//----------------------------------------------------------------
void InfoViewerImp::setGeneralFileInfo(const TFilePath &path)
{
QFileInfo fi = toQString(path);
assert(fi.exists());
setVal(eFullpath, fi.absoluteFilePath());
setVal(eFileType, getTypeString());
if (fi.owner() != "")
setVal(eOwner, fi.owner());
setVal(eSize, fileSizeString(fi.size()));
setVal(eCreated, fi.created().toString());
setVal(eModified, fi.lastModified().toString());
setVal(eLastAccess, fi.lastRead().toString());
m_separator1.show();
}
//----------------------------------------------------------------
bool InfoViewerImp::setLabel(TPropertyGroup *pg, int index, std::string type)
{
TProperty *p = pg->getProperty(type);
if (!p)
return false;
QString str = QString::fromStdString(p->getValueAsString());
if (dynamic_cast<TBoolProperty *>(p))
setVal(index, str == "0" ? "No" : "Yes");
else
setVal(index, str);
return true;
}
//----------------------------------------------------------------
void InfoViewerImp::setImageInfo()
{
if (m_path != TFilePath() && !m_fids.empty())
setGeneralFileInfo(m_path.getType() == "tlv" || !m_path.isLevelName() ? m_path : m_path.withFrame(m_fids[m_currentIndex]));
assert(m_level);
setVal(eFrames, QString::number(m_level->getFrameCount()));
TLevelReaderP lr(m_path);
const TImageInfo *ii;
try {
ii = lr->getImageInfo(m_fids[m_currentIndex]);
} catch (...) {
return;
}
if (!m_fids.empty() && lr && ii) {
setVal(eImageSize, QString::number(ii->m_lx) + " X " + QString::number(ii->m_ly));
if (ii->m_x0 <= ii->m_x1)
setVal(eSaveBox, "(" + QString::number(ii->m_x0) + ", " + QString::number(ii->m_y0) + ", " + QString::number(ii->m_x1) + ", " + QString::number(ii->m_y1) + ")");
if (ii->m_bitsPerSample > 0)
setVal(eBitsSample, QString::number(ii->m_bitsPerSample));
if (ii->m_samplePerPixel > 0)
setVal(eSamplePixel, QString::number(ii->m_samplePerPixel));
if (ii->m_dpix > 0 || ii->m_dpiy > 0)
setVal(eDpi, "(" + QString::number(ii->m_dpix) + ", " + QString::number(ii->m_dpiy) + ")");
TPropertyGroup *pg = ii->m_properties;
if (pg) {
setLabel(pg, eOrientation, "Orientation");
if (!setLabel(pg, eCompression, "Compression") && !setLabel(pg, eCompression, "Compression Type") && !setLabel(pg, eCompression, "RLE-Compressed"))
setLabel(pg, eCompression, "File Compression");
setLabel(pg, eQuality, "Quality");
setLabel(pg, eSmoothing, "Smoothing");
setLabel(pg, eCodec, "Codec");
setLabel(pg, eAlphaChannel, "Alpha Channel");
setLabel(pg, eByteOrdering, "Byte Ordering");
setLabel(pg, eEndianess, "Endianess");
}
} else
m_separator1.hide();
const TContentHistory *ch = 0;
if (lr)
ch = lr->getContentHistory();
if (ch) {
QString str = ch->serialize();
str = str.remove('\n');
str = str.remove(QChar(0));
str = str.replace("||", "\n");
str = str.remove('|');
m_history.setPlainText(str);
}
TImageP img = m_level->frame(m_fids[m_currentIndex]);
TToonzImageP timg = (TToonzImageP)img;
TRasterImageP rimg = (TRasterImageP)img;
TVectorImageP vimg = (TVectorImageP)img;
if (img) {
TRect r = convert(timg->getBBox());
if (r.x0 <= r.x1)
setVal(eSaveBox, "(" + QString::number(r.x0) + ", " + QString::number(r.y0) + ", " + QString::number(r.x1) + ", " + QString::number(r.y1) + ")");
}
double dpix, dpiy;
if (timg) {
//setVal(eHPos, QString::number(timg->gethPos()));
timg->getDpi(dpix, dpiy);
setVal(eDpi, "(" + QString::number(dpix) + ", " + QString::number(dpiy) + ")");
TDimension dim = timg->getRaster()->getSize();
setVal(eImageSize, QString::number(dim.lx) + " X " + QString::number(dim.ly));
m_palette = timg->getPalette();
} else if (rimg) {
rimg->getDpi(dpix, dpiy);
setVal(eDpi, "(" + QString::number(dpix) + ", " + QString::number(dpiy) + ")");
TDimension dim = rimg->getRaster()->getSize();
setVal(eImageSize, QString::number(dim.lx) + " X " + QString::number(dim.ly));
} else if (vimg)
m_palette = vimg->getPalette();
//TImageP img = m_level->frame(m_fids[m_currentIndex]);
}
//----------------------------------------------------------------
void InfoViewerImp::setSoundInfo()
{
if (m_path != TFilePath())
setGeneralFileInfo(m_path);
TSoundTrackP sndTrack;
try {
TSoundTrackReaderP sr(m_path);
if (sr)
sndTrack = sr->load();
} catch (...) {
return;
}
if (!sndTrack)
return;
int seconds = sndTrack->getDuration();
int minutes = seconds / 60;
seconds = seconds % 60;
QString label;
if (minutes > 0)
label += QString::number(minutes) + " min ";
label += QString::number(seconds) + " sec";
setVal(eLength, label);
label = QString::number(sndTrack->getChannelCount());
setVal(eChannels, label);
TUINT32 sampleRate = sndTrack->getSampleRate();
label = QString::number(sampleRate / 1000) + " KHz";
setVal(eSampleRate, label);
label = QString::number(sndTrack->getBitPerSample()) + " bit";
setVal(eSampleSize, label);
}
//----------------------------------------------------------------
void InfoViewerImp::cleanLevelInfo()
{
}
//----------------------------------------------------------------
void InfoViewer::setItem(const TLevelP &level, TPalette *palette, const TFilePath &path)
{
if (m_imp->setItem(level, palette, path))
show();
else
hide();
}
//----------------------------------------------------------------
void InfoViewerImp::setToonzSceneInfo()
{
ToonzScene scene;
try {
scene.loadNoResources(m_path);
} catch (...) {
return;
}
TCamera *cam = scene.getCurrentCamera();
if (!cam)
return;
TContentHistory *ch = scene.getContentHistory();
if (ch) {
QString str = ch->serialize();
str = str.remove('\n');
str = str.remove(QChar(0));
str = str.replace("||", "\n");
str = str.remove('|');
m_history.setPlainText(str);
}
TLevelSet *set = scene.getLevelSet();
TSceneProperties *prop = scene.getProperties();
TOutputProperties *oprop = prop->getOutputProperties();
setVal(eCamera, QString::number(cam->getRes().lx) + " X " + QString::number(cam->getRes().ly));
setVal(eCameraDpi, QString::number(cam->getDpi().x) + ", " + QString::number(cam->getDpi().y));
setVal(eFrameCount, QString::number(scene.getFrameCount()));
if (set)
setVal(eLevelCount, QString::number(set->getLevelCount()));
if (oprop)
setVal(eOutputPath, toQString(oprop->getPath()));
}
//----------------------------------------------------------------
void InfoViewerImp::setPaletteInfo()
{
if (!m_palette)
return;
setVal(ePalettePages, QString::number(m_palette->getPageCount()));
setVal(ePaletteStyles, QString::number(m_palette->getStyleCount()));
}
//----------------------------------------------------------------
void InfoViewerImp::loadPalette(const TFilePath &path)
{
TIStream is(path);
if (is) {
TPersist *p = 0;
is >> p;
m_palette = dynamic_cast<TPalette *>(p);
}
}
//----------------------------------------------------------------
bool InfoViewerImp::setItem(const TLevelP &level, TPalette *palette, const TFilePath &path)
{
int i;
clear();
m_path = path;
m_level = level;
m_fids.clear();
m_currentIndex = 0;
m_palette = palette;
m_framesLabel.hide();
m_framesSlider.hide();
m_separator1.hide();
m_separator2.hide();
QString ext = QString::fromStdString(m_path.getType());
if (m_path != TFilePath() && !m_formats.contains(ext) && !Tiio::makeReader(m_path.getType())) {
// e' un file non di immagine (plt, tnz, ...)
assert(!m_level);
if (!TSystem::doesExistFileOrLevel(m_path)) {
DVGui::warning(QObject::tr("The file %1 does not exist.").arg(QString::fromStdWString(path.getWideString())));
return false;
}
setGeneralFileInfo(m_path);
if (ext == "plt") {
assert(!m_level && !m_palette);
loadPalette(m_path);
} else if (ext == "tnz")
setToonzSceneInfo();
} else if (TFileType::getInfo(m_path) == TFileType::AUDIO_LEVEL) {
setSoundInfo();
} else {
if (ext == "tlv")
loadPalette(m_path.withNoFrame().withType("tpl"));
if (!m_level) {
assert(m_path != TFilePath());
TLevelReaderP lr;
try {
lr = TLevelReaderP(m_path);
} catch (...) {
return false;
}
if (lr) {
try {
m_level = lr->loadInfo();
} catch (...) {
return false;
}
}
}
if (m_level) {
// Image or level of images case
// TLVs are not intended as movie file here (why?). Neither are those
bool isMovieFile =
(ext != "tlv" && m_formats.contains(ext) && !m_path.isLevelName());
m_frameCount = m_level->getFrameCount();
assert(m_frameCount);
m_fids.resize(m_frameCount);
TLevel::Iterator it = m_level->begin();
for (i = 0; it != m_level->end(); ++it, ++i)
m_fids[i] = it->first;
if (m_frameCount > 1 && !isMovieFile) {
m_framesSlider.setRange(1, m_frameCount);
m_framesSlider.setValue(0);
m_framesSlider.show();
m_framesLabel.show();
}
setImageInfo();
} else
return false;
}
if (m_palette)
setPaletteInfo();
for (i = 0; i < (int)m_labels.size(); i++)
if (m_labels[i].second->text() == "")
m_labels[i].first->hide(), m_labels[i].second->hide();
else
m_labels[i].first->show(), m_labels[i].second->show();
if (m_history.toPlainText() == "") {
m_separator2.hide();
m_historyLabel.hide();
m_history.hide();
} else {
m_separator2.show();
m_historyLabel.show();
m_history.show();
}
return true;
}