mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 05:49:53 +08:00
InsertImageDialog: support scaling image
This commit is contained in:
parent
5cc8d6c8f1
commit
9923feea14
@ -14,7 +14,6 @@ VInsertImageDialog::VInsertImageDialog(const QString &p_title,
|
||||
bool p_browsable,
|
||||
QWidget *p_parent)
|
||||
: QDialog(p_parent),
|
||||
m_image(NULL),
|
||||
m_browsable(p_browsable)
|
||||
{
|
||||
setupUI(p_title, p_imageTitle, p_imagePath);
|
||||
@ -35,40 +34,81 @@ VInsertImageDialog::VInsertImageDialog(const QString &p_title,
|
||||
handleInputChanged();
|
||||
}
|
||||
|
||||
VInsertImageDialog::~VInsertImageDialog()
|
||||
{
|
||||
delete m_image;
|
||||
m_image = NULL;
|
||||
}
|
||||
|
||||
void VInsertImageDialog::setupUI(const QString &p_title,
|
||||
const QString &p_imageTitle,
|
||||
const QString &p_imagePath)
|
||||
{
|
||||
QLabel *pathLabel = new QLabel(tr("&From:"));
|
||||
// Path.
|
||||
m_pathEdit = new VLineEdit(p_imagePath);
|
||||
pathLabel->setBuddy(m_pathEdit);
|
||||
browseBtn = new QPushButton(tr("&Browse"));
|
||||
m_pathEdit->setReadOnly(!m_browsable);
|
||||
browseBtn = new QPushButton(tr("&Browse"));
|
||||
browseBtn->setEnabled(m_browsable);
|
||||
|
||||
QLabel *imageTitleLabel = new QLabel(tr("&Image title:"));
|
||||
// Title.
|
||||
m_imageTitleEdit = new VMetaWordLineEdit(p_imageTitle);
|
||||
m_imageTitleEdit->selectAll();
|
||||
imageTitleLabel->setBuddy(m_imageTitleEdit);
|
||||
QValidator *validator = new QRegExpValidator(QRegExp(VUtils::c_imageTitleRegExp),
|
||||
m_imageTitleEdit);
|
||||
m_imageTitleEdit->setValidator(validator);
|
||||
|
||||
// Scale.
|
||||
m_widthSpin = new QSpinBox();
|
||||
m_widthSpin->setMinimum(1);
|
||||
m_widthSpin->setSingleStep(10);
|
||||
m_widthSpin->setSuffix(" px");
|
||||
connect(m_widthSpin, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged),
|
||||
this, [this](int p_val) {
|
||||
if (!m_image) {
|
||||
return;
|
||||
}
|
||||
|
||||
int height = m_image->height() * (1.0 * p_val / m_image->width());
|
||||
m_imageLabel->resize(p_val, height);
|
||||
});
|
||||
|
||||
// 0.1 to 2.0 -> 1 to 20.
|
||||
m_scaleSlider = new QSlider();
|
||||
m_scaleSlider->setOrientation(Qt::Horizontal);
|
||||
m_scaleSlider->setMinimum(1);
|
||||
m_scaleSlider->setMaximum(20);
|
||||
m_scaleSlider->setValue(10);
|
||||
m_scaleSlider->setSingleStep(1);
|
||||
m_scaleSlider->setPageStep(5);
|
||||
connect(m_scaleSlider, &QSlider::valueChanged,
|
||||
this, [this](int p_val) {
|
||||
if (!m_image) {
|
||||
return;
|
||||
}
|
||||
|
||||
int width = m_image->width();
|
||||
qreal factor = 1.0;
|
||||
if (p_val != 10) {
|
||||
factor = p_val / 10.0;
|
||||
width = m_image->width() * factor;
|
||||
}
|
||||
|
||||
m_widthSpin->setValue(width);
|
||||
m_sliderLabel->setText(QString::number(factor) + "x");
|
||||
});
|
||||
|
||||
m_sliderLabel = new QLabel("1x");
|
||||
|
||||
QGridLayout *topLayout = new QGridLayout();
|
||||
topLayout->addWidget(pathLabel, 0, 0);
|
||||
topLayout->addWidget(m_pathEdit, 0, 1);
|
||||
topLayout->addWidget(browseBtn, 0, 2);
|
||||
topLayout->addWidget(imageTitleLabel, 1, 0);
|
||||
topLayout->addWidget(m_imageTitleEdit, 1, 1, 1, 2);
|
||||
topLayout->addWidget(new QLabel(tr("From:")), 0, 0, 1, 1);
|
||||
topLayout->addWidget(m_pathEdit, 0, 1, 1, 3);
|
||||
topLayout->addWidget(browseBtn, 0, 4, 1, 1);
|
||||
topLayout->addWidget(new QLabel(tr("Title:")), 1, 0, 1, 1);
|
||||
topLayout->addWidget(m_imageTitleEdit, 1, 1, 1, 4);
|
||||
topLayout->addWidget(new QLabel(tr("Scaling width:")), 2, 0, 1, 1);
|
||||
topLayout->addWidget(m_widthSpin, 2, 1, 1, 1);
|
||||
topLayout->addWidget(m_scaleSlider, 2, 2, 1, 2);
|
||||
topLayout->addWidget(m_sliderLabel, 2, 4, 1, 1);
|
||||
|
||||
topLayout->setColumnStretch(0, 0);
|
||||
topLayout->setColumnStretch(1, 1);
|
||||
topLayout->setColumnStretch(2, 0);
|
||||
topLayout->setColumnStretch(1, 0);
|
||||
topLayout->setColumnStretch(2, 1);
|
||||
topLayout->setColumnStretch(3, 1);
|
||||
topLayout->setColumnStretch(4, 0);
|
||||
|
||||
// Ok is the default button.
|
||||
m_btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
@ -76,15 +116,23 @@ void VInsertImageDialog::setupUI(const QString &p_title,
|
||||
connect(m_btnBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
m_btnBox->button(QDialogButtonBox::Ok)->setProperty("SpecialBtn", true);
|
||||
|
||||
imagePreviewLabel = new QLabel();
|
||||
imagePreviewLabel->setVisible(false);
|
||||
m_imageLabel = new QLabel();
|
||||
m_imageLabel->setScaledContents(true);
|
||||
|
||||
m_previewArea = new QScrollArea();
|
||||
m_previewArea->setBackgroundRole(QPalette::Dark);
|
||||
m_previewArea->setWidget(m_imageLabel);
|
||||
int minWidth = 512 * VUtils::calculateScaleFactor();
|
||||
m_previewArea->setMinimumSize(minWidth, minWidth);
|
||||
|
||||
setImageControlsVisible(false);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout();
|
||||
mainLayout->addLayout(topLayout);
|
||||
mainLayout->addWidget(m_btnBox);
|
||||
mainLayout->addWidget(imagePreviewLabel);
|
||||
mainLayout->addWidget(m_previewArea);
|
||||
setLayout(mainLayout);
|
||||
mainLayout->setSizeConstraint(QLayout::SetFixedSize);
|
||||
|
||||
setWindowTitle(p_title);
|
||||
|
||||
m_imageTitleEdit->setFocus();
|
||||
@ -133,34 +181,29 @@ void VInsertImageDialog::handleBrowseBtnClicked()
|
||||
m_imageTitleEdit->setFocus();
|
||||
}
|
||||
|
||||
void VInsertImageDialog::setImage(const QImage &image)
|
||||
void VInsertImageDialog::setImage(const QImage &p_image)
|
||||
{
|
||||
if (image.isNull()) {
|
||||
imagePreviewLabel->setVisible(false);
|
||||
delete m_image;
|
||||
m_image = NULL;
|
||||
if (p_image.isNull()) {
|
||||
m_image.clear();
|
||||
m_imageLabel->clear();
|
||||
|
||||
handleInputChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
int width = 512 * VUtils::calculateScaleFactor();
|
||||
QSize previewSize(width, width);
|
||||
if (!m_image) {
|
||||
m_image = new QImage(image);
|
||||
setImageControlsVisible(false);
|
||||
} else {
|
||||
*m_image = image;
|
||||
}
|
||||
m_image.reset(new QImage(p_image));
|
||||
|
||||
QPixmap pixmap;
|
||||
if (image.width() > width || image.height() > width) {
|
||||
pixmap = QPixmap::fromImage(m_image->scaled(previewSize, Qt::KeepAspectRatio));
|
||||
} else {
|
||||
pixmap = QPixmap::fromImage(*m_image);
|
||||
}
|
||||
m_imageLabel->setPixmap(QPixmap::fromImage(*m_image));
|
||||
|
||||
imagePreviewLabel->setPixmap(pixmap);
|
||||
imagePreviewLabel->setVisible(true);
|
||||
m_imageLabel->adjustSize();
|
||||
|
||||
// Set the scaling widgets.
|
||||
m_scaleSlider->setValue(10);
|
||||
|
||||
int width = m_image->width();
|
||||
m_widthSpin->setMaximum(width * 5);
|
||||
m_widthSpin->setValue(width);
|
||||
|
||||
setImageControlsVisible(true);
|
||||
}
|
||||
|
||||
handleInputChanged();
|
||||
}
|
||||
@ -281,3 +324,22 @@ void VInsertImageDialog::setPath(const QString &p_path)
|
||||
m_pathEdit->setText(p_path);
|
||||
handlePathEditChanged();
|
||||
}
|
||||
|
||||
void VInsertImageDialog::setImageControlsVisible(bool p_visible)
|
||||
{
|
||||
m_widthSpin->setEnabled(p_visible);
|
||||
m_scaleSlider->setEnabled(p_visible);
|
||||
m_sliderLabel->setEnabled(p_visible);
|
||||
|
||||
m_previewArea->setVisible(p_visible);
|
||||
}
|
||||
|
||||
int VInsertImageDialog::getOverridenWidth() const
|
||||
{
|
||||
int width = m_widthSpin->value();
|
||||
if (m_image && m_image->width() != width) {
|
||||
return width;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -13,6 +13,9 @@ class VLineEdit;
|
||||
class VMetaWordLineEdit;
|
||||
class QPushButton;
|
||||
class QDialogButtonBox;
|
||||
class QScrollArea;
|
||||
class QSpinBox;
|
||||
class QSlider;
|
||||
|
||||
class VInsertImageDialog : public QDialog
|
||||
{
|
||||
@ -30,18 +33,19 @@ public:
|
||||
bool p_browsable = true,
|
||||
QWidget *p_parent = nullptr);
|
||||
|
||||
~VInsertImageDialog();
|
||||
|
||||
QString getImageTitleInput() const;
|
||||
|
||||
QString getPathInput() const;
|
||||
|
||||
void setImage(const QImage &image);
|
||||
void setImage(const QImage &p_image);
|
||||
|
||||
QImage getImage() const;
|
||||
|
||||
VInsertImageDialog::ImageType getImageType() const;
|
||||
|
||||
// Return 0 if no override.
|
||||
int getOverridenWidth() const;
|
||||
|
||||
public slots:
|
||||
void imageDownloaded(const QByteArray &data);
|
||||
|
||||
@ -61,13 +65,22 @@ private:
|
||||
|
||||
void setPath(const QString &p_path);
|
||||
|
||||
void setImageControlsVisible(bool p_visible);
|
||||
|
||||
VMetaWordLineEdit *m_imageTitleEdit;
|
||||
VLineEdit *m_pathEdit;
|
||||
QPushButton *browseBtn;
|
||||
QDialogButtonBox *m_btnBox;
|
||||
QLabel *imagePreviewLabel;
|
||||
|
||||
QImage *m_image;
|
||||
QSpinBox *m_widthSpin;
|
||||
QSlider *m_scaleSlider;
|
||||
QLabel *m_sliderLabel;
|
||||
|
||||
QDialogButtonBox *m_btnBox;
|
||||
|
||||
QLabel *m_imageLabel;
|
||||
QScrollArea *m_previewArea;
|
||||
|
||||
QSharedPointer<QImage> m_image;
|
||||
|
||||
// Whether enable the browse action.
|
||||
bool m_browsable;
|
||||
|
@ -52,28 +52,51 @@ bool VMdEditOperations::insertImageFromMimeData(const QMimeData *source)
|
||||
insertImageFromQImage(dialog.getImageTitleInput(),
|
||||
m_file->fetchImageFolderPath(),
|
||||
m_file->getImageFolderInLink(),
|
||||
image);
|
||||
image,
|
||||
dialog.getOverridenWidth());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void VMdEditOperations::insertImageFromQImage(const QString &title,
|
||||
const QString &path,
|
||||
const QString &folderInLink,
|
||||
const QImage &image)
|
||||
// @p_width, @p_height: 0 if no override.
|
||||
static QString imageLink(const QString &p_title,
|
||||
const QString &p_url,
|
||||
int p_width = 0,
|
||||
int p_height = 0)
|
||||
{
|
||||
QString fileName = VUtils::generateImageFileName(path, title);
|
||||
QString filePath = QDir(path).filePath(fileName);
|
||||
QString scale;
|
||||
if (p_width > 0) {
|
||||
if (p_height > 0) {
|
||||
scale = QString(" =%1x%2").arg(p_width).arg(p_height);
|
||||
} else {
|
||||
scale = QString(" =%1x").arg(p_width);
|
||||
}
|
||||
} else if (p_height > 0) {
|
||||
scale = QString(" =x%1").arg(p_height);
|
||||
}
|
||||
|
||||
return QString("").arg(p_title).arg(p_url).arg(scale);
|
||||
}
|
||||
|
||||
void VMdEditOperations::insertImageFromQImage(const QString &p_title,
|
||||
const QString &p_folderPath,
|
||||
const QString &p_folderInLink,
|
||||
const QImage &p_image,
|
||||
int p_width,
|
||||
int p_height)
|
||||
{
|
||||
QString fileName = VUtils::generateImageFileName(p_folderPath, p_title);
|
||||
QString filePath = QDir(p_folderPath).filePath(fileName);
|
||||
V_ASSERT(!QFile(filePath).exists());
|
||||
|
||||
QString errStr;
|
||||
bool ret = VUtils::makePath(path);
|
||||
bool ret = VUtils::makePath(p_folderPath);
|
||||
if (!ret) {
|
||||
errStr = tr("Fail to create image folder <span style=\"%1\">%2</span>.")
|
||||
.arg(g_config->c_dataTextStyle).arg(path);
|
||||
.arg(g_config->c_dataTextStyle).arg(p_folderPath);
|
||||
} else {
|
||||
ret = image.save(filePath);
|
||||
ret = p_image.save(filePath);
|
||||
if (!ret) {
|
||||
errStr = tr("Fail to save image <span style=\"%1\">%2</span>.")
|
||||
.arg(g_config->c_dataTextStyle).arg(filePath);
|
||||
@ -82,7 +105,7 @@ void VMdEditOperations::insertImageFromQImage(const QString &title,
|
||||
|
||||
if (!ret) {
|
||||
VUtils::showMessage(QMessageBox::Warning, tr("Warning"),
|
||||
tr("Fail to insert image <span style=\"%1\">%2</span>.").arg(g_config->c_dataTextStyle).arg(title),
|
||||
tr("Fail to insert image <span style=\"%1\">%2</span>.").arg(g_config->c_dataTextStyle).arg(p_title),
|
||||
errStr,
|
||||
QMessageBox::Ok,
|
||||
QMessageBox::Ok,
|
||||
@ -90,11 +113,11 @@ void VMdEditOperations::insertImageFromQImage(const QString &title,
|
||||
return;
|
||||
}
|
||||
|
||||
QString url = QString("%1/%2").arg(folderInLink).arg(fileName);
|
||||
QString md = QString("").arg(title).arg(url);
|
||||
insertText(md);
|
||||
QString url = QString("%1/%2").arg(p_folderInLink).arg(fileName);
|
||||
|
||||
qDebug() << "insert image" << title << filePath;
|
||||
insertText(imageLink(p_title, url, p_width, p_height));
|
||||
|
||||
qDebug() << "insert image" << p_title << filePath;
|
||||
|
||||
VMdEditor *mdEditor = dynamic_cast<VMdEditor *>(m_editor);
|
||||
Q_ASSERT(mdEditor);
|
||||
@ -104,7 +127,9 @@ void VMdEditOperations::insertImageFromQImage(const QString &title,
|
||||
void VMdEditOperations::insertImageFromPath(const QString &p_title,
|
||||
const QString &p_folderPath,
|
||||
const QString &p_folderInLink,
|
||||
const QString &p_srcImagePath)
|
||||
const QString &p_srcImagePath,
|
||||
int p_width,
|
||||
int p_height)
|
||||
{
|
||||
insertImageFromPath(p_title,
|
||||
p_folderPath,
|
||||
@ -112,7 +137,9 @@ void VMdEditOperations::insertImageFromPath(const QString &p_title,
|
||||
p_srcImagePath,
|
||||
true,
|
||||
QString(),
|
||||
QString());
|
||||
QString(),
|
||||
p_width,
|
||||
p_height);
|
||||
}
|
||||
|
||||
void VMdEditOperations::insertImageFromPath(const QString &p_title,
|
||||
@ -121,7 +148,9 @@ void VMdEditOperations::insertImageFromPath(const QString &p_title,
|
||||
const QString &p_srcImagePath,
|
||||
bool p_insertText,
|
||||
QString &p_destImagePath,
|
||||
QString &p_urlInLink)
|
||||
QString &p_urlInLink,
|
||||
int p_width,
|
||||
int p_height)
|
||||
{
|
||||
p_destImagePath.clear();
|
||||
p_urlInLink.clear();
|
||||
@ -161,8 +190,7 @@ void VMdEditOperations::insertImageFromPath(const QString &p_title,
|
||||
p_destImagePath = filePath;
|
||||
|
||||
if (p_insertText) {
|
||||
QString md = QString("").arg(p_title).arg(p_urlInLink);
|
||||
insertText(md);
|
||||
insertText(imageLink(p_title, p_urlInLink, p_width, p_height));
|
||||
}
|
||||
|
||||
qDebug() << "insert image" << p_title << filePath;
|
||||
@ -214,18 +242,21 @@ bool VMdEditOperations::insertImageFromURL(const QUrl &imageUrl)
|
||||
insertImageFromPath(dialog.getImageTitleInput(),
|
||||
m_file->fetchImageFolderPath(),
|
||||
m_file->getImageFolderInLink(),
|
||||
imagePath);
|
||||
imagePath,
|
||||
dialog.getOverridenWidth());
|
||||
} else {
|
||||
if (dialog.getImageType() == VInsertImageDialog::ImageType::LocalFile) {
|
||||
insertImageFromPath(dialog.getImageTitleInput(),
|
||||
m_file->fetchImageFolderPath(),
|
||||
m_file->getImageFolderInLink(),
|
||||
dialog.getPathInput());
|
||||
dialog.getPathInput(),
|
||||
dialog.getOverridenWidth());
|
||||
} else {
|
||||
insertImageFromQImage(dialog.getImageTitleInput(),
|
||||
m_file->fetchImageFolderPath(),
|
||||
m_file->getImageFolderInLink(),
|
||||
dialog.getImage());
|
||||
dialog.getImage(),
|
||||
dialog.getOverridenWidth());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -246,14 +277,16 @@ bool VMdEditOperations::insertImage()
|
||||
insertImageFromPath(dialog.getImageTitleInput(),
|
||||
m_file->fetchImageFolderPath(),
|
||||
m_file->getImageFolderInLink(),
|
||||
dialog.getPathInput());
|
||||
dialog.getPathInput(),
|
||||
dialog.getOverridenWidth());
|
||||
} else {
|
||||
QImage img = dialog.getImage();
|
||||
if (!img.isNull()) {
|
||||
insertImageFromQImage(dialog.getImageTitleInput(),
|
||||
m_file->fetchImageFolderPath(),
|
||||
m_file->getImageFolderInLink(),
|
||||
img);
|
||||
img,
|
||||
dialog.getOverridenWidth());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1168,9 +1201,8 @@ bool VMdEditOperations::insertLink(const QString &p_linkText,
|
||||
bool VMdEditOperations::insertImageLink(const QString &p_linkText,
|
||||
const QString &p_linkUrl)
|
||||
{
|
||||
QString link = QString("").arg(p_linkText).arg(p_linkUrl);
|
||||
QTextCursor cursor = m_editor->textCursorW();
|
||||
cursor.insertText(link);
|
||||
cursor.insertText(imageLink(p_linkText, p_linkUrl));
|
||||
m_editor->setTextCursorW(cursor);
|
||||
|
||||
setVimMode(VimMode::Insert);
|
||||
|
@ -41,7 +41,9 @@ public:
|
||||
const QString &p_srcImagePath,
|
||||
bool p_insertText,
|
||||
QString &p_destImagePath,
|
||||
QString &p_urlInLink);
|
||||
QString &p_urlInLink,
|
||||
int p_width = 0,
|
||||
int p_height = 0);
|
||||
|
||||
private:
|
||||
// Insert image from @p_srcImagePath as to @p_folderPath.
|
||||
@ -49,14 +51,20 @@ private:
|
||||
void insertImageFromPath(const QString &p_title,
|
||||
const QString &p_folderPath,
|
||||
const QString &p_folderInLink,
|
||||
const QString &p_srcImagePath);
|
||||
const QString &p_srcImagePath,
|
||||
int p_width = 0,
|
||||
int p_height = 0);
|
||||
|
||||
// @title: title of the inserted image;
|
||||
// @path: the image folder path to insert the image in;
|
||||
// @folderInLink: the folder part in the image link.
|
||||
// @image: the image to be inserted;
|
||||
void insertImageFromQImage(const QString &title, const QString &path,
|
||||
const QString &folderInLink, const QImage &image);
|
||||
// @p_title: title of the inserted image;
|
||||
// @p_folderPath: the image folder path to insert the image in;
|
||||
// @p_folderInLink: the folder part in the image link.
|
||||
// @p_image: the image to be inserted;
|
||||
void insertImageFromQImage(const QString &p_title,
|
||||
const QString &p_folderPath,
|
||||
const QString &p_folderInLink,
|
||||
const QImage &p_image,
|
||||
int p_width = 0,
|
||||
int p_height = 0);
|
||||
|
||||
// Key press handlers.
|
||||
bool handleKeyTab(QKeyEvent *p_event);
|
||||
|
Loading…
x
Reference in New Issue
Block a user