forked from qt-creator/qt-creator
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:
committed by
Thomas Hartmann
parent
34798b3efd
commit
f5a49e6b0b
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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));
|
||||||
|
@@ -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;
|
||||||
|
Reference in New Issue
Block a user