2010-06-18 11:02:48 +02:00
|
|
|
/**************************************************************************
|
|
|
|
|
**
|
2015-01-14 18:07:15 +01:00
|
|
|
** Copyright (C) 2015 Denis Mingulov.
|
|
|
|
|
** Copyright (C) 2015 The Qt Company Ltd.
|
|
|
|
|
** Contact: http://www.qt.io/licensing
|
2010-06-18 11:02:48 +02:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** This file is part of Qt Creator.
|
2010-06-18 11:02:48 +02:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** Commercial License Usage
|
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
2015-01-14 18:07:15 +01:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms and
|
|
|
|
|
** conditions see http://www.qt.io/terms-conditions. For further information
|
2014-10-01 13:21:18 +02:00
|
|
|
** use the contact form at http://www.qt.io/contact-us.
|
2010-06-18 11:02:48 +02:00
|
|
|
**
|
|
|
|
|
** GNU Lesser General Public License Usage
|
2012-10-02 09:12:39 +02:00
|
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
2014-10-01 13:21:18 +02:00
|
|
|
** General Public License version 2.1 or version 3 as published by the Free
|
|
|
|
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
|
|
|
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
|
|
|
|
** following information to ensure the GNU Lesser General Public License
|
|
|
|
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
|
|
|
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
2012-10-02 09:12:39 +02:00
|
|
|
**
|
2015-01-14 18:07:15 +01:00
|
|
|
** In addition, as a special exception, The Qt Company gives you certain additional
|
|
|
|
|
** rights. These rights are described in The Qt Company LGPL Exception
|
2010-12-17 16:01:08 +01:00
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
****************************************************************************/
|
2010-06-18 11:02:48 +02:00
|
|
|
|
|
|
|
|
#include "imageviewerfile.h"
|
|
|
|
|
#include "imageviewer.h"
|
2014-03-05 15:58:12 +01:00
|
|
|
#include "imageviewerconstants.h"
|
2010-06-18 11:02:48 +02:00
|
|
|
|
2015-05-29 13:23:52 +02:00
|
|
|
#include <coreplugin/editormanager/documentmodel.h>
|
2015-02-26 13:38:54 +01:00
|
|
|
#include <utils/fileutils.h>
|
2015-05-29 13:23:52 +02:00
|
|
|
#include <utils/mimetypes/mimedatabase.h>
|
|
|
|
|
#include <utils/qtcassert.h>
|
2015-02-26 13:38:54 +01:00
|
|
|
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QFileInfo>
|
2015-05-29 13:23:52 +02:00
|
|
|
#include <QGraphicsPixmapItem>
|
|
|
|
|
#ifndef QT_NO_SVG
|
|
|
|
|
#include <QGraphicsSvgItem>
|
|
|
|
|
#endif
|
|
|
|
|
#include <QImageReader>
|
|
|
|
|
#include <QMovie>
|
|
|
|
|
#include <QPainter>
|
|
|
|
|
#include <QPixmap>
|
2010-06-18 11:02:48 +02:00
|
|
|
|
|
|
|
|
namespace ImageViewer {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
|
2015-05-29 13:23:52 +02:00
|
|
|
class MovieItem : public QObject, public QGraphicsPixmapItem
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
MovieItem(QMovie *movie)
|
|
|
|
|
: m_movie(movie)
|
|
|
|
|
{
|
|
|
|
|
setPixmap(m_movie->currentPixmap());
|
|
|
|
|
connect(m_movie, &QMovie::updated, this, [this](const QRectF &rect) {
|
|
|
|
|
update(rect);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
|
|
|
|
|
{
|
|
|
|
|
const bool smoothTransform = painter->worldTransform().m11() < 1;
|
|
|
|
|
painter->setRenderHint(QPainter::SmoothPixmapTransform, smoothTransform);
|
|
|
|
|
painter->drawPixmap(offset(), m_movie->currentPixmap());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
QMovie *m_movie;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
ImageViewerFile::ImageViewerFile()
|
2010-06-18 11:02:48 +02:00
|
|
|
{
|
2014-03-05 15:58:12 +01:00
|
|
|
setId(Constants::IMAGEVIEWER_ID);
|
2015-01-29 14:32:36 +01:00
|
|
|
connect(this, &ImageViewerFile::mimeTypeChanged, this, &ImageViewerFile::changed);
|
2010-06-18 11:02:48 +02:00
|
|
|
}
|
|
|
|
|
|
2015-05-29 13:23:52 +02:00
|
|
|
ImageViewerFile::~ImageViewerFile()
|
|
|
|
|
{
|
|
|
|
|
cleanUp();
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-04 15:21:02 +02:00
|
|
|
Core::IDocument::OpenResult ImageViewerFile::open(QString *errorString, const QString &fileName,
|
|
|
|
|
const QString &realFileName)
|
2015-05-29 13:23:52 +02:00
|
|
|
{
|
|
|
|
|
QTC_CHECK(fileName == realFileName); // does not support auto save
|
2015-06-04 15:21:02 +02:00
|
|
|
OpenResult success = openImpl(errorString, fileName);
|
|
|
|
|
emit openFinished(success == OpenResult::Success);
|
2015-06-02 17:14:48 +02:00
|
|
|
return success;
|
|
|
|
|
}
|
2015-05-29 13:23:52 +02:00
|
|
|
|
2015-06-04 15:21:02 +02:00
|
|
|
Core::IDocument::OpenResult ImageViewerFile::openImpl(QString *errorString, const QString &fileName)
|
2015-06-02 17:14:48 +02:00
|
|
|
{
|
2015-05-29 13:23:52 +02:00
|
|
|
cleanUp();
|
|
|
|
|
m_type = TypeInvalid;
|
|
|
|
|
|
2015-06-04 15:21:02 +02:00
|
|
|
if (!QFileInfo(fileName).isReadable())
|
|
|
|
|
return OpenResult::ReadError;
|
|
|
|
|
|
2015-05-29 13:23:52 +02:00
|
|
|
QByteArray format = QImageReader::imageFormat(fileName);
|
|
|
|
|
// if it is impossible to recognize a file format - file will not be open correctly
|
|
|
|
|
if (format.isEmpty()) {
|
|
|
|
|
if (errorString)
|
|
|
|
|
*errorString = tr("Image format not supported.");
|
2015-06-04 15:21:02 +02:00
|
|
|
return OpenResult::CannotHandle;
|
2015-05-29 13:23:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifndef QT_NO_SVG
|
|
|
|
|
if (format.startsWith("svg")) {
|
|
|
|
|
m_type = TypeSvg;
|
|
|
|
|
m_tempSvgItem = new QGraphicsSvgItem(fileName);
|
|
|
|
|
QRectF bound = m_tempSvgItem->boundingRect();
|
|
|
|
|
if (bound.width() == 0 && bound.height() == 0) {
|
|
|
|
|
if (errorString)
|
|
|
|
|
*errorString = tr("Failed to read SVG image.");
|
2015-06-04 15:21:02 +02:00
|
|
|
return OpenResult::CannotHandle;
|
2015-05-29 13:23:52 +02:00
|
|
|
}
|
|
|
|
|
emit imageSizeChanged(QSize());
|
|
|
|
|
} else
|
|
|
|
|
#endif
|
|
|
|
|
if (QMovie::supportedFormats().contains(format)) {
|
|
|
|
|
m_type = TypeMovie;
|
|
|
|
|
m_movie = new QMovie(fileName, QByteArray(), this);
|
|
|
|
|
m_movie->setCacheMode(QMovie::CacheAll);
|
|
|
|
|
connect(m_movie, &QMovie::finished, m_movie, &QMovie::start);
|
|
|
|
|
connect(m_movie, &QMovie::resized, this, &ImageViewerFile::imageSizeChanged);
|
|
|
|
|
m_movie->start();
|
|
|
|
|
m_isPaused = false; // force update
|
|
|
|
|
setPaused(true);
|
|
|
|
|
} else {
|
|
|
|
|
m_type = TypePixmap;
|
|
|
|
|
m_pixmap = new QPixmap(fileName);
|
|
|
|
|
if (m_pixmap->isNull()) {
|
|
|
|
|
if (errorString)
|
|
|
|
|
*errorString = tr("Failed to read image.");
|
|
|
|
|
delete m_pixmap;
|
2015-06-04 15:21:02 +02:00
|
|
|
return OpenResult::CannotHandle;
|
2015-05-29 13:23:52 +02:00
|
|
|
}
|
|
|
|
|
emit imageSizeChanged(m_pixmap->size());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setFilePath(Utils::FileName::fromString(fileName));
|
|
|
|
|
Utils::MimeDatabase mdb;
|
|
|
|
|
setMimeType(mdb.mimeTypeForFile(fileName).name());
|
2015-06-04 15:21:02 +02:00
|
|
|
return OpenResult::Success;
|
2015-05-29 13:23:52 +02:00
|
|
|
}
|
|
|
|
|
|
2012-03-08 08:42:29 +01:00
|
|
|
Core::IDocument::ReloadBehavior ImageViewerFile::reloadBehavior(ChangeTrigger state, ChangeType type) const
|
|
|
|
|
{
|
|
|
|
|
if (type == TypeRemoved || type == TypePermissions)
|
|
|
|
|
return BehaviorSilent;
|
|
|
|
|
if (type == TypeContents && state == TriggerInternal && !isModified())
|
|
|
|
|
return BehaviorSilent;
|
|
|
|
|
return BehaviorAsk;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-04 15:24:13 +02:00
|
|
|
bool ImageViewerFile::reload(QString *errorString,
|
2012-02-14 16:43:51 +01:00
|
|
|
Core::IDocument::ReloadFlag flag,
|
|
|
|
|
Core::IDocument::ChangeType type)
|
2010-06-18 11:02:48 +02:00
|
|
|
{
|
|
|
|
|
if (flag == FlagIgnore)
|
2011-04-04 15:24:13 +02:00
|
|
|
return true;
|
2010-06-18 11:02:48 +02:00
|
|
|
if (type == TypePermissions) {
|
|
|
|
|
emit changed();
|
2011-04-04 15:24:13 +02:00
|
|
|
return true;
|
2010-06-18 11:02:48 +02:00
|
|
|
}
|
2015-05-29 13:23:52 +02:00
|
|
|
emit aboutToReload();
|
2015-06-04 15:21:02 +02:00
|
|
|
bool success = (openImpl(errorString, filePath().toString()) == OpenResult::Success);
|
2015-05-29 13:23:52 +02:00
|
|
|
emit reloadFinished(success);
|
|
|
|
|
return success;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ImageViewerFile::isPaused() const
|
|
|
|
|
{
|
|
|
|
|
return m_isPaused;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ImageViewerFile::setPaused(bool paused)
|
|
|
|
|
{
|
|
|
|
|
if (!m_movie || m_isPaused == paused)
|
|
|
|
|
return;
|
|
|
|
|
m_isPaused = paused;
|
|
|
|
|
m_movie->setPaused(paused);
|
|
|
|
|
emit isPausedChanged(m_isPaused);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QGraphicsItem *ImageViewerFile::createGraphicsItem() const
|
|
|
|
|
{
|
|
|
|
|
QGraphicsItem *val = 0;
|
|
|
|
|
switch (m_type) {
|
|
|
|
|
case TypeInvalid:
|
|
|
|
|
break;
|
|
|
|
|
case TypeSvg:
|
|
|
|
|
#ifndef QT_NO_SVG
|
|
|
|
|
if (m_tempSvgItem) {
|
|
|
|
|
val = m_tempSvgItem;
|
|
|
|
|
m_tempSvgItem = 0;
|
|
|
|
|
} else {
|
|
|
|
|
val = new QGraphicsSvgItem(filePath().toString());
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
break;
|
|
|
|
|
case TypeMovie:
|
|
|
|
|
val = new MovieItem(m_movie);
|
|
|
|
|
break;
|
|
|
|
|
case TypePixmap: {
|
|
|
|
|
auto pixmapItem = new QGraphicsPixmapItem(*m_pixmap);
|
|
|
|
|
pixmapItem->setTransformationMode(Qt::SmoothTransformation);
|
|
|
|
|
val = pixmapItem;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImageViewerFile::ImageType ImageViewerFile::type() const
|
|
|
|
|
{
|
|
|
|
|
return m_type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ImageViewerFile::updateVisibility()
|
|
|
|
|
{
|
|
|
|
|
if (!m_movie || m_isPaused)
|
|
|
|
|
return;
|
|
|
|
|
bool visible = false;
|
|
|
|
|
foreach (Core::IEditor *editor, Core::DocumentModel::editorsForDocument(this)) {
|
|
|
|
|
if (editor->widget()->isVisible()) {
|
|
|
|
|
visible = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
m_movie->setPaused(!visible);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ImageViewerFile::cleanUp()
|
|
|
|
|
{
|
|
|
|
|
delete m_pixmap;
|
|
|
|
|
delete m_movie;
|
|
|
|
|
#ifndef QT_NO_SVG
|
|
|
|
|
delete m_tempSvgItem;
|
|
|
|
|
#endif
|
2010-06-18 11:02:48 +02:00
|
|
|
}
|
|
|
|
|
|
2011-05-10 20:43:03 +02:00
|
|
|
bool ImageViewerFile::save(QString *errorString, const QString &fileName, bool autoSave)
|
2010-06-18 11:02:48 +02:00
|
|
|
{
|
2011-03-30 13:45:16 +02:00
|
|
|
Q_UNUSED(errorString)
|
2010-06-18 11:02:48 +02:00
|
|
|
Q_UNUSED(fileName);
|
2011-05-10 20:43:03 +02:00
|
|
|
Q_UNUSED(autoSave)
|
2010-06-18 11:02:48 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-15 15:14:10 +02:00
|
|
|
bool ImageViewerFile::setContents(const QByteArray &contents)
|
|
|
|
|
{
|
|
|
|
|
Q_UNUSED(contents);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-18 11:02:48 +02:00
|
|
|
QString ImageViewerFile::defaultPath() const
|
|
|
|
|
{
|
|
|
|
|
return QString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString ImageViewerFile::suggestedFileName() const
|
|
|
|
|
{
|
|
|
|
|
return QString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ImageViewerFile::isModified() const
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ImageViewerFile::isSaveAsAllowed() const
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace Internal
|
|
|
|
|
} // namespace ImageViewer
|