/*
Copyright 2012-2013, 2015 Adam Reichold
This file is part of qpdfview.
qpdfview is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
qpdfview is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with qpdfview. If not, see .
*/
#include "pluginhandler.h"
#include
#include
#include
#include
#include
#include
#include
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#include
#endif // QT_VERSION
#ifdef WITH_MAGIC
#include
#endif // WITH_MAGIC
#include "model.h"
namespace
{
using namespace qpdfview;
Plugin* loadStaticPlugin(const QString& objectName)
{
foreach(QObject* object, QPluginLoader::staticInstances())
{
if(object->objectName() == objectName)
{
Plugin* plugin = qobject_cast< Plugin* >(object);
if(plugin != 0)
{
return plugin;
}
}
}
qCritical() << "Could not load static plug-in:" << objectName;
return 0;
}
Plugin* loadPlugin(const QString& fileName)
{
//QPluginLoader pluginLoader(QDir(QApplication::applicationDirPath()).absoluteFilePath(fileName));
QPluginLoader pluginLoader("/usr/lib/terepaima/"+fileName);
//qDebug("****loadPlugin****");
//qDebug() << QDir(QApplication::applicationDirPath()).absoluteFilePath(fileName);
//qDebug("******************");
if(!pluginLoader.load())
{
const QString firstFileName = pluginLoader.fileName();
const QString firstErrorString = pluginLoader.errorString();
pluginLoader.setFileName(QDir(PLUGIN_INSTALL_PATH).absoluteFilePath(fileName));
//qDebug("loadPlugin failed:");
//qDebug() << QDir(QApplication::applicationDirPath()).absoluteFilePath(fileName) << "endl";
if(!pluginLoader.load())
{
qCritical() << "Could not load plug-in in first attempt:" << firstFileName;
qCritical() << firstErrorString;
qCritical() << "Could not load plug-in in second attempt:" << pluginLoader.fileName();
qCritical() << pluginLoader.errorString();
return 0;
}
}
Plugin* plugin = qobject_cast< Plugin* >(pluginLoader.instance());
if(plugin == 0)
{
qCritical() << "Could not instantiate plug-in:" << pluginLoader.fileName();
qCritical() << pluginLoader.errorString();
}
return plugin;
}
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
bool isSupportedImageFormat(const QMimeType& mimeType)
{
const QByteArray name = mimeType.name().toLocal8Bit();
return QImageReader::supportedMimeTypes().contains(name);
}
#else
bool isSupportedImageFormat(const QString& fileName)
{
return !QImageReader::imageFormat(fileName).isEmpty();
}
#endif // QT_VERSION
QStringList supportedImageFormats()
{
QStringList formats;
foreach(const QByteArray& format, QImageReader::supportedImageFormats())
{
const QString name = QString::fromLocal8Bit(format);
formats.append(QLatin1String("*.") + name);
}
return formats;
}
const char* const pdfMimeType = "application/pdf";
const char* const psMimeType = "application/postscript";
const char* const djvuMimeType = "image/vnd.djvu";
PluginHandler::FileType matchFileType(const QString& filePath)
{
PluginHandler::FileType fileType = PluginHandler::Unknown;
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
const QMimeType mimeType = QMimeDatabase().mimeTypeForFile(filePath, QMimeDatabase::MatchContent);
if(mimeType.inherits(pdfMimeType))
{
fileType = PluginHandler::PDF;
}
else if(mimeType.inherits(psMimeType))
{
fileType = PluginHandler::PS;
}
else if(mimeType.inherits(djvuMimeType))
{
fileType = PluginHandler::DjVu;
}
else if(isSupportedImageFormat(mimeType))
{
fileType = PluginHandler::Image;
}
else
{
qDebug() << "Unknown MIME type:" << mimeType.name();
}
#else
#ifdef WITH_MAGIC
magic_t cookie = magic_open(MAGIC_MIME_TYPE | MAGIC_SYMLINK);
if(magic_load(cookie, 0) == 0)
{
const char* mimeType = magic_file(cookie, QFile::encodeName(filePath));
if(qstrncmp(mimeType, pdfMimeType, qstrlen(pdfMimeType)) == 0)
{
fileType = PluginHandler::PDF;
}
else if(qstrncmp(mimeType, psMimeType, qstrlen(psMimeType)) == 0)
{
fileType = PluginHandler::PS;
}
else if(qstrncmp(mimeType, djvuMimeType, qstrlen(djvuMimeType)) == 0)
{
fileType = PluginHandler::DjVu;
}
else if(isSupportedImageFormat(filePath))
{
fileType = PluginHandler::Image;
}
else
{
qDebug() << "Unknown MIME type:" << mimeType;
}
}
magic_close(cookie);
#else
const QString suffix = QFileInfo(filePath).suffix().toLower();
if(suffix == QLatin1String("pdf"))
{
fileType = PluginHandler::PDF;
}
else if(suffix == QLatin1String("ps") || suffix == QLatin1String("eps"))
{
fileType = PluginHandler::PS;
}
else if(suffix == QLatin1String("djvu") || suffix == QLatin1String("djv"))
{
fileType = PluginHandler::DjVu;
}
else if(isSupportedImageFormat(filePath))
{
fileType = PluginHandler::Image;
}
else
{
qDebug() << "Unkown file suffix:" << suffix;
}
#endif // WITH_MAGIC
#endif // QT_VERSION
return fileType;
}
} // anonymous
namespace qpdfview
{
PluginHandler* PluginHandler::s_instance = 0;
PluginHandler* PluginHandler::instance()
{
if(s_instance == 0)
{
s_instance = new PluginHandler(qApp);
}
return s_instance;
}
PluginHandler::~PluginHandler()
{
s_instance = 0;
}
QString PluginHandler::fileTypeName(PluginHandler::FileType fileType)
{
switch(fileType)
{
default:
case PluginHandler::Unknown:
return QLatin1String("Unknown");
case PluginHandler::PDF:
return QLatin1String("PDF");
case PluginHandler::PS:
return QLatin1String("PS");
case PluginHandler::DjVu:
return QLatin1String("DjVu");
case PluginHandler::Image:
return QLatin1String("Image");
}
}
QStringList PluginHandler::openFilter()
{
QStringList openFilter;
QStringList supportedFormats;
#if defined(WITH_PDF) || defined(WITH_FITZ)
openFilter.append(QLatin1String("Portable document format (*.pdf)"));
supportedFormats.append(QLatin1String("*.pdf"));
#endif // WITH_PDF // WITH_FITZ
#ifdef WITH_PS
openFilter.append(QLatin1String("PostScript (*.ps)"));
openFilter.append(QLatin1String("Encapsulated PostScript (*.eps)"));
supportedFormats.append(QLatin1String("*.ps *.eps"));
#endif // WITH_PS
#ifdef WITH_DJVU
openFilter.append(QLatin1String("DjVu (*.djvu *.djv)"));
supportedFormats.append(QLatin1String("*.djvu *.djv"));
#endif // WITH_DJVU
#ifdef WITH_IMAGE
const QStringList imageFormats = supportedImageFormats();
openFilter.append(tr("Image (%1)").arg(imageFormats.join(QLatin1String(" "))));
supportedFormats.append(imageFormats);
#endif // WITH_IMAGE
openFilter.prepend(tr("Supported formats (%1)").arg(supportedFormats.join(QLatin1String(" "))));
return openFilter;
}
Model::Document* PluginHandler::loadDocument(const QString& filePath)
{
const FileType fileType = matchFileType(filePath);
if(fileType == Unknown)
{
qWarning() << tr("Could not match file type of '%1'!").arg(filePath);
return 0;
}
if(!loadPlugin(fileType))
{
QMessageBox::critical(0, tr("Critical"), tr("Could not load plug-in for file type '%1'!").arg(fileTypeName(fileType)));
return 0;
}
return m_plugins.value(fileType)->loadDocument(filePath);
}
SettingsWidget* PluginHandler::createSettingsWidget(FileType fileType, QWidget* parent)
{
return loadPlugin(fileType) ? m_plugins.value(fileType)->createSettingsWidget(parent) : 0;
}
PluginHandler::PluginHandler(QObject* parent) : QObject(parent),
m_plugins()
{
#ifdef WITH_IMAGE
#ifdef STATIC_IMAGE_PLUGIN
m_objectNames.insertMulti(Image, QLatin1String("ImagePlugin"));
#else
m_fileNames.insertMulti(Image, QLatin1String(IMAGE_PLUGIN_NAME));
#endif // STATIC_IMAGE_PLUGIN
#endif // WITH_IMAGE
#ifdef WITH_FITZ
#ifdef STATIC_FITZ_PLUGIN
m_objectNames.insertMulti(PDF, QLatin1String("FitzPlugin"));
#else
m_fileNames.insertMulti(PDF, QLatin1String(FITZ_PLUGIN_NAME));
#endif // STATIC_FITZ_PLUGIN
#endif // WITH_FITZ
#ifdef WITH_PDF
#ifdef STATIC_PDF_PLUGIN
m_objectNames.insertMulti(PDF, QLatin1String("PdfPlugin"));
#else
m_fileNames.insertMulti(PDF, QLatin1String(PDF_PLUGIN_NAME));
#endif // STATIC_PDF_PLUGIN
#endif // WITH_PDF
#ifdef WITH_PS
#ifdef STATIC_PS_PLUGIN
m_objectNames.insertMulti(PS, QLatin1String("PsPlugin"));
#else
m_fileNames.insertMulti(PS, QLatin1String(PS_PLUGIN_NAME));
#endif // STATIC_PS_PLUGIN
#endif // WITH_PS
#ifdef WITH_DJVU
#ifdef STATIC_DJVU_PLUGIN
m_objectNames.insertMulti(DjVu, QLatin1String("DjVuPlugin"));
#else
m_fileNames.insertMulti(DjVu, QLatin1String(DJVU_PLUGIN_NAME));
#endif // STATIC_DJVU_PLUGIN
#endif // WITH_DJVU
}
bool PluginHandler::loadPlugin(FileType fileType)
{
if(m_plugins.contains(fileType))
{
return true;
}
foreach(const QString& objectName, m_objectNames.values(fileType))
{
if(Plugin* plugin = ::loadStaticPlugin(objectName))
{
m_plugins.insert(fileType, plugin);
return true;
}
}
foreach(const QString& fileName, m_fileNames.values(fileType))
{
if(Plugin* plugin = ::loadPlugin(fileName))
{
m_plugins.insert(fileType, plugin);
return true;
}
}
return false;
}
} // qpdfview
#ifdef STATIC_IMAGE_PLUGIN
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
Q_IMPORT_PLUGIN(qpdfview_image)
#else
Q_IMPORT_PLUGIN(ImagePlugin)
#endif // QT_VERSION
#endif // STATIC_IMAGE_PLUGIN
#ifdef STATIC_FITZ_PLUGIN
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
Q_IMPORT_PLUGIN(qpdfview_fitz)
#else
Q_IMPORT_PLUGIN(FitzPlugin)
#endif // QT_VERSION
#endif // STATIC_FITZ_PLUGIN
#ifdef STATIC_PDF_PLUGIN
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
Q_IMPORT_PLUGIN(qpdfview_pdf)
#else
Q_IMPORT_PLUGIN(PdfPlugin)
#endif // QT_VERSION
#endif // STATIC_PDF_PLUGIN
#ifdef STATIC_PS_PLUGIN
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
Q_IMPORT_PLUGIN(qpdfview_ps)
#else
Q_IMPORT_PLUGIN(PsPlugin)
#endif // QT_VERSION
#endif // STATIC_PS_PLUGIN
#ifdef STATIC_DJVU_PLUGIN
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
Q_IMPORT_PLUGIN(qpdfview_djvu)
#else
Q_IMPORT_PLUGIN(DjvuPlugin)
#endif // QT_VERSION
#endif // STATIC_DJVU_PLUGIN