forked from qt-creator/qt-creator
QmlDesigner: Add font asset preview tooltip
Refactored item library component preview tooltip to be also suitable for asset previews. Also now using the same image cache for font asset icons. Fixes: QDS-3254 Fixes: QDS-3470 Change-Id: I34c1278be2e5697e01eaedabe2798104507a6ad8 Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io> Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io> Reviewed-by: Marco Bubke <marco.bubke@qt.io> Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -44,10 +44,10 @@ QImage renderImage(ServerNodeInstance rootNodeInstance)
|
|||||||
|
|
||||||
QSize previewImageSize = rootNodeInstance.boundingRect().size().toSize();
|
QSize previewImageSize = rootNodeInstance.boundingRect().size().toSize();
|
||||||
if (previewImageSize.isEmpty())
|
if (previewImageSize.isEmpty())
|
||||||
previewImageSize = {640, 480};
|
previewImageSize = {300, 300};
|
||||||
|
|
||||||
if (previewImageSize.width() > 800 || previewImageSize.height() > 800)
|
if (previewImageSize.width() > 300 || previewImageSize.height() > 300)
|
||||||
previewImageSize.scale({800, 800}, Qt::KeepAspectRatio);
|
previewImageSize.scale({300, 300}, Qt::KeepAspectRatio);
|
||||||
|
|
||||||
QImage previewImage = rootNodeInstance.renderPreviewImage(previewImageSize);
|
QImage previewImage = rootNodeInstance.renderPreviewImage(previewImageSize);
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ MouseArea {
|
|||||||
onExited: tooltipBackend.hideTooltip()
|
onExited: tooltipBackend.hideTooltip()
|
||||||
onCanceled: tooltipBackend.hideTooltip()
|
onCanceled: tooltipBackend.hideTooltip()
|
||||||
onClicked: forceActiveFocus()
|
onClicked: forceActiveFocus()
|
||||||
|
onPositionChanged: tooltipBackend.reposition()
|
||||||
|
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
|
|
||||||
@@ -40,8 +41,8 @@ MouseArea {
|
|||||||
interval: 1000
|
interval: 1000
|
||||||
running: mouseArea.containsMouse
|
running: mouseArea.containsMouse
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
tooltipBackend.componentName = itemName
|
tooltipBackend.name = itemName
|
||||||
tooltipBackend.componentPath = componentPath
|
tooltipBackend.path = componentPath
|
||||||
tooltipBackend.showTooltip()
|
tooltipBackend.showTooltip()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -599,6 +599,8 @@ extend_qtc_plugin(QmlDesigner
|
|||||||
|
|
||||||
imagecache/imagecachecollector.h
|
imagecache/imagecachecollector.h
|
||||||
imagecache/imagecachecollector.cpp
|
imagecache/imagecachecollector.cpp
|
||||||
|
imagecache/imagecachefontcollector.h
|
||||||
|
imagecache/imagecachefontcollector.cpp
|
||||||
imagecache/imagecache.cpp
|
imagecache/imagecache.cpp
|
||||||
imagecache/imagecachecollectorinterface.h
|
imagecache/imagecachecollectorinterface.h
|
||||||
imagecache/imagecacheconnectionmanager.cpp
|
imagecache/imagecacheconnectionmanager.cpp
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include "customfilesystemmodel.h"
|
#include "customfilesystemmodel.h"
|
||||||
|
|
||||||
#include <theme.h>
|
#include <theme.h>
|
||||||
|
#include <imagecache.h>
|
||||||
|
|
||||||
#include <utils/filesystemwatcher.h>
|
#include <utils/filesystemwatcher.h>
|
||||||
|
|
||||||
@@ -37,8 +38,10 @@
|
|||||||
#include <QImageReader>
|
#include <QImageReader>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QRawFont>
|
#include <QRawFont>
|
||||||
#include <QGlyphRun>
|
#include <QPair>
|
||||||
#include <qmath.h>
|
#include <qmath.h>
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
@@ -84,68 +87,6 @@ static QPixmap defaultPixmapForType(const QString &type, const QSize &size)
|
|||||||
return QPixmap(QStringLiteral(":/ItemLibrary/images/asset_%1_%2.png").arg(type).arg(size.width()));
|
return QPixmap(QStringLiteral(":/ItemLibrary/images/asset_%1_%2.png").arg(type).arg(size.width()));
|
||||||
}
|
}
|
||||||
|
|
||||||
static QPixmap generateFontImage(const QFileInfo &info, const QSize &size)
|
|
||||||
{
|
|
||||||
static QHash<QString, QPixmap> fontImageCache;
|
|
||||||
const QString file = info.absoluteFilePath();
|
|
||||||
const QString key = QStringLiteral("%1@%2@%3").arg(file).arg(size.width()).arg(size.height());
|
|
||||||
if (!fontImageCache.contains(key)) {
|
|
||||||
QPixmap pixmap(size);
|
|
||||||
pixmap.fill(Qt::transparent);
|
|
||||||
qreal pixelSize = size.width() / 2.;
|
|
||||||
bool done = false;
|
|
||||||
while (!done) {
|
|
||||||
QRawFont font(file, pixelSize);
|
|
||||||
if (!font.isValid())
|
|
||||||
break;
|
|
||||||
QGlyphRun gr;
|
|
||||||
gr.setRawFont(font);
|
|
||||||
QVector<quint32> indices = font.glyphIndexesForString("Abc");
|
|
||||||
if (indices.isEmpty())
|
|
||||||
break;
|
|
||||||
const QVector<QPointF> advances = font.advancesForGlyphIndexes(indices);
|
|
||||||
QVector<QPointF> positions;
|
|
||||||
QPointF totalAdvance;
|
|
||||||
for (const QPointF &advance : advances) {
|
|
||||||
positions.append(totalAdvance);
|
|
||||||
totalAdvance += advance;
|
|
||||||
}
|
|
||||||
|
|
||||||
gr.setGlyphIndexes(indices);
|
|
||||||
gr.setPositions(positions);
|
|
||||||
QRectF bounds = gr.boundingRect();
|
|
||||||
if (bounds.width() <= 0 || bounds.height() <= 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
bounds.moveCenter({size.width() / 2., size.height() / 2.});
|
|
||||||
|
|
||||||
// Bounding rectangle doesn't necessarily contain the entirety of glyphs for some
|
|
||||||
// reason, so also check totalAdvance for overflow.
|
|
||||||
qreal limitX = qMax(bounds.width(), totalAdvance.x());
|
|
||||||
if (size.width() < limitX) {
|
|
||||||
pixelSize = qreal(qFloor(pixelSize * size.width() / limitX));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
qreal limitY = qMax(bounds.height(), totalAdvance.y());
|
|
||||||
if (size.height() < limitY) {
|
|
||||||
pixelSize = qreal(qFloor(pixelSize * size.height() / limitY));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
QPainter painter(&pixmap);
|
|
||||||
painter.setPen(Theme::getColor(Theme::DStextColor));
|
|
||||||
painter.drawGlyphRun(bounds.bottomLeft(), gr);
|
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!done)
|
|
||||||
pixmap = defaultPixmapForType("font", size);
|
|
||||||
|
|
||||||
fontImageCache[key] = pixmap;
|
|
||||||
}
|
|
||||||
return fontImageCache[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
QString fontFamily(const QFileInfo &info)
|
QString fontFamily(const QFileInfo &info)
|
||||||
{
|
{
|
||||||
QRawFont font(info.absoluteFilePath(), 10);
|
QRawFont font(info.absoluteFilePath(), 10);
|
||||||
@@ -157,21 +98,27 @@ QString fontFamily(const QFileInfo &info)
|
|||||||
class ItemLibraryFileIconProvider : public QFileIconProvider
|
class ItemLibraryFileIconProvider : public QFileIconProvider
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ItemLibraryFileIconProvider() = default;
|
ItemLibraryFileIconProvider(ImageCache &fontImageCache)
|
||||||
|
: QFileIconProvider()
|
||||||
|
, m_fontImageCache(fontImageCache)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
QIcon icon( const QFileInfo & info ) const override
|
QIcon icon( const QFileInfo & info ) const override
|
||||||
{
|
{
|
||||||
QIcon icon;
|
QIcon icon;
|
||||||
const QString suffix = info.suffix();
|
const QString suffix = info.suffix();
|
||||||
|
const QString filePath = info.absoluteFilePath();
|
||||||
|
|
||||||
|
if (supportedFontSuffixes().contains(suffix))
|
||||||
|
return generateFontIcons(filePath);
|
||||||
|
|
||||||
for (auto iconSize : iconSizes) {
|
for (auto iconSize : iconSizes) {
|
||||||
// Provide icon depending on suffix
|
// Provide icon depending on suffix
|
||||||
QPixmap pixmap;
|
QPixmap pixmap;
|
||||||
|
|
||||||
if (supportedImageSuffixes().contains(suffix))
|
if (supportedImageSuffixes().contains(suffix))
|
||||||
pixmap.load(info.absoluteFilePath());
|
pixmap.load(filePath);
|
||||||
else if (supportedFontSuffixes().contains(suffix))
|
|
||||||
pixmap = generateFontImage(info, iconSize);
|
|
||||||
else if (supportedAudioSuffixes().contains(suffix))
|
else if (supportedAudioSuffixes().contains(suffix))
|
||||||
pixmap = defaultPixmapForType("sound", iconSize);
|
pixmap = defaultPixmapForType("sound", iconSize);
|
||||||
else if (supportedShaderSuffixes().contains(suffix))
|
else if (supportedShaderSuffixes().contains(suffix))
|
||||||
@@ -189,6 +136,61 @@ public:
|
|||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QIcon generateFontIcons(const QString &filePath) const
|
||||||
|
{
|
||||||
|
QIcon icon;
|
||||||
|
QString colorName = Theme::getColor(Theme::DStextColor).name();
|
||||||
|
std::condition_variable condition;
|
||||||
|
int count = iconSizes.size();
|
||||||
|
std::mutex mutex;
|
||||||
|
QList<QPair<QSize, QImage>> images;
|
||||||
|
|
||||||
|
for (auto iconSize : iconSizes) {
|
||||||
|
m_fontImageCache.requestImage(
|
||||||
|
filePath,
|
||||||
|
[&images, &condition, &count, &mutex, iconSize](const QImage &image) {
|
||||||
|
int currentCount;
|
||||||
|
{
|
||||||
|
std::unique_lock lock{mutex};
|
||||||
|
currentCount = --count;
|
||||||
|
images.append({iconSize, image});
|
||||||
|
}
|
||||||
|
if (currentCount <= 0)
|
||||||
|
condition.notify_all();
|
||||||
|
},
|
||||||
|
[&images, &condition, &count, &mutex, iconSize] {
|
||||||
|
int currentCount;
|
||||||
|
{
|
||||||
|
std::unique_lock lock{mutex};
|
||||||
|
currentCount = --count;
|
||||||
|
images.append({iconSize, {}});
|
||||||
|
}
|
||||||
|
if (currentCount <= 0)
|
||||||
|
condition.notify_all();
|
||||||
|
},
|
||||||
|
QStringLiteral("%1@%2@Abc").arg(QString::number(iconSize.width()),
|
||||||
|
colorName)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Block main thread until icons are generated, as it has to be done synchronously
|
||||||
|
std::unique_lock lock{mutex};
|
||||||
|
if (count > 0)
|
||||||
|
condition.wait(lock, [&]{ return count <= 0; });
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &pair : qAsConst(images)) {
|
||||||
|
QImage image = pair.second;
|
||||||
|
if (image.isNull())
|
||||||
|
icon.addPixmap(defaultPixmapForType("font", pair.first));
|
||||||
|
else
|
||||||
|
icon.addPixmap(QPixmap::fromImage(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
// Generated icon sizes should contain all ItemLibraryResourceView needed icon sizes, and their
|
// Generated icon sizes should contain all ItemLibraryResourceView needed icon sizes, and their
|
||||||
// x2 versions for HDPI sceens
|
// x2 versions for HDPI sceens
|
||||||
QList<QSize> iconSizes = {{384, 384}, {192, 192}, // Large
|
QList<QSize> iconSizes = {{384, 384}, {192, 192}, // Large
|
||||||
@@ -197,13 +199,15 @@ public:
|
|||||||
{48, 48}, // Small
|
{48, 48}, // Small
|
||||||
{64, 64}, {32, 32}}; // List
|
{64, 64}, {32, 32}}; // List
|
||||||
|
|
||||||
|
ImageCache &m_fontImageCache;
|
||||||
};
|
};
|
||||||
|
|
||||||
CustomFileSystemModel::CustomFileSystemModel(QObject *parent) : QAbstractListModel(parent)
|
CustomFileSystemModel::CustomFileSystemModel(ImageCache &fontImageCache, QObject *parent)
|
||||||
|
: QAbstractListModel(parent)
|
||||||
, m_fileSystemModel(new QFileSystemModel(this))
|
, m_fileSystemModel(new QFileSystemModel(this))
|
||||||
, m_fileSystemWatcher(new Utils::FileSystemWatcher(this))
|
, m_fileSystemWatcher(new Utils::FileSystemWatcher(this))
|
||||||
{
|
{
|
||||||
m_fileSystemModel->setIconProvider(new ItemLibraryFileIconProvider());
|
m_fileSystemModel->setIconProvider(new ItemLibraryFileIconProvider(fontImageCache));
|
||||||
|
|
||||||
connect(m_fileSystemWatcher, &Utils::FileSystemWatcher::directoryChanged, [this] {
|
connect(m_fileSystemWatcher, &Utils::FileSystemWatcher::directoryChanged, [this] {
|
||||||
updatePath(m_fileSystemModel->rootPath());
|
updatePath(m_fileSystemModel->rootPath());
|
||||||
@@ -345,6 +349,20 @@ const QSet<QString> &CustomFileSystemModel::supportedSuffixes() const
|
|||||||
return allSuffixes;
|
return allSuffixes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QSet<QString> &CustomFileSystemModel::previewableSuffixes() const
|
||||||
|
{
|
||||||
|
static QSet<QString> previewableSuffixes;
|
||||||
|
if (previewableSuffixes.isEmpty()) {
|
||||||
|
auto insertSuffixes = [](const QStringList &suffixes) {
|
||||||
|
for (const auto &suffix : suffixes)
|
||||||
|
previewableSuffixes.insert(suffix);
|
||||||
|
};
|
||||||
|
insertSuffixes(supportedFontSuffixes());
|
||||||
|
}
|
||||||
|
return previewableSuffixes;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void CustomFileSystemModel::appendIfNotFiltered(const QString &file)
|
void CustomFileSystemModel::appendIfNotFiltered(const QString &file)
|
||||||
{
|
{
|
||||||
if (filterMetaIcons(file))
|
if (filterMetaIcons(file))
|
||||||
|
|||||||
@@ -39,11 +39,13 @@ namespace Utils { class FileSystemWatcher; }
|
|||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class ImageCache;
|
||||||
|
|
||||||
class CustomFileSystemModel : public QAbstractListModel
|
class CustomFileSystemModel : public QAbstractListModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
CustomFileSystemModel(QObject *parent = nullptr);
|
CustomFileSystemModel(ImageCache &fontImageCache, QObject *parent = nullptr);
|
||||||
|
|
||||||
void setFilter(QDir::Filters filters);
|
void setFilter(QDir::Filters filters);
|
||||||
QString rootPath() const;
|
QString rootPath() const;
|
||||||
@@ -64,6 +66,7 @@ public:
|
|||||||
|
|
||||||
QPair<QString, QByteArray> resourceTypeAndData(const QModelIndex &index) const;
|
QPair<QString, QByteArray> resourceTypeAndData(const QModelIndex &index) const;
|
||||||
const QSet<QString> &supportedSuffixes() const;
|
const QSet<QString> &supportedSuffixes() const;
|
||||||
|
const QSet<QString> &previewableSuffixes() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QModelIndex updatePath(const QString &newPath);
|
QModelIndex updatePath(const QString &newPath);
|
||||||
|
|||||||
@@ -27,6 +27,10 @@
|
|||||||
|
|
||||||
#include "customfilesystemmodel.h"
|
#include "customfilesystemmodel.h"
|
||||||
|
|
||||||
|
#include <theme.h>
|
||||||
|
#include <imagecache.h>
|
||||||
|
#include <previewtooltip/previewtooltipbackend.h>
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QActionGroup>
|
#include <QActionGroup>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
@@ -35,6 +39,7 @@
|
|||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
|
#include <QtGui/qevent.h>
|
||||||
|
|
||||||
#include <QProxyStyle>
|
#include <QProxyStyle>
|
||||||
|
|
||||||
@@ -58,7 +63,7 @@ void ItemLibraryResourceView::addSizeAction(QActionGroup *group, const QString &
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemLibraryResourceView::ItemLibraryResourceView(QWidget *parent) :
|
ItemLibraryResourceView::ItemLibraryResourceView(ImageCache &fontImageCache, QWidget *parent) :
|
||||||
QListView(parent)
|
QListView(parent)
|
||||||
{
|
{
|
||||||
setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||||
@@ -102,6 +107,20 @@ ItemLibraryResourceView::ItemLibraryResourceView(QWidget *parent) :
|
|||||||
defaultAction->toggle();
|
defaultAction->toggle();
|
||||||
|
|
||||||
addActions(actionGroup->actions());
|
addActions(actionGroup->actions());
|
||||||
|
|
||||||
|
viewport()->setAttribute(Qt::WA_Hover);
|
||||||
|
m_fontPreviewTooltipBackend = std::make_unique<PreviewTooltipBackend>(fontImageCache);
|
||||||
|
// Note: Though the text specified here appears in UI, it shouldn't be translated, as it's
|
||||||
|
// a commonly used sentence to preview the font glyphs in latin fonts.
|
||||||
|
// For fonts that do not have latin glyphs, the font family name will have to
|
||||||
|
// suffice for preview. Font family name is inserted into %1 at render time.
|
||||||
|
m_fontPreviewTooltipBackend->setState(QStringLiteral("%1@%2@%3")
|
||||||
|
.arg(QString::number(300),
|
||||||
|
Theme::getColor(Theme::DStextColor).name(),
|
||||||
|
QStringLiteral("%1\n\n"
|
||||||
|
"The quick brown fox jumps\n"
|
||||||
|
"over the lazy dog\n"
|
||||||
|
"1234567890")));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemLibraryResourceView::startDrag(Qt::DropActions /* supportedActions */)
|
void ItemLibraryResourceView::startDrag(Qt::DropActions /* supportedActions */)
|
||||||
@@ -136,5 +155,51 @@ void ItemLibraryResourceView::startDrag(Qt::DropActions /* supportedActions */)
|
|||||||
drag->exec();
|
drag->exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ItemLibraryResourceView::viewportEvent(QEvent *event)
|
||||||
|
{
|
||||||
|
if (event->type() == QEvent::ToolTip) {
|
||||||
|
auto fileSystemModel = qobject_cast<CustomFileSystemModel *>(model());
|
||||||
|
Q_ASSERT(fileSystemModel);
|
||||||
|
QHelpEvent *helpEvent = static_cast<QHelpEvent *>(event);
|
||||||
|
QModelIndex index = indexAt(helpEvent->pos());
|
||||||
|
if (index.isValid()) {
|
||||||
|
QFileInfo fi = fileSystemModel->fileInfo(index);
|
||||||
|
if (fileSystemModel->previewableSuffixes().contains(fi.suffix())) {
|
||||||
|
QString filePath = fi.absoluteFilePath();
|
||||||
|
if (!filePath.isEmpty()) {
|
||||||
|
if (!m_fontPreviewTooltipBackend->isVisible()
|
||||||
|
|| m_fontPreviewTooltipBackend->path() != filePath) {
|
||||||
|
m_fontPreviewTooltipBackend->setPath(filePath);
|
||||||
|
m_fontPreviewTooltipBackend->setName(fi.fileName());
|
||||||
|
m_fontPreviewTooltipBackend->showTooltip();
|
||||||
|
} else {
|
||||||
|
m_fontPreviewTooltipBackend->reposition();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_fontPreviewTooltipBackend->hideTooltip();
|
||||||
|
} else if (event->type() == QEvent::Leave) {
|
||||||
|
m_fontPreviewTooltipBackend->hideTooltip();
|
||||||
|
} else if (event->type() == QEvent::HoverMove) {
|
||||||
|
if (m_fontPreviewTooltipBackend->isVisible()) {
|
||||||
|
auto fileSystemModel = qobject_cast<CustomFileSystemModel *>(model());
|
||||||
|
Q_ASSERT(fileSystemModel);
|
||||||
|
auto *he = static_cast<QHoverEvent *>(event);
|
||||||
|
QModelIndex index = indexAt(he->pos());
|
||||||
|
if (index.isValid()) {
|
||||||
|
QFileInfo fi = fileSystemModel->fileInfo(index);
|
||||||
|
if (fi.absoluteFilePath() != m_fontPreviewTooltipBackend->path())
|
||||||
|
m_fontPreviewTooltipBackend->hideTooltip();
|
||||||
|
else
|
||||||
|
m_fontPreviewTooltipBackend->reposition();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return QListView::viewportEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
|
||||||
|
|||||||
@@ -33,15 +33,22 @@ QT_END_NAMESPACE
|
|||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class PreviewTooltipBackend;
|
||||||
|
class ImageCache;
|
||||||
|
|
||||||
class ItemLibraryResourceView : public QListView {
|
class ItemLibraryResourceView : public QListView {
|
||||||
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit ItemLibraryResourceView(QWidget *parent = nullptr);
|
explicit ItemLibraryResourceView(ImageCache &fontImageCache, QWidget *parent = nullptr);
|
||||||
|
|
||||||
void startDrag(Qt::DropActions supportedActions) override;
|
void startDrag(Qt::DropActions supportedActions) override;
|
||||||
|
bool viewportEvent(QEvent *event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void addSizeAction(QActionGroup *group, const QString &text, int size, int iconSize);
|
void addSizeAction(QActionGroup *group, const QString &text, int size, int iconSize);
|
||||||
|
|
||||||
|
std::unique_ptr<PreviewTooltipBackend> m_fontPreviewTooltipBackend;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <imagecache.h>
|
#include <imagecache.h>
|
||||||
#include <imagecache/imagecachecollector.h>
|
#include <imagecache/imagecachecollector.h>
|
||||||
|
#include <imagecache/imagecachefontcollector.h>
|
||||||
#include <imagecache/imagecacheconnectionmanager.h>
|
#include <imagecache/imagecacheconnectionmanager.h>
|
||||||
#include <imagecache/imagecachegenerator.h>
|
#include <imagecache/imagecachegenerator.h>
|
||||||
#include <imagecache/imagecachestorage.h>
|
#include <imagecache/imagecachestorage.h>
|
||||||
@@ -55,9 +56,12 @@ public:
|
|||||||
ImageCacheStorage<Sqlite::Database> storage{database};
|
ImageCacheStorage<Sqlite::Database> storage{database};
|
||||||
ImageCacheConnectionManager connectionManager;
|
ImageCacheConnectionManager connectionManager;
|
||||||
ImageCacheCollector collector{connectionManager};
|
ImageCacheCollector collector{connectionManager};
|
||||||
|
ImageCacheFontCollector fontCollector;
|
||||||
ImageCacheGenerator generator{collector, storage};
|
ImageCacheGenerator generator{collector, storage};
|
||||||
|
ImageCacheGenerator fontGenerator{fontCollector, storage};
|
||||||
TimeStampProvider timeStampProvider;
|
TimeStampProvider timeStampProvider;
|
||||||
ImageCache cache{storage, generator, timeStampProvider};
|
ImageCache cache{storage, generator, timeStampProvider};
|
||||||
|
ImageCache fontImageCache{storage, fontGenerator, timeStampProvider};
|
||||||
};
|
};
|
||||||
|
|
||||||
ItemLibraryView::ItemLibraryView(QObject* parent)
|
ItemLibraryView::ItemLibraryView(QObject* parent)
|
||||||
@@ -78,7 +82,7 @@ bool ItemLibraryView::hasWidget() const
|
|||||||
WidgetInfo ItemLibraryView::widgetInfo()
|
WidgetInfo ItemLibraryView::widgetInfo()
|
||||||
{
|
{
|
||||||
if (m_widget.isNull()) {
|
if (m_widget.isNull()) {
|
||||||
m_widget = new ItemLibraryWidget{m_imageCacheData->cache};
|
m_widget = new ItemLibraryWidget{m_imageCacheData->cache, m_imageCacheData->fontImageCache};
|
||||||
m_widget->setImportsWidget(m_importManagerView->widgetInfo().widget);
|
m_widget->setImportsWidget(m_importManagerView->widgetInfo().widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +159,7 @@ void ItemLibraryView::importsChanged(const QList<Import> &addedImports, const QL
|
|||||||
void ItemLibraryView::setResourcePath(const QString &resourcePath)
|
void ItemLibraryView::setResourcePath(const QString &resourcePath)
|
||||||
{
|
{
|
||||||
if (m_widget.isNull())
|
if (m_widget.isNull())
|
||||||
m_widget = new ItemLibraryWidget{m_imageCacheData->cache};
|
m_widget = new ItemLibraryWidget{m_imageCacheData->cache, m_imageCacheData->fontImageCache};
|
||||||
|
|
||||||
m_widget->setResourcePath(resourcePath);
|
m_widget->setResourcePath(resourcePath);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,10 +83,10 @@ static QString propertyEditorResourcesPath() {
|
|||||||
return Core::ICore::resourcePath() + QStringLiteral("/qmldesigner/propertyEditorQmlSources");
|
return Core::ICore::resourcePath() + QStringLiteral("/qmldesigner/propertyEditorQmlSources");
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemLibraryWidget::ItemLibraryWidget(ImageCache &imageCache)
|
ItemLibraryWidget::ItemLibraryWidget(ImageCache &imageCache, ImageCache &fontImageCache)
|
||||||
: m_itemIconSize(24, 24)
|
: m_itemIconSize(24, 24)
|
||||||
, m_itemViewQuickWidget(new QQuickWidget(this))
|
, m_itemViewQuickWidget(new QQuickWidget(this))
|
||||||
, m_resourcesView(new ItemLibraryResourceView(this))
|
, m_resourcesView(new ItemLibraryResourceView(fontImageCache, this))
|
||||||
, m_importTagsWidget(new QWidget(this))
|
, m_importTagsWidget(new QWidget(this))
|
||||||
, m_addResourcesWidget(new QWidget(this))
|
, m_addResourcesWidget(new QWidget(this))
|
||||||
, m_imageCache{imageCache}
|
, m_imageCache{imageCache}
|
||||||
@@ -115,12 +115,11 @@ ItemLibraryWidget::ItemLibraryWidget(ImageCache &imageCache)
|
|||||||
m_previewTooltipBackend = std::make_unique<PreviewTooltipBackend>(m_imageCache);
|
m_previewTooltipBackend = std::make_unique<PreviewTooltipBackend>(m_imageCache);
|
||||||
m_itemViewQuickWidget->rootContext()->setContextProperty("tooltipBackend",
|
m_itemViewQuickWidget->rootContext()->setContextProperty("tooltipBackend",
|
||||||
m_previewTooltipBackend.get());
|
m_previewTooltipBackend.get());
|
||||||
|
|
||||||
m_itemViewQuickWidget->setClearColor(
|
m_itemViewQuickWidget->setClearColor(
|
||||||
Theme::getColor(Theme::Color::QmlDesigner_BackgroundColorDarkAlternate));
|
Theme::getColor(Theme::Color::QmlDesigner_BackgroundColorDarkAlternate));
|
||||||
|
|
||||||
/* create Resources view and its model */
|
/* create Resources view and its model */
|
||||||
m_resourcesFileSystemModel = new CustomFileSystemModel(this);
|
m_resourcesFileSystemModel = new CustomFileSystemModel(fontImageCache, this);
|
||||||
m_resourcesView->setModel(m_resourcesFileSystemModel.data());
|
m_resourcesView->setModel(m_resourcesFileSystemModel.data());
|
||||||
|
|
||||||
/* create image provider for loading item icons */
|
/* create image provider for loading item icons */
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ class ItemLibraryWidget : public QFrame
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ItemLibraryWidget(ImageCache &imageCache);
|
ItemLibraryWidget(ImageCache &imageCache, ImageCache &fontImageCache);
|
||||||
~ItemLibraryWidget();
|
~ItemLibraryWidget();
|
||||||
|
|
||||||
void setItemLibraryInfo(ItemLibraryInfo *itemLibraryInfo);
|
void setItemLibraryInfo(ItemLibraryInfo *itemLibraryInfo);
|
||||||
|
|||||||
@@ -36,28 +36,36 @@ PreviewImageTooltip::PreviewImageTooltip(QWidget *parent)
|
|||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, m_ui(std::make_unique<Ui::PreviewImageTooltip>())
|
, m_ui(std::make_unique<Ui::PreviewImageTooltip>())
|
||||||
{
|
{
|
||||||
// setAttribute(Qt::WA_TransparentForMouseEvents);
|
setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowTransparentForInput
|
||||||
setWindowFlags(Qt::ToolTip);
|
| Qt::WindowStaysOnTopHint | Qt::WindowDoesNotAcceptFocus);
|
||||||
m_ui->setupUi(this);
|
m_ui->setupUi(this);
|
||||||
|
m_ui->nameLabel->setElideMode(Qt::ElideLeft);
|
||||||
|
m_ui->pathLabel->setElideMode(Qt::ElideLeft);
|
||||||
|
m_ui->infoLabel->setElideMode(Qt::ElideLeft);
|
||||||
setStyleSheet(QString("QWidget { background-color: %1 }").arg(Utils::creatorTheme()->color(Utils::Theme::BackgroundColorNormal).name()));
|
setStyleSheet(QString("QWidget { background-color: %1 }").arg(Utils::creatorTheme()->color(Utils::Theme::BackgroundColorNormal).name()));
|
||||||
}
|
}
|
||||||
|
|
||||||
PreviewImageTooltip::~PreviewImageTooltip() = default;
|
PreviewImageTooltip::~PreviewImageTooltip() = default;
|
||||||
|
|
||||||
void PreviewImageTooltip::setComponentPath(const QString &path)
|
void PreviewImageTooltip::setName(const QString &name)
|
||||||
{
|
{
|
||||||
m_ui->componentPathLabel->setText(path);
|
m_ui->nameLabel->setText(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewImageTooltip::setComponentName(const QString &name)
|
void PreviewImageTooltip::setPath(const QString &path)
|
||||||
{
|
{
|
||||||
m_ui->componentNameLabel->setText(name);
|
m_ui->pathLabel->setText(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PreviewImageTooltip::setInfo(const QString &info)
|
||||||
|
{
|
||||||
|
m_ui->infoLabel->setText(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewImageTooltip::setImage(const QImage &image)
|
void PreviewImageTooltip::setImage(const QImage &image)
|
||||||
{
|
{
|
||||||
resize(image.width() + 20 + m_ui->componentNameLabel->width(),
|
m_ui->imageLabel->setPixmap(QPixmap::fromImage({image}).scaled(m_ui->imageLabel->width(),
|
||||||
std::max(image.height() + 20, height()));
|
m_ui->imageLabel->height(),
|
||||||
m_ui->imageLabel->setPixmap(QPixmap::fromImage({image}));
|
Qt::KeepAspectRatio));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,8 +43,9 @@ public:
|
|||||||
explicit PreviewImageTooltip(QWidget *parent = {});
|
explicit PreviewImageTooltip(QWidget *parent = {});
|
||||||
~PreviewImageTooltip();
|
~PreviewImageTooltip();
|
||||||
|
|
||||||
void setComponentPath(const QString &path);
|
void setName(const QString &name);
|
||||||
void setComponentName(const QString &name);
|
void setPath(const QString &path);
|
||||||
|
void setInfo(const QString &info);
|
||||||
void setImage(const QImage &pixmap);
|
void setImage(const QImage &pixmap);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -6,20 +6,20 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>400</width>
|
<width>651</width>
|
||||||
<height>300</height>
|
<height>318</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>200</width>
|
<width>300</width>
|
||||||
<height>200</height>
|
<height>140</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
@@ -64,37 +64,36 @@
|
|||||||
<property name="lineWidth">
|
<property name="lineWidth">
|
||||||
<number>1</number>
|
<number>1</number>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<item row="1" column="1">
|
<property name="spacing">
|
||||||
<widget class="QLabel" name="componentPathLabel">
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="imageLabel">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>1</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>0</width>
|
<width>300</width>
|
||||||
<height>0</height>
|
<height>300</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
|
||||||
<string notr="true"/>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignCenter</set>
|
|
||||||
</property>
|
|
||||||
<property name="wordWrap">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="textInteractionFlags">
|
|
||||||
<set>Qt::NoTextInteraction</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0" rowspan="2">
|
|
||||||
<widget class="QLabel" name="imageLabel">
|
|
||||||
<property name="frameShape">
|
<property name="frameShape">
|
||||||
<enum>QFrame::Box</enum>
|
<enum>QFrame::Box</enum>
|
||||||
</property>
|
</property>
|
||||||
@@ -102,12 +101,15 @@
|
|||||||
<enum>QFrame::Plain</enum>
|
<enum>QFrame::Plain</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
<set>Qt::AlignCenter</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item>
|
||||||
<widget class="Utils::ElidingLabel" name="componentNameLabel">
|
<widget class="QWidget" name="widget" native="true">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="Utils::ElidingLabel" name="nameLabel">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@@ -120,27 +122,70 @@
|
|||||||
<height>0</height>
|
<height>0</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<pointsize>12</pointsize>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string notr="true"/>
|
<string notr="true"><name label></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignCenter</set>
|
<set>Qt::AlignCenter</set>
|
||||||
</property>
|
</property>
|
||||||
<property name="wordWrap">
|
<property name="textInteractionFlags">
|
||||||
<bool>true</bool>
|
<set>Qt::NoTextInteraction</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Utils::ElidingLabel" name="pathLabel">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>1</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true"><path label></string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
</property>
|
</property>
|
||||||
<property name="textInteractionFlags">
|
<property name="textInteractionFlags">
|
||||||
<set>Qt::NoTextInteraction</set>
|
<set>Qt::NoTextInteraction</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Utils::ElidingLabel" name="infoLabel">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>1</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true"><info label></string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::NoTextInteraction</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QMetaObject>
|
#include <QMetaObject>
|
||||||
|
#include <QScreen>
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
@@ -46,28 +47,25 @@ PreviewTooltipBackend::~PreviewTooltipBackend()
|
|||||||
|
|
||||||
void PreviewTooltipBackend::showTooltip()
|
void PreviewTooltipBackend::showTooltip()
|
||||||
{
|
{
|
||||||
if (m_componentPath.isEmpty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_tooltip = std::make_unique<PreviewImageTooltip>();
|
m_tooltip = std::make_unique<PreviewImageTooltip>();
|
||||||
|
|
||||||
m_tooltip->setComponentName(m_componentName);
|
m_tooltip->setName(m_name);
|
||||||
m_tooltip->setComponentPath(m_componentPath);
|
m_tooltip->setPath(m_path);
|
||||||
|
m_tooltip->setInfo(m_info);
|
||||||
|
|
||||||
m_cache.requestImage(
|
m_cache.requestImage(
|
||||||
m_componentPath,
|
m_path,
|
||||||
[tooltip = QPointer<PreviewImageTooltip>(m_tooltip.get())](const QImage &image) {
|
[tooltip = QPointer<PreviewImageTooltip>(m_tooltip.get())](const QImage &image) {
|
||||||
QMetaObject::invokeMethod(tooltip, [tooltip, image] {
|
QMetaObject::invokeMethod(tooltip, [tooltip, image] {
|
||||||
if (tooltip)
|
if (tooltip)
|
||||||
tooltip->setImage(image);
|
tooltip->setImage(image);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[] {});
|
[] {},
|
||||||
|
m_state
|
||||||
|
);
|
||||||
|
|
||||||
auto mousePosition = QCursor::pos();
|
reposition();
|
||||||
|
|
||||||
mousePosition += {20, 20};
|
|
||||||
m_tooltip->move(mousePosition);
|
|
||||||
m_tooltip->show();
|
m_tooltip->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,30 +77,94 @@ void PreviewTooltipBackend::hideTooltip()
|
|||||||
m_tooltip.reset();
|
m_tooltip.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QmlDesigner::PreviewTooltipBackend::componentPath() const
|
bool PreviewTooltipBackend::isVisible() const
|
||||||
{
|
{
|
||||||
return m_componentPath;
|
if (m_tooltip)
|
||||||
|
return m_tooltip->isVisible();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlDesigner::PreviewTooltipBackend::setComponentPath(const QString &path)
|
void PreviewTooltipBackend::reposition()
|
||||||
{
|
{
|
||||||
m_componentPath = path;
|
if (m_tooltip) {
|
||||||
|
// By default tooltip is placed right and below the cursor, but if the screen
|
||||||
|
// doesn't have sufficient space in that direction, position is adjusted.
|
||||||
|
// It is assumed that some diagonal direction will have enough space.
|
||||||
|
const QPoint mousePos = QCursor::pos();
|
||||||
|
QScreen *screen = qApp->screenAt(mousePos);
|
||||||
|
QRect tipRect = m_tooltip->geometry();
|
||||||
|
QPoint offset(10, 5);
|
||||||
|
QPoint pos = mousePos + offset;
|
||||||
|
if (screen) {
|
||||||
|
QRect rect = screen->geometry();
|
||||||
|
tipRect.moveTo(pos);
|
||||||
|
if (!rect.contains(tipRect)) {
|
||||||
|
pos = mousePos + QPoint(-offset.x() - m_tooltip->size().width(),
|
||||||
|
offset.y());
|
||||||
|
tipRect.moveTo(pos);
|
||||||
|
if (!rect.contains(tipRect)) {
|
||||||
|
pos = mousePos + QPoint(offset.x(), -offset.y() - m_tooltip->size().height());
|
||||||
|
tipRect.moveTo(pos);
|
||||||
|
if (!rect.contains(tipRect)) {
|
||||||
|
pos = mousePos + QPoint(-offset.x() - m_tooltip->size().width(),
|
||||||
|
-offset.y() - m_tooltip->size().height());
|
||||||
|
tipRect.moveTo(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (m_componentPath != path)
|
m_tooltip->move(pos);
|
||||||
emit componentPathChanged();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QmlDesigner::PreviewTooltipBackend::componentName() const
|
QString PreviewTooltipBackend::name() const
|
||||||
{
|
{
|
||||||
return m_componentName;
|
return m_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlDesigner::PreviewTooltipBackend::setComponentName(const QString &name)
|
void PreviewTooltipBackend::setName(const QString &name)
|
||||||
{
|
{
|
||||||
m_componentName = name;
|
m_name = name;
|
||||||
|
if (m_name != name)
|
||||||
|
emit nameChanged();
|
||||||
|
}
|
||||||
|
|
||||||
if (m_componentName != name)
|
QString PreviewTooltipBackend::path() const
|
||||||
emit componentNameChanged();
|
{
|
||||||
|
return m_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PreviewTooltipBackend::setPath(const QString &path)
|
||||||
|
{
|
||||||
|
m_path = path;
|
||||||
|
if (m_path != path)
|
||||||
|
emit pathChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PreviewTooltipBackend::info() const
|
||||||
|
{
|
||||||
|
return m_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PreviewTooltipBackend::setInfo(const QString &info)
|
||||||
|
{
|
||||||
|
m_info = info;
|
||||||
|
if (m_info != info)
|
||||||
|
emit infoChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PreviewTooltipBackend::state() const
|
||||||
|
{
|
||||||
|
return m_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets the imageCache state hint. Valid content depends on image cache collector used.
|
||||||
|
void PreviewTooltipBackend::setState(const QString &state)
|
||||||
|
{
|
||||||
|
m_state = state;
|
||||||
|
if (m_state != state)
|
||||||
|
emit stateChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
|||||||
@@ -39,8 +39,10 @@ class PreviewTooltipBackend : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
Q_PROPERTY(QString componentPath READ componentPath WRITE setComponentPath NOTIFY componentPathChanged)
|
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
|
||||||
Q_PROPERTY(QString componentName READ componentName WRITE setComponentName NOTIFY componentNameChanged)
|
Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged)
|
||||||
|
Q_PROPERTY(QString info READ info WRITE setInfo NOTIFY infoChanged)
|
||||||
|
Q_PROPERTY(QString state READ state WRITE setState NOTIFY stateChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PreviewTooltipBackend(ImageCache &cache);
|
PreviewTooltipBackend(ImageCache &cache);
|
||||||
@@ -48,20 +50,30 @@ public:
|
|||||||
|
|
||||||
Q_INVOKABLE void showTooltip();
|
Q_INVOKABLE void showTooltip();
|
||||||
Q_INVOKABLE void hideTooltip();
|
Q_INVOKABLE void hideTooltip();
|
||||||
|
Q_INVOKABLE void reposition();
|
||||||
|
|
||||||
QString componentPath() const;
|
QString name() const;
|
||||||
void setComponentPath(const QString &path);
|
void setName(const QString &name);
|
||||||
|
QString path() const;
|
||||||
|
void setPath(const QString &path);
|
||||||
|
QString info() const;
|
||||||
|
void setInfo(const QString &info);
|
||||||
|
QString state() const;
|
||||||
|
void setState(const QString &state);
|
||||||
|
|
||||||
QString componentName() const;
|
bool isVisible() const;
|
||||||
void setComponentName(const QString &path);
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void componentPathChanged();
|
void nameChanged();
|
||||||
void componentNameChanged();
|
void pathChanged();
|
||||||
|
void infoChanged();
|
||||||
|
void stateChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_componentPath;
|
QString m_name;
|
||||||
QString m_componentName;
|
QString m_path;
|
||||||
|
QString m_info;
|
||||||
|
QString m_state;
|
||||||
std::unique_ptr<PreviewImageTooltip> m_tooltip;
|
std::unique_ptr<PreviewImageTooltip> m_tooltip;
|
||||||
ImageCache &m_cache;
|
ImageCache &m_cache;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ include (../../../../share/qtcreator/qml/qmlpuppet/types/types.pri)
|
|||||||
|
|
||||||
SOURCES += $$PWD/model/abstractview.cpp \
|
SOURCES += $$PWD/model/abstractview.cpp \
|
||||||
$$PWD/imagecache/imagecachecollector.cpp \
|
$$PWD/imagecache/imagecachecollector.cpp \
|
||||||
|
$$PWD/imagecache/imagecachefontcollector.cpp \
|
||||||
$$PWD/model/rewriterview.cpp \
|
$$PWD/model/rewriterview.cpp \
|
||||||
$$PWD/model/documentmessage.cpp \
|
$$PWD/model/documentmessage.cpp \
|
||||||
$$PWD/metainfo/metainfo.cpp \
|
$$PWD/metainfo/metainfo.cpp \
|
||||||
@@ -95,6 +96,7 @@ SOURCES += $$PWD/model/abstractview.cpp \
|
|||||||
|
|
||||||
HEADERS += $$PWD/include/qmldesignercorelib_global.h \
|
HEADERS += $$PWD/include/qmldesignercorelib_global.h \
|
||||||
$$PWD/imagecache/imagecachecollector.h \
|
$$PWD/imagecache/imagecachecollector.h \
|
||||||
|
$$PWD/imagecache/imagecachefontcollector.h \
|
||||||
$$PWD/include/abstractview.h \
|
$$PWD/include/abstractview.h \
|
||||||
$$PWD/include/nodeinstanceview.h \
|
$$PWD/include/nodeinstanceview.h \
|
||||||
$$PWD/include/rewriterview.h \
|
$$PWD/include/rewriterview.h \
|
||||||
|
|||||||
@@ -0,0 +1,126 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2021 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** 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
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "imagecachefontcollector.h"
|
||||||
|
|
||||||
|
#include <theme.h>
|
||||||
|
|
||||||
|
#include <QtGui/qrawfont.h>
|
||||||
|
#include <QtGui/qpainter.h>
|
||||||
|
#include <QtGui/qimage.h>
|
||||||
|
#include <QtGui/qfontdatabase.h>
|
||||||
|
#include <QtGui/qfontmetrics.h>
|
||||||
|
#include <QtCore/qfileinfo.h>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
ImageCacheFontCollector::ImageCacheFontCollector() = default;
|
||||||
|
|
||||||
|
ImageCacheFontCollector::~ImageCacheFontCollector() = default;
|
||||||
|
|
||||||
|
QByteArray fileToByteArray(QString const &filename)
|
||||||
|
{
|
||||||
|
QFile file(filename);
|
||||||
|
QFileInfo fileInfo(file);
|
||||||
|
|
||||||
|
if (fileInfo.exists() && file.open(QFile::ReadOnly))
|
||||||
|
return file.readAll();
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageCacheFontCollector::start(Utils::SmallStringView name,
|
||||||
|
Utils::SmallStringView state,
|
||||||
|
CaptureCallback captureCallback,
|
||||||
|
AbortCallback abortCallback)
|
||||||
|
{
|
||||||
|
// State contains size, text color, and sample text
|
||||||
|
QStringList hints = QString(state).split('@');
|
||||||
|
int dim(300);
|
||||||
|
if (hints.size() >= 1) {
|
||||||
|
bool ok = false;
|
||||||
|
int newDim = QString(hints[0]).toInt(&ok);
|
||||||
|
if (ok)
|
||||||
|
dim = newDim;
|
||||||
|
}
|
||||||
|
QColor textColor(Theme::getColor(Theme::DStextColor));
|
||||||
|
if (hints.size() >= 2)
|
||||||
|
textColor.setNamedColor(hints[1]);
|
||||||
|
QString text = hints.size() >= 3 ? hints[2] : "Abc";
|
||||||
|
QSize size(dim, dim);
|
||||||
|
QRect rect({0, 0}, size);
|
||||||
|
|
||||||
|
QByteArray fontData(fileToByteArray(QString(name)));
|
||||||
|
if (!fontData.isEmpty()) {
|
||||||
|
int fontId = QFontDatabase::addApplicationFontFromData(fontData);
|
||||||
|
if (fontId != -1) {
|
||||||
|
QRawFont rawFont(fontData, 10.); // Pixel size is irrelevant, we only need style/weight
|
||||||
|
const QStringList families = QFontDatabase::applicationFontFamilies(fontId);
|
||||||
|
if (!families.isEmpty()) {
|
||||||
|
QString fontFamily = families.first();
|
||||||
|
if (text.contains("%1"))
|
||||||
|
text = text.arg(fontFamily);
|
||||||
|
QFont font(fontFamily);
|
||||||
|
font.setStyle(rawFont.style());
|
||||||
|
font.setStyleName(rawFont.styleName());
|
||||||
|
font.setWeight(rawFont.weight());
|
||||||
|
QImage image(size, QImage::Format_ARGB32);
|
||||||
|
image.fill(Qt::transparent);
|
||||||
|
int pixelSize(200);
|
||||||
|
int flags = Qt::AlignCenter;
|
||||||
|
while (pixelSize >= 2) {
|
||||||
|
font.setPixelSize(pixelSize);
|
||||||
|
QFontMetrics fm(font, &image);
|
||||||
|
QRect bounds = fm.boundingRect(rect, flags, text);
|
||||||
|
if (bounds.width() < rect.width() && bounds.height() < rect.height()) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
int newPixelSize = pixelSize - 1;
|
||||||
|
if (bounds.width() >= rect.width())
|
||||||
|
newPixelSize = int(qreal(pixelSize) * qreal(rect.width()) / qreal(bounds.width()));
|
||||||
|
else if (bounds.height() >= rect.height())
|
||||||
|
newPixelSize = int(qreal(pixelSize) * qreal(rect.height()) / qreal(bounds.height()));
|
||||||
|
if (newPixelSize < pixelSize)
|
||||||
|
pixelSize = newPixelSize;
|
||||||
|
else
|
||||||
|
--pixelSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QPainter painter(&image);
|
||||||
|
painter.setPen(textColor);
|
||||||
|
painter.setFont(font);
|
||||||
|
painter.drawText(rect, flags, text);
|
||||||
|
|
||||||
|
captureCallback(std::move(image));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QFontDatabase::removeApplicationFont(fontId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
abortCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2021 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** 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
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "imagecachecollectorinterface.h"
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class ImageCacheFontCollector final : public ImageCacheCollectorInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ImageCacheFontCollector();
|
||||||
|
|
||||||
|
~ImageCacheFontCollector();
|
||||||
|
|
||||||
|
void start(Utils::SmallStringView filePath,
|
||||||
|
Utils::SmallStringView state,
|
||||||
|
CaptureCallback captureCallback,
|
||||||
|
AbortCallback abortCallback) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
||||||
@@ -418,6 +418,8 @@ Project {
|
|||||||
"include/imagecacheinterface.h",
|
"include/imagecacheinterface.h",
|
||||||
"imagecache/imagecachecollector.cpp",
|
"imagecache/imagecachecollector.cpp",
|
||||||
"imagecache/imagecachecollector.h",
|
"imagecache/imagecachecollector.h",
|
||||||
|
"imagecache/imagecachefontcollector.cpp",
|
||||||
|
"imagecache/imagecachefontcollector.h",
|
||||||
"imagecache/imagecache.cpp",
|
"imagecache/imagecache.cpp",
|
||||||
"imagecache/imagecachecollectorinterface.h",
|
"imagecache/imagecachecollectorinterface.h",
|
||||||
"imagecache/imagecacheconnectionmanager.cpp",
|
"imagecache/imagecacheconnectionmanager.cpp",
|
||||||
|
|||||||
Reference in New Issue
Block a user