Implement adding images in the rich text format to the annotations

Task-number: QDS-3306
Change-Id: I8372c3d10ad5beb1ec52d8d3d45a3f963711a63c
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
Reviewed-by: Michael Winkelmann <michael.winkelmann@qt.io>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Lukasz Ornatek
2020-12-16 14:59:17 +01:00
committed by Thomas Hartmann
parent 34798b3efd
commit f5a49e6b0b
4 changed files with 128 additions and 1 deletions

View File

@@ -28,8 +28,14 @@
#include "richtexteditor/richtexteditor.h" #include "richtexteditor/richtexteditor.h"
#include <QCryptographicHash>
#include "QStringListModel" #include "QStringListModel"
#include "projectexplorer/session.h"
#include "projectexplorer/target.h"
#include "qmldesignerplugin.h"
#include "qmlprojectmanager/qmlproject.h"
namespace QmlDesigner { namespace QmlDesigner {
AnnotationCommentTab::AnnotationCommentTab(QWidget *parent) AnnotationCommentTab::AnnotationCommentTab(QWidget *parent)
@@ -38,7 +44,17 @@ AnnotationCommentTab::AnnotationCommentTab(QWidget *parent)
{ {
ui->setupUi(this); ui->setupUi(this);
m_editor = new RichTextEditor; m_editor = new RichTextEditor{this};
connect(m_editor, &RichTextEditor::insertingImage, this, [this](QString &filePath) {
filePath = backupFile(filePath);
});
Utils::FilePath projPath = ProjectExplorer::SessionManager::startupProject()->projectFilePath();
m_editor->setDocumentBaseUrl(QUrl::fromLocalFile(projPath.toString()));
m_editor->setImageActionVisible(true);
ui->formLayout->setWidget(3, QFormLayout::FieldRole, m_editor); ui->formLayout->setWidget(3, QFormLayout::FieldRole, m_editor);
ui->titleEdit->setModel(new QStringListModel{QStringList{"Description", ui->titleEdit->setModel(new QStringListModel{QStringList{"Description",
@@ -113,4 +129,64 @@ void AnnotationCommentTab::commentTitleChanged(const QString &text)
emit titleChanged(text, this); emit titleChanged(text, this);
} }
QString AnnotationCommentTab::backupFile(const QString &filePath)
{
const QDir projDir(
ProjectExplorer::SessionManager::startupProject()->projectDirectory().toString());
const QString imageSubDir(".AnnotationImages");
const QDir imgDir(projDir.absolutePath() + QDir::separator() + imageSubDir);
ensureDir(imgDir);
const QFileInfo oldFile(filePath);
QFileInfo newFile(imgDir, oldFile.fileName());
QString newName = newFile.baseName() + "_%1." + newFile.completeSuffix();
for (size_t i = 1; true; ++i) {
if (!newFile.exists()) {
QFile(oldFile.absoluteFilePath()).copy(newFile.absoluteFilePath());
break;
} else if (compareFileChecksum(oldFile.absoluteFilePath(),
newFile.absoluteFilePath()) == 0) {
break;
}
newFile.setFile(imgDir, newName.arg(i));
}
return projDir.relativeFilePath(newFile.absoluteFilePath());
}
void AnnotationCommentTab::ensureDir(const QDir &dir)
{
if (!dir.exists()) {
dir.mkdir(".");
}
}
int AnnotationCommentTab::compareFileChecksum(const QString &firstFile, const QString &secondFile)
{
QCryptographicHash sum1(QCryptographicHash::Md5);
{
QFile f1(firstFile);
if (f1.open(QFile::ReadOnly)) {
sum1.addData(&f1);
}
}
QCryptographicHash sum2(QCryptographicHash::Md5);
{
QFile f2(secondFile);
if (f2.open(QFile::ReadOnly)) {
sum2.addData(&f2);
}
}
return sum1.result().compare(sum2.result());
}
} //namespace QmlDesigner } //namespace QmlDesigner

View File

@@ -29,6 +29,8 @@
#include "annotation.h" #include "annotation.h"
class QDir;
namespace QmlDesigner { namespace QmlDesigner {
namespace Ui { namespace Ui {
@@ -64,6 +66,10 @@ private:
RichTextEditor *m_editor; RichTextEditor *m_editor;
Comment m_comment; Comment m_comment;
QString backupFile(const QString &filePath);
void ensureDir(const QDir &dir);
int compareFileChecksum(const QString &firstFile, const QString &secondFile);
}; };
} //namespace QmlDesigner } //namespace QmlDesigner

View File

@@ -32,6 +32,7 @@
#include <QAction> #include <QAction>
#include <QActionGroup> #include <QActionGroup>
#include <QColorDialog> #include <QColorDialog>
#include <QFileDialog>
#include <QPainter> #include <QPainter>
#include <QPointer> #include <QPointer>
#include <QScopeGuard> #include <QScopeGuard>
@@ -120,6 +121,7 @@ RichTextEditor::RichTextEditor(QWidget *parent)
setupEditActions(); setupEditActions();
setupTextActions(); setupTextActions();
setupImageActions();
setupHyperlinkActions(); setupHyperlinkActions();
setupAlignActions(); setupAlignActions();
setupListActions(); setupListActions();
@@ -184,6 +186,16 @@ void RichTextEditor::setTabChangesFocus(bool change)
ui->textEdit->setTabChangesFocus(change); ui->textEdit->setTabChangesFocus(change);
} }
void RichTextEditor::setImageActionVisible(bool change)
{
m_actionImage->setVisible(change);
}
void RichTextEditor::setDocumentBaseUrl(const QUrl& url)
{
ui->textEdit->document()->setBaseUrl(url);
}
QIcon RichTextEditor::getIcon(Theme::Icon icon) QIcon RichTextEditor::getIcon(Theme::Icon icon)
{ {
const QString fontName = "qtds_propertyIconFont.ttf"; const QString fontName = "qtds_propertyIconFont.ttf";
@@ -361,6 +373,30 @@ void RichTextEditor::setupTextActions()
ui->toolBar->addSeparator(); ui->toolBar->addSeparator();
} }
void RichTextEditor::setupImageActions()
{
auto insertImage = [this]() {
QFileDialog dialog(this);
dialog.setFileMode(QFileDialog::ExistingFile);
dialog.setWindowTitle(tr("Select Image"));
dialog.setNameFilters({tr("Image files (*.png *.jpg)")});
if (dialog.exec()) {
QStringList files = dialog.selectedFiles();
for (QString& filePath : files) {
emit insertingImage(filePath);
ui->textEdit->insertHtml("<img src=\"" + filePath + "\" />");
}
}
};
m_actionImage = ui->toolBar
->addAction(getIcon(Theme::Icon::addFile), tr("Insert &Image"), insertImage);
setImageActionVisible(false);
}
void RichTextEditor::setupHyperlinkActions() void RichTextEditor::setupHyperlinkActions()
{ {
const QIcon bulletIcon(getIcon(Theme::Icon::actionIconBinding)); const QIcon bulletIcon(getIcon(Theme::Icon::actionIconBinding));

View File

@@ -63,6 +63,13 @@ public:
void setTabChangesFocus(bool change); void setTabChangesFocus(bool change);
void setImageActionVisible(bool change);
void setDocumentBaseUrl(const QUrl &url);
signals:
void insertingImage(QString &filePath);
private slots: private slots:
void currentCharFormatChanged(const QTextCharFormat &format); void currentCharFormatChanged(const QTextCharFormat &format);
void cursorPositionChanged(); void cursorPositionChanged();
@@ -79,6 +86,7 @@ private:
void setupEditActions(); void setupEditActions();
void setupTextActions(); void setupTextActions();
void setupImageActions();
void setupHyperlinkActions(); void setupHyperlinkActions();
void setupAlignActions(); void setupAlignActions();
void setupListActions(); void setupListActions();
@@ -97,6 +105,7 @@ private:
QAction *m_actionTextItalic; QAction *m_actionTextItalic;
QAction *m_actionTextUnderline; QAction *m_actionTextUnderline;
QAction *m_actionImage;
QAction *m_actionHyperlink; QAction *m_actionHyperlink;
QAction *m_actionAlignLeft; QAction *m_actionAlignLeft;