mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 22:09:52 +08:00
251 lines
7.2 KiB
C++
251 lines
7.2 KiB
C++
#ifndef VIMAGEPREVIEWER_H
|
|
#define VIMAGEPREVIEWER_H
|
|
|
|
#include <QObject>
|
|
#include <QString>
|
|
#include <QTextBlock>
|
|
#include <QHash>
|
|
#include "hgmarkdownhighlighter.h"
|
|
|
|
class QTimer;
|
|
class VMdEdit;
|
|
class QTextDocument;
|
|
class VFile;
|
|
class VDownloader;
|
|
|
|
class VImagePreviewer : public QObject
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
explicit VImagePreviewer(VMdEdit *p_edit, const HGMarkdownHighlighter *p_highlighter);
|
|
|
|
// Whether @p_block is an image previewed block.
|
|
// The image previewed block is a block containing only the special character
|
|
// and whitespaces.
|
|
bool isImagePreviewBlock(const QTextBlock &p_block);
|
|
|
|
QImage fetchCachedImageByID(long long p_id);
|
|
|
|
// Update preview image width.
|
|
void updatePreviewImageWidth();
|
|
|
|
bool isPreviewing() const;
|
|
|
|
bool isEnabled() const;
|
|
|
|
public slots:
|
|
// Image links have changed.
|
|
void imageLinksChanged(const QVector<VElementRegion> &p_imageRegions);
|
|
|
|
private slots:
|
|
// Non-local image downloaded for preview.
|
|
void imageDownloaded(const QByteArray &p_data, const QString &p_url);
|
|
|
|
// Update preview image width right now.
|
|
void doUpdatePreviewImageWidth();
|
|
|
|
signals:
|
|
// Request highlighter to update image links.
|
|
void requestUpdateImageLinks();
|
|
|
|
// Emit after finishing previewing.
|
|
void previewFinished();
|
|
|
|
// Emit after updating preview width.
|
|
void previewWidthUpdated();
|
|
|
|
private:
|
|
struct ImageInfo
|
|
{
|
|
ImageInfo(const QString &p_name, int p_width)
|
|
: m_name(p_name), m_width(p_width)
|
|
{
|
|
}
|
|
|
|
QString m_name;
|
|
int m_width;
|
|
};
|
|
|
|
struct ImageLinkInfo
|
|
{
|
|
ImageLinkInfo()
|
|
: m_startPos(-1), m_endPos(-1),
|
|
m_isBlock(false), m_previewImageID(-1)
|
|
{
|
|
}
|
|
|
|
ImageLinkInfo(int p_startPos, int p_endPos)
|
|
: m_startPos(p_startPos), m_endPos(p_endPos),
|
|
m_isBlock(false), m_previewImageID(-1)
|
|
{
|
|
}
|
|
|
|
int m_startPos;
|
|
int m_endPos;
|
|
QString m_linkUrl;
|
|
|
|
// Whether it is a image block.
|
|
bool m_isBlock;
|
|
|
|
// The previewed image ID if this link has been previewed.
|
|
// -1 if this link has not yet been previewed.
|
|
long long m_previewImageID;
|
|
};
|
|
|
|
// Info about a previewed image.
|
|
struct PreviewImageInfo
|
|
{
|
|
PreviewImageInfo() : m_id(-1), m_timeStamp(-1)
|
|
{
|
|
}
|
|
|
|
PreviewImageInfo(long long p_id, long long p_timeStamp,
|
|
const QString p_path, bool p_isBlock)
|
|
: m_id(p_id), m_timeStamp(p_timeStamp),
|
|
m_path(p_path), m_isBlock(p_isBlock)
|
|
{
|
|
}
|
|
|
|
QString toString()
|
|
{
|
|
return QString("PreviewImageInfo(ID %0 path %1 stamp %2 isBlock %3")
|
|
.arg(m_id).arg(m_path).arg(m_timeStamp).arg(m_isBlock);
|
|
}
|
|
|
|
long long m_id;
|
|
long long m_timeStamp;
|
|
QString m_path;
|
|
bool m_isBlock;
|
|
};
|
|
|
|
// Status about the VMdEdit, used for restore.
|
|
struct EditStatus
|
|
{
|
|
EditStatus()
|
|
: m_modified(false)
|
|
{
|
|
}
|
|
|
|
bool m_modified;
|
|
};
|
|
|
|
// Kick off new preview of m_imageRegions.
|
|
void kickOffPreview(const QVector<VElementRegion> &p_imageRegions);
|
|
|
|
// Preview images according to m_timeStamp and m_imageRegions.
|
|
void previewImages();
|
|
|
|
// According to m_imageRegions, fetch the image link Url.
|
|
// Will check if this link has been previewed correctly and mark the previewed
|
|
// image with the newest timestamp.
|
|
// @p_imageLinks should be sorted in descending order of m_startPos.
|
|
void fetchImageLinksFromRegions(QVector<ImageLinkInfo> &p_imageLinks);
|
|
|
|
// Preview not previewed image links in @p_imageLinks.
|
|
// Insert the preview block with same indentation with the link block.
|
|
// @p_imageLinks should be sorted in descending order of m_startPos.
|
|
void previewImageLinks(QVector<ImageLinkInfo> &p_imageLinks, QTextCursor &p_cursor);
|
|
|
|
// Clear obsolete preview images whose timeStamp does not match current one
|
|
// or does not exist in the cache.
|
|
void clearObsoletePreviewImages(QTextCursor &p_cursor);
|
|
|
|
// Clear obsolete preview image in @p_block.
|
|
// A preview image is obsolete if it is not in the cache.
|
|
// If it is a preview block, delete the whole block.
|
|
// @p_block: a block may contain multiple preview images;
|
|
// @p_cursor: cursor used to manipulate the text;
|
|
bool clearObsoletePreviewImagesOfBlock(QTextBlock &p_block, QTextCursor &p_cursor);
|
|
|
|
// Update the width of preview image in @p_block.
|
|
bool updatePreviewImageWidthOfBlock(const QTextBlock &p_block, QTextCursor &p_cursor);
|
|
|
|
// Check if there is a correct previewed image following the @p_info link.
|
|
// Returns the previewImageID if yes. Otherwise, returns -1.
|
|
long long isImageLinkPreviewed(const ImageLinkInfo &p_info);
|
|
|
|
// Fetch the image link's URL if there is only one link.
|
|
QString fetchImageUrlToPreview(const QString &p_text);
|
|
|
|
// Fetch teh image's full path if there is only one image link.
|
|
QString fetchImagePathToPreview(const QString &p_text);
|
|
|
|
// Clear all the previewed images.
|
|
void clearAllPreviewImages();
|
|
|
|
// Fetch the text image format from an image preview block.
|
|
QTextImageFormat fetchFormatFromPreviewBlock(const QTextBlock &p_block) const;
|
|
|
|
// Whether the preview image is Image source.
|
|
bool isImageSourcePreviewImage(const QTextImageFormat &p_format) const;
|
|
|
|
void initImageFormat(QTextImageFormat &p_imgFormat,
|
|
const QString &p_imageName,
|
|
const PreviewImageInfo &p_info) const;
|
|
|
|
// Look up m_imageCache to get the resource name in QTextDocument's cache.
|
|
// If there is none, insert it.
|
|
QString imageCacheResourceName(const QString &p_imagePath);
|
|
|
|
QString imagePathToCacheResourceName(const QString &p_imagePath);
|
|
|
|
// Return true if and only if there is update.
|
|
bool updateImageWidth(QTextImageFormat &p_format);
|
|
|
|
// Clean up image cache.
|
|
void shrinkImageCache();
|
|
|
|
void saveEditStatus(EditStatus &p_status) const;
|
|
void restoreEditStatus(const EditStatus &p_status);
|
|
|
|
VMdEdit *m_edit;
|
|
QTextDocument *m_document;
|
|
VFile *m_file;
|
|
|
|
const HGMarkdownHighlighter *m_highlighter;
|
|
|
|
// Map from image full path to QUrl identifier in the QTextDocument's cache.
|
|
QHash<QString, ImageInfo> m_imageCache;
|
|
|
|
VDownloader *m_downloader;
|
|
|
|
// The preview width.
|
|
int m_imageWidth;
|
|
|
|
// Used to denote the obsolete previewed images.
|
|
// Increased when a new preview is kicked off.
|
|
long long m_timeStamp;
|
|
|
|
// Incremental ID for previewed images.
|
|
long long m_previewIndex;
|
|
|
|
// Map from previewImageID to PreviewImageInfo.
|
|
QHash<long long, PreviewImageInfo> m_previewImages;
|
|
|
|
// Regions of all the image links.
|
|
QVector<VElementRegion> m_imageRegions;
|
|
|
|
// Timer for updatePreviewImageWidth().
|
|
QTimer *m_updateTimer;
|
|
|
|
// Whether preview is enabled.
|
|
bool m_previewEnabled;
|
|
|
|
// Whether preview is ongoing.
|
|
bool m_isPreviewing;
|
|
|
|
static const int c_minImageWidth;
|
|
};
|
|
|
|
inline bool VImagePreviewer::isPreviewing() const
|
|
{
|
|
return m_isPreviewing;
|
|
}
|
|
|
|
inline bool VImagePreviewer::isEnabled() const
|
|
{
|
|
return m_previewEnabled;
|
|
}
|
|
|
|
#endif // VIMAGEPREVIEWER_H
|