diff --git a/src/plugins/qmldesigner/components/propertyeditor/contextpanewidgetimage.cpp b/src/plugins/qmldesigner/components/propertyeditor/contextpanewidgetimage.cpp index fa743a8a3f098c8162d4195dac7ee78eb94f74bf..5dae8f23a4f816682b52a51392d6c0a06053b188 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/contextpanewidgetimage.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/contextpanewidgetimage.cpp @@ -1,14 +1,19 @@ #include "contextpanewidgetimage.h" #include "ui_contextpanewidgetimage.h" +#include "ui_contextpanewidgetborderimage.h" #include <qmljs/qmljspropertyreader.h> #include <QFile> #include <QPixmap> #include <QPainter> #include <QGraphicsEffect> +#include <QMouseEvent> +#include <QScrollArea> +#include <QSlider> +#include <QDebug> namespace QmlDesigner { -bool LabelFilter::eventFilter(QObject *, QEvent *event) +bool LabelFilter::eventFilter(QObject *obj, QEvent *event) { if (event->type() == QEvent::MouseButtonPress) { return true; @@ -20,80 +25,177 @@ bool LabelFilter::eventFilter(QObject *, QEvent *event) emit doubleClicked(); event->accept(); return true; + } + return QObject::eventFilter(obj, event); +} + +bool WheelFilter::eventFilter(QObject *obj, QEvent *event) +{ + if (event->type() == QEvent::Wheel) { + if (obj + && obj->isWidgetType() + && obj != m_target) { + QApplication::sendEvent(m_target, event); + return true; + } } - return false; + return QObject::eventFilter(obj, event); } -ContextPaneWidgetImage::ContextPaneWidgetImage(QWidget *parent) : +ContextPaneWidgetImage::ContextPaneWidgetImage(QWidget *parent, bool borderImage) : QWidget(parent), - ui(new Ui::ContextPaneWidgetImage) + ui(0), uiBorderImage(0), previewWasVisible(false) { LabelFilter *labelFilter = new LabelFilter(this); - ui->setupUi(this); - ui->fileWidget->setShowComboBox(true); - ui->fileWidget->setFilter("*.png *.gif *.jpg"); - ui->label->setToolTip(tr("double click for preview")); - ui->label->installEventFilter(labelFilter); - m_previewDialog = new PreviewDialog(this); - m_previewDialog->hide(); - - connect(ui->stretchRadioButton, SIGNAL(toggled(bool)), this, SLOT(onStretchChanged())); - connect(ui->tileRadioButton, SIGNAL(toggled(bool)), this, SLOT(onStretchChanged())); - connect(ui->horizontalStretchRadioButton, SIGNAL(toggled(bool)), this, SLOT(onStretchChanged())); - connect(ui->verticalStretchRadioButton, SIGNAL(toggled(bool)), this, SLOT(onStretchChanged())); - connect(ui->preserveAspectFitRadioButton, SIGNAL(toggled(bool)), this, SLOT(onStretchChanged())); - connect(ui->cropAspectFitRadioButton, SIGNAL(toggled(bool)), this, SLOT(onStretchChanged())); - - connect(ui->fileWidget, SIGNAL(fileNameChanged(QUrl)), this, SLOT(onFileNameChanged())); + m_borderImage = borderImage; + + if (m_borderImage) { + uiBorderImage = new Ui::ContextPaneWidgetBorderImage; + uiBorderImage->setupUi(this); + m_fileWidget = uiBorderImage->fileWidget; + m_sizeLabel = uiBorderImage->sizeLabel; + uiBorderImage->label->setToolTip(tr("double click for preview")); + uiBorderImage->label->installEventFilter(labelFilter); + + + connect(uiBorderImage->verticalTileRadioButton, SIGNAL(toggled(bool)), this, SLOT(onVerticalStretchChanged())); + connect(uiBorderImage->verticalStretchRadioButton, SIGNAL(toggled(bool)), this, SLOT(onVerticalStretchChanged())); + connect(uiBorderImage->verticalTileRadioButtonNoCrop, SIGNAL(toggled(bool)), this, SLOT(onVerticalStretchChanged())); + + connect(uiBorderImage->horizontalTileRadioButton, SIGNAL(toggled(bool)), this, SLOT(onHorizontalStretchChanged())); + connect(uiBorderImage->horizontalStretchRadioButton, SIGNAL(toggled(bool)), this, SLOT(onHorizontalStretchChanged())); + connect(uiBorderImage->horizontalTileRadioButtonNoCrop, SIGNAL(toggled(bool)), this, SLOT(onHorizontalStretchChanged())); + connect(previewDialog()->previewLabel(), SIGNAL(leftMarginChanged()), this, SLOT(onLeftMarginsChanged())); + connect(previewDialog()->previewLabel(), SIGNAL(rightMarginChanged()), this, SLOT(onRightMarginsChanged())); + connect(previewDialog()->previewLabel(), SIGNAL(topMarginChanged()), this, SLOT(onTopMarginsChanged())); + connect(previewDialog()->previewLabel(), SIGNAL(bottomMarginChanged()), this, SLOT(onBottomMarginsChanged())); + + } else { + ui = new Ui::ContextPaneWidgetImage; + ui->setupUi(this); + ui->label->setToolTip(tr("double click for preview")); + ui->label->installEventFilter(labelFilter); + m_fileWidget = ui->fileWidget; + m_sizeLabel = ui->sizeLabel; + + connect(ui->stretchRadioButton, SIGNAL(toggled(bool)), this, SLOT(onStretchChanged())); + connect(ui->tileRadioButton, SIGNAL(toggled(bool)), this, SLOT(onStretchChanged())); + connect(ui->horizontalStretchRadioButton, SIGNAL(toggled(bool)), this, SLOT(onStretchChanged())); + connect(ui->verticalStretchRadioButton, SIGNAL(toggled(bool)), this, SLOT(onStretchChanged())); + connect(ui->preserveAspectFitRadioButton, SIGNAL(toggled(bool)), this, SLOT(onStretchChanged())); + connect(ui->cropAspectFitRadioButton, SIGNAL(toggled(bool)), this, SLOT(onStretchChanged())); + } + previewDialog(); + m_fileWidget->setShowComboBox(true); + m_fileWidget->setFilter("*.png *.gif *.jpg"); + + connect(m_fileWidget, SIGNAL(fileNameChanged(QUrl)), this, SLOT(onFileNameChanged())); connect(labelFilter, SIGNAL(doubleClicked()), this, SLOT(onPixmapDoubleClicked())); + } ContextPaneWidgetImage::~ContextPaneWidgetImage() { - delete ui; + if (ui) + delete ui; + if (uiBorderImage) + delete uiBorderImage; } void ContextPaneWidgetImage::setProperties(QmlJS::PropertyReader *propertyReader) { + if (m_borderImage) { + if (propertyReader->hasProperty(QLatin1String("horizontalTileMode"))) { + QString fillMode = propertyReader->readProperty(QLatin1String("horizontalTileMode")).toString(); + if (fillMode.contains("BorderImage.")) + fillMode.remove("BorderImage."); + + uiBorderImage->horizontalStretchRadioButton->setChecked(true); - if (propertyReader->hasProperty(QLatin1String("fillMode"))) { - QString fillMode = propertyReader->readProperty(QLatin1String("fillMode")).toString(); - if (fillMode.contains("Image.")) - fillMode.remove("Image."); + if (fillMode == "Stretch") + uiBorderImage->horizontalStretchRadioButton->setChecked(true); + if (fillMode == "Repeat") + uiBorderImage->horizontalTileRadioButton->setChecked(true); + if (fillMode == "Round") + uiBorderImage->horizontalTileRadioButtonNoCrop->setChecked(true); + } else { + //uiBorderImage + uiBorderImage->horizontalStretchRadioButton->setChecked(true); + } + if (propertyReader->hasProperty(QLatin1String("verticalTileMode"))) { + QString fillMode = propertyReader->readProperty(QLatin1String("verticalTileMode")).toString(); + if (fillMode.contains("BorderImage.")) + fillMode.remove("BorderImage."); - ui->stretchRadioButton->setChecked(true); + uiBorderImage->verticalStretchRadioButton->setChecked(true); - if (fillMode == "Image.Tile" || fillMode == "Tile") - ui->tileRadioButton->setChecked(true); - if (fillMode == "Image.TileVertically" || fillMode == "TileVertically") - ui->horizontalStretchRadioButton->setChecked(true); - if (fillMode == "Image.TileHorizontally" || fillMode == "TileHorizontally") - ui->verticalStretchRadioButton->setChecked(true); - if (fillMode == "Image.PreserveAspectFit" || fillMode == "PreserveAspectFit") - ui->preserveAspectFitRadioButton->setChecked(true); - if (fillMode == "Image.PreserveAspectCrop" || fillMode == "PreserveAspectCrop") - ui->cropAspectFitRadioButton->setChecked(true); + if (fillMode == "Stretch") + uiBorderImage->verticalStretchRadioButton->setChecked(true); + if (fillMode == "Repeat") + uiBorderImage->verticalTileRadioButton->setChecked(true); + if (fillMode == "Round") + uiBorderImage->verticalTileRadioButtonNoCrop->setChecked(true); + } else { + //uiBorderImage + uiBorderImage->verticalStretchRadioButton->setChecked(true); + } } else { - ui->stretchRadioButton->setChecked(true); - } + if (propertyReader->hasProperty(QLatin1String("fillMode"))) { + QString fillMode = propertyReader->readProperty(QLatin1String("fillMode")).toString(); + if (fillMode.contains("Image.")) + fillMode.remove("Image."); + ui->stretchRadioButton->setChecked(true); + + if (fillMode == "Image.Tile" || fillMode == "Tile") + ui->tileRadioButton->setChecked(true); + if (fillMode == "Image.TileVertically" || fillMode == "TileVertically") + ui->horizontalStretchRadioButton->setChecked(true); + if (fillMode == "Image.TileHorizontally" || fillMode == "TileHorizontally") + ui->verticalStretchRadioButton->setChecked(true); + if (fillMode == "Image.PreserveAspectFit" || fillMode == "PreserveAspectFit") + ui->preserveAspectFitRadioButton->setChecked(true); + if (fillMode == "Image.PreserveAspectCrop" || fillMode == "PreserveAspectCrop") + ui->cropAspectFitRadioButton->setChecked(true); + } else { + ui->stretchRadioButton->setChecked(true); + } + } if (propertyReader->hasProperty(QLatin1String("source"))) { QString source = propertyReader->readProperty(QLatin1String("source")).toString(); - ui->fileWidget->setFileName(source); + m_fileWidget->setFileName(source); if (QFile::exists(m_path + '/' + source)) setPixmap(m_path + '/' + source); else setPixmap(source); } else { - ui->sizeLabel->setText(""); + m_sizeLabel->setText(""); } } void ContextPaneWidgetImage::setPath(const QString& path) { m_path = path; - ui->fileWidget->setPath(QUrl::fromLocalFile(m_path)); + m_fileWidget->setPath(QUrl::fromLocalFile(m_path)); +} + +void PreviewDialog::setZoom(int z) +{ + m_zoom = z; + m_label->setZoom(z); + setPixmap(m_pixmap, m_zoom); +} + +void PreviewDialog::setIsBorderImage(bool b) +{ + m_borderImage = b; + m_label->setIsBorderImage(b); +} + +PreviewLabel *PreviewDialog::previewLabel() const +{ + return m_label; } void ContextPaneWidgetImage::onStretchChanged() @@ -118,78 +220,189 @@ void ContextPaneWidgetImage::onStretchChanged() emit propertyChanged(QLatin1String("fillMode"), stretch); } +void ContextPaneWidgetImage::onHorizontalStretchChanged() +{ + QString stretch; + if (uiBorderImage->horizontalStretchRadioButton->isChecked()) + stretch = QLatin1String("BorderImage.Stretch"); + if (uiBorderImage->horizontalTileRadioButton->isChecked()) + stretch = QLatin1String("BorderImage.Repeat"); + if (uiBorderImage->horizontalTileRadioButtonNoCrop->isChecked()) + stretch = QLatin1String("BorderImage.Round"); + + if (stretch == QLatin1String("BorderImage.Stretch")) + emit removeProperty(QLatin1String("horizontalTileMode")); + else + emit propertyChanged(QLatin1String("horizontalTileMode"), stretch); +} + +void ContextPaneWidgetImage::onVerticalStretchChanged() +{ + QString stretch; + if (uiBorderImage->verticalStretchRadioButton->isChecked()) + stretch = QLatin1String("BorderImage.Stretch"); + if (uiBorderImage->verticalTileRadioButton->isChecked()) + stretch = QLatin1String("BorderImage.Repeat"); + if (uiBorderImage->verticalTileRadioButtonNoCrop->isChecked()) + stretch = QLatin1String("BorderImage.Round"); + + if (stretch == QLatin1String("BorderImage.Stretch")) + emit removeProperty(QLatin1String("verticalTileMode")); + else + emit propertyChanged(QLatin1String("verticalTileMode"), stretch); + +} + void ContextPaneWidgetImage::onFileNameChanged() { - if (ui->fileWidget->fileName().isNull()) + if (m_fileWidget->fileName().isNull()) emit removeProperty(QLatin1String("source")); else - emit propertyChanged(QLatin1String("source"), QString(QLatin1Char('\"') + ui->fileWidget->fileName() + QLatin1Char('\"'))); + emit propertyChanged(QLatin1String("source"), QString(QLatin1Char('\"') + m_fileWidget->fileName() + QLatin1Char('\"'))); } void ContextPaneWidgetImage::onPixmapDoubleClicked() -{ - m_previewDialog->setParent(parentWidget()->parentWidget()); +{ + previewDialog()->setParent(parentWidget()->parentWidget()); + previewDialog()->setMaximumSize(previewDialog()->parentWidget()->size() - QSize(150, 100)); + if (m_borderImage) + previewDialog()->setZoom(4); + previewDialog()->setIsBorderImage(m_borderImage); + QPoint p = parentWidget()->pos(); - p = p + QPoint(-20, -20); - m_previewDialog->show(); - m_previewDialog->update(); - m_previewDialog->move(p); - m_previewDialog->resize(m_previewDialog->sizeHint()); - if ((m_previewDialog->pos().x() + m_previewDialog->width()) > m_previewDialog->parentWidget()->width()) - m_previewDialog->move(m_previewDialog->parentWidget()->width() - (m_previewDialog->width()) - 40, p.y()); + p = p + QPoint(-2, -2); + previewDialog()->show(); + previewDialog()->update(); + previewDialog()->move(p); + //previewDialog()->adjustSize(); + if ((previewDialog()->pos().x() + previewDialog()->width()) > previewDialog()->parentWidget()->width()) + previewDialog()->move(previewDialog()->parentWidget()->width() - (previewDialog()->width()) - 40, p.y()); + + if ((previewDialog()->pos().y() + previewDialog()->height()) > previewDialog()->parentWidget()->height()) + previewDialog()->move(previewDialog()->pos().x(), previewDialog()->parentWidget()->height() - (previewDialog()->height()) - 40); + + if (previewDialog()->pos().x() < 0) + previewDialog()->move(0, previewDialog()->pos().y()); + if (previewDialog()->pos().y() < 0) + previewDialog()->move(previewDialog()->pos().x(), 0); + + previewDialog()->raise(); +} + +void ContextPaneWidgetImage::onLeftMarginsChanged() +{ + if (previewDialog()->previewLabel()->leftMarging()) + propertyChanged(QLatin1String("border.left"), previewDialog()->previewLabel()->leftMarging()); + else + emit removeProperty(QLatin1String("border.left")); +} + +void ContextPaneWidgetImage::onRightMarginsChanged() +{ + if (previewDialog()->previewLabel()->rightMarging()) + propertyChanged(QLatin1String("border.right"), previewDialog()->previewLabel()->rightMarging()); + else + emit removeProperty(QLatin1String("border.right")); - if ((m_previewDialog->pos().y() + m_previewDialog->height()) > m_previewDialog->parentWidget()->height()) - m_previewDialog->move(m_previewDialog->pos().x(), m_previewDialog->parentWidget()->height() - (m_previewDialog->height()) - 40); - if (m_previewDialog->pos().x() < 0) - m_previewDialog->move(0, m_previewDialog->pos().y()); - if (m_previewDialog->pos().y() < 0) - m_previewDialog->move(m_previewDialog->pos().x(), 0); +} + +void ContextPaneWidgetImage::onTopMarginsChanged() +{ + if (previewDialog()->previewLabel()->topMarging()) + propertyChanged(QLatin1String("border.top"), previewDialog()->previewLabel()->topMarging()); + else + emit removeProperty(QLatin1String("border.top")); +} + +void ContextPaneWidgetImage::onBottomMarginsChanged() +{ + if (previewDialog()->previewLabel()->bottomMarging()) + propertyChanged(QLatin1String("border.bottom"), previewDialog()->previewLabel()->bottomMarging()); + else + emit removeProperty(QLatin1String("border.bottom")); - m_previewDialog->raise(); } + void ContextPaneWidgetImage::setPixmap(const QString &fileName) { QPixmap pix(76,76); pix.fill(Qt::black); - if (QFile(fileName).exists()) { - QPixmap source(fileName); - m_previewDialog->setPixmap(source); - ui->sizeLabel->setText(QString::number(source.width()) + 'x' + QString::number(source.height())); - QPainter p(&pix); - if (ui->stretchRadioButton->isChecked()) { - p.drawPixmap(0,0,76,76, source); - } else if (ui->tileRadioButton->isChecked()) { - QPixmap small = source.scaled(38,38); - p.drawTiledPixmap(0,0,76,76, small); - } else if (ui->horizontalStretchRadioButton->isChecked()) { - QPixmap small = source.scaled(38,38); - QPixmap half = pix.scaled(38, 76); - QPainter p2(&half); - p2.drawTiledPixmap(0,0,38,76, small); - p.drawPixmap(0,0,76,76, half); - } else if (ui->verticalStretchRadioButton->isChecked()) { - QPixmap small = source.scaled(38,38); - QPixmap half = pix.scaled(76, 38); - QPainter p2(&half); - p2.drawTiledPixmap(0,0,76,38, small); - p.drawPixmap(0,0,76,76, half); - } else if (ui->preserveAspectFitRadioButton->isChecked()) { - QPixmap preserved = source.scaledToWidth(76); - int offset = (76 - preserved.height()) / 2; - p.drawPixmap(0, offset, 76, preserved.height(), source); - } else if (ui->cropAspectFitRadioButton->isChecked()) { - QPixmap cropped = source.scaledToHeight(76); - int offset = (76 - cropped.width()) / 2; - p.drawPixmap(offset, 0, cropped.width(), 76, source); + if (m_borderImage) { + if (QFile(fileName).exists()) { + QPixmap source(fileName); + previewDialog()->setPixmap(source, previewDialog()->zoom()); + uiBorderImage->sizeLabel->setText(QString::number(source.width()) + 'x' + QString::number(source.height())); + QPainter p(&pix); + Qt::TileRule horizontalTileMode = Qt::StretchTile; + Qt::TileRule verticalTileMode = Qt::StretchTile; + if (uiBorderImage->horizontalTileRadioButton->isChecked()) + horizontalTileMode =Qt::RepeatTile; + if (uiBorderImage->horizontalTileRadioButtonNoCrop->isChecked()) + horizontalTileMode =Qt::RoundTile; + if (uiBorderImage->verticalTileRadioButton->isChecked()) + verticalTileMode =Qt::RepeatTile; + if (uiBorderImage->verticalTileRadioButtonNoCrop->isChecked()) + verticalTileMode =Qt::RoundTile; + QTileRules rules(horizontalTileMode, verticalTileMode); + QMargins margins(previewDialog()->previewLabel()->leftMarging() ,previewDialog()->previewLabel()->topMarging() ,previewDialog()->previewLabel()->rightMarging(), previewDialog()->previewLabel()->bottomMarging()); + qDrawBorderPixmap(&p, QRect(0, 0, 76, 76), margins, source, source.rect(), margins, rules); + //p.drawPixmap(0,0,76,76, source); + } else { + uiBorderImage->sizeLabel->setText(""); } + uiBorderImage->label->setPixmap(pix); } else { - ui->sizeLabel->setText(""); + if (QFile(fileName).exists()) { + QPixmap source(fileName); + previewDialog()->setPixmap(source, 1); + ui->sizeLabel->setText(QString::number(source.width()) + 'x' + QString::number(source.height())); + QPainter p(&pix); + if (ui->stretchRadioButton->isChecked()) { + p.drawPixmap(0,0,76,76, source); + } else if (ui->tileRadioButton->isChecked()) { + QPixmap small = source.scaled(38,38); + p.drawTiledPixmap(0,0,76,76, small); + } else if (ui->horizontalStretchRadioButton->isChecked()) { + QPixmap small = source.scaled(38,38); + QPixmap half = pix.scaled(38, 76); + QPainter p2(&half); + p2.drawTiledPixmap(0,0,38,76, small); + p.drawPixmap(0,0,76,76, half); + } else if (ui->verticalStretchRadioButton->isChecked()) { + QPixmap small = source.scaled(38,38); + QPixmap half = pix.scaled(76, 38); + QPainter p2(&half); + p2.drawTiledPixmap(0,0,76,38, small); + p.drawPixmap(0,0,76,76, half); + } else if (ui->preserveAspectFitRadioButton->isChecked()) { + QPixmap preserved = source.scaledToWidth(76); + int offset = (76 - preserved.height()) / 2; + p.drawPixmap(0, offset, 76, preserved.height(), source); + } else if (ui->cropAspectFitRadioButton->isChecked()) { + QPixmap cropped = source.scaledToHeight(76); + int offset = (76 - cropped.width()) / 2; + p.drawPixmap(offset, 0, cropped.width(), 76, source); + } + } else { + ui->sizeLabel->setText(""); + } + + ui->label->setPixmap(pix); + + } +} + +PreviewDialog* ContextPaneWidgetImage::previewDialog() +{ + if (!m_previewDialog) { + m_previewDialog = new PreviewDialog(this); + m_previewDialog->hide(); } - ui->label->setPixmap(pix); + return m_previewDialog.data(); } void ContextPaneWidgetImage::changeEvent(QEvent *e) @@ -204,29 +417,324 @@ void ContextPaneWidgetImage::changeEvent(QEvent *e) } } + +void ContextPaneWidgetImage::hideEvent(QHideEvent * event) +{ + previewWasVisible = previewDialog()->isVisible(); + previewDialog()->hide(); + QWidget::hideEvent(event); +} + +void ContextPaneWidgetImage::showEvent(QShowEvent* event) +{ + if (previewWasVisible) + previewDialog()->show(); + QWidget::showEvent(event); +} + +PreviewLabel::PreviewLabel(QWidget *parent) : QLabel(parent), m_dragging_top(false), m_dragging_bottom(false), + m_dragging_left(false), m_dragging_right(false) +{ + m_zoom = 1; + m_showBorders = false; + m_left = 2; + m_right = 2; + m_top = 2; + m_bottom = 2; + setMouseTracking(true); + setCursor(QCursor(Qt::ArrowCursor)); +} + +void PreviewLabel::setZoom(int z) +{ + m_zoom = z; +} + +void PreviewLabel::setIsBorderImage(bool b) +{ + m_borderImage = b; +} + +void PreviewLabel::setMargins(int left, int top, int right, int bottom) +{ + m_left = left; + m_top = top; + m_right = right; + m_bottom = bottom; +} + +void PreviewLabel::paintEvent(QPaintEvent *event) +{ + QLabel::paintEvent(event); + if (m_borderImage) { + + QPainter p(this); + + p.setOpacity(0.5); + + p.setBackgroundMode(Qt::TransparentMode); + { + QPen pen(Qt::SolidLine); + pen.setColor("#F0F0F0"); + p.setPen(pen); + + p.drawLine(m_left * m_zoom, 4, m_left * m_zoom, height() - 4); + p.drawLine(width() - m_right * m_zoom, 4, width() - m_right * m_zoom, height() - 4); + + p.drawLine(4, m_top * m_zoom, width() - 4, m_top * m_zoom); + p.drawLine(4, height() - m_bottom * m_zoom, width() - 4, height() - m_bottom * m_zoom); + } + + { + QBrush brush(Qt::Dense4Pattern); + brush.setColor("#101010"); + QPen pen(brush, 1, Qt::DotLine); + pen.setColor("#101010"); + p.setPen(pen); + + p.drawLine(m_left * m_zoom, 4, m_left * m_zoom, height() - 4); + p.drawLine(width() - m_right * m_zoom, 4, width() - m_right * m_zoom, height() - 4); + + p.drawLine(4, m_top * m_zoom, width() - 4, m_top * m_zoom); + p.drawLine(4, height() - m_bottom * m_zoom, width() - 4, height() - m_bottom * m_zoom); + } + } +} + +static inline bool rangeCheck(int target, int pos) +{ + return (target - 10 < pos) && (target + 10 > pos); +} + +void PreviewLabel::mousePressEvent(QMouseEvent * event) +{ + if (!m_borderImage) + return QLabel::mouseMoveEvent(event); + + if (event->button() == Qt::LeftButton) { + if (QApplication::overrideCursor()) + QApplication::restoreOverrideCursor(); + if (rangeCheck(m_left * m_zoom, event->pos().x())) { + QApplication::setOverrideCursor(QCursor(Qt::SizeHorCursor)); + m_dragging_left = true; + event->accept(); + } else if (rangeCheck(m_top * m_zoom, event->pos().y())) { + QApplication::setOverrideCursor(QCursor(Qt::SizeVerCursor)); + m_dragging_top = true; + event->accept(); + } else if (rangeCheck(m_right * m_zoom, width() - event->pos().x())) { + QApplication::setOverrideCursor(QCursor(Qt::SizeHorCursor)); + m_dragging_right = true; + event->accept(); + } else if (rangeCheck(m_bottom * m_zoom, height() - event->pos().y())) { + QApplication::setOverrideCursor(QCursor(Qt::SizeVerCursor)); + m_dragging_bottom = true; + event->accept(); + } else { + QLabel::mousePressEvent(event); + } + m_startPos = event->pos(); + } +} + +void PreviewLabel::mouseReleaseEvent(QMouseEvent * event) +{ + if (!m_borderImage) + return QLabel::mouseMoveEvent(event); + + if (m_dragging_left || m_dragging_top || m_dragging_right|| m_dragging_bottom) { + + if (m_dragging_left) + emit leftMarginChanged(); + + if (m_dragging_top) + emit topMarginChanged(); + + if (m_dragging_bottom) + emit bottomMarginChanged(); + + if (m_dragging_right) + emit rightMarginChanged(); + + m_dragging_left = false; + m_dragging_top = false; + m_dragging_right = false; + m_dragging_bottom = false; + QApplication::restoreOverrideCursor(); + event->accept(); + + } else { + QLabel::mouseReleaseEvent(event); + } +} + + +static inline int limit(int i, int zoom) +{ + static bool flag1 = 1; + static bool flag2 = 1; + if (zoom == 1) + return i; + if (i < 0) { + int v = i / zoom; + if (v) + return v; + if (zoom == 2) { + flag1 =!flag1; + return flag1 ? -1 : 0; + } + flag1 =!flag1; + if (flag1) + flag2 =!flag2; + + return flag1 && flag2 ? -1 : 0; + } + if (i > 0) { + int v = i / zoom; + if (v) + return v; + if (zoom == 2) { + flag1 =!flag1; + return flag1 ? 1 : 0; + } + flag1 =!flag1; + if (flag1) + flag2 =!flag2; + + return flag1 && flag2 ? 1 : 0; + } + return 0; +} + +void PreviewLabel::mouseMoveEvent(QMouseEvent * event) +{ + if (!m_borderImage) + return QLabel::mouseMoveEvent(event); + + QPoint p = event->pos(); + if (m_dragging_left) { + m_left += limit(p.x() - m_startPos.x(), m_zoom); + event->accept(); + update(); + } else if (m_dragging_top) { + m_top += limit(p.y() - m_startPos.y(), m_zoom); + event->accept(); + update(); + } else if (m_dragging_right) { + m_right += limit(m_startPos.x() - p.x(), m_zoom); + event->accept(); + update(); + } else if (m_dragging_bottom) { + m_bottom += limit(m_startPos.y() - p.y(), m_zoom); + event->accept(); + update(); + } else if (rangeCheck(m_left * m_zoom, p.x())) { + QApplication::setOverrideCursor(QCursor(Qt::SizeHorCursor)); + event->accept(); + } else if (rangeCheck(m_top * m_zoom, p.y())) { + QApplication::setOverrideCursor(QCursor(Qt::SizeVerCursor)); + event->accept(); + } else if (rangeCheck(m_right * m_zoom, width() - p.x())) { + QApplication::setOverrideCursor(QCursor(Qt::SizeHorCursor)); + event->accept(); + } else if (rangeCheck(m_bottom * m_zoom, height() - p.y())) { + QApplication::setOverrideCursor(QCursor(Qt::SizeVerCursor)); + event->accept(); + } else { + if (QApplication::overrideCursor()) + QApplication::restoreOverrideCursor(); + QLabel::mouseMoveEvent(event); + } + m_startPos = p; +} + +void PreviewLabel::leaveEvent(QEvent* event ) +{ + while (QApplication::overrideCursor()) + QApplication::restoreOverrideCursor(); + QLabel::leaveEvent(event); +} + PreviewDialog::PreviewDialog(QWidget *parent) : DragWidget(parent) { + m_zoom = 1; + m_borderImage = false; setAutoFillBackground(true); - m_label = new QLabel(this); + m_label = new PreviewLabel(this); + m_slider = new QSlider(this); QGridLayout *layout = new QGridLayout(this); layout->setMargin(0); - layout->setContentsMargins(1, 1, 1, 1); - layout->setSpacing(0); + layout->setContentsMargins(2, 2, 2, 6); + layout->setSpacing(4); QToolButton *toolButton = new QToolButton(this); QIcon icon(style()->standardIcon(QStyle::SP_DockWidgetCloseButton)); toolButton->setIcon(icon); toolButton->setToolButtonStyle(Qt::ToolButtonIconOnly); toolButton->setFixedSize(icon.availableSizes().value(0) + QSize(4, 4)); connect(toolButton, SIGNAL(clicked()), this, SLOT(onTogglePane())); - layout->addWidget(toolButton, 0, 0, 1, 1); - layout->addWidget(m_label, 0, 1, 2, 2); + layout->addWidget(toolButton, 0, 0, 1, 1); + + QScrollArea *scrollArea = new QScrollArea(this); + WheelFilter *wheelFilter = new WheelFilter(scrollArea); + //scrollArea->installEventFilter(wheelFilter); + scrollArea->setWidget(m_label); + scrollArea->setFrameStyle(QFrame::NoFrame); + m_slider->setOrientation(Qt::Horizontal); + m_slider->setMaximumWidth(120); + //layout->addItem(new QSpacerItem(10, 10), 0, 1, 1, 1); + layout->addWidget(m_slider, 0, 1, 1, 2); + layout->addWidget(scrollArea, 1, 1, 2, 2); + + wheelFilter->setTarget(this); + + foreach (QWidget *childWidget, findChildren<QWidget*>()) { + childWidget->installEventFilter(wheelFilter); + } } -void PreviewDialog::setPixmap(const QPixmap &p) +void PreviewDialog::setPixmap(const QPixmap &p, int zoom) { - m_label->setPixmap(p); + m_pixmap = p; + m_label->setPixmap(p.scaled(p.width() * zoom, p.height() * zoom)); + m_label->adjustSize(); + m_zoom = zoom; + m_label->setZoom(m_zoom); + QSize size = m_label->pixmap()->size() + QSize(44, 44); + if (size.width() < 140) + size.setWidth(140); + resize(size); +} + +void PreviewDialog::wheelEvent(QWheelEvent* event) +{ + int delta = event->delta(); + event->accept(); + if (delta > 0) { + if (m_zoom == 1) + m_zoom = 2; + else if (m_zoom == 2) + m_zoom = 4; + else if (m_zoom == 4) + m_zoom = 6; + else if (m_zoom == 6) + m_zoom = 8; + else if (m_zoom == 8) + m_zoom = 10; + } else { + if (m_zoom == 10) + m_zoom = 8; + else if (m_zoom == 8) + m_zoom = 6; + else if (m_zoom == 6) + m_zoom = 4; + else if (m_zoom == 4) + m_zoom = 2; + else if (m_zoom == 2) + m_zoom = 1; + } + setPixmap(m_pixmap, m_zoom); } void PreviewDialog::onTogglePane() diff --git a/src/plugins/qmldesigner/components/propertyeditor/contextpanewidgetimage.h b/src/plugins/qmldesigner/components/propertyeditor/contextpanewidgetimage.h index 4ac9ed915e03f787e7972e551284d6857ada3912..b0bd4179e4e2209f6c5c999fa6599039f6d04d74 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/contextpanewidgetimage.h +++ b/src/plugins/qmldesigner/components/propertyeditor/contextpanewidgetimage.h @@ -3,20 +3,63 @@ #include <QWidget> #include <QFrame> +#include <QLabel> +#include <qdrawutil.h> #include <contextpanewidget.h> QT_BEGIN_NAMESPACE namespace Ui { class ContextPaneWidgetImage; + class ContextPaneWidgetBorderImage; } class QLabel; +class QSlider; +class FileWidget; QT_END_NAMESPACE namespace QmlJS { class PropertyReader; } -namespace QmlDesigner { +namespace QmlDesigner { + +class PreviewLabel : public QLabel +{ + Q_OBJECT + +public: + PreviewLabel(QWidget *parent = 0); + void setZoom(int); + void setIsBorderImage(bool b); + void setMargins(int left, int top, int right, int bottom); + int leftMarging() const { return m_left; } + int topMarging() const { return m_top; } + int rightMarging() const { return m_right; } + int bottomMarging() const { return m_bottom; } + +signals: + void leftMarginChanged(); + void topMarginChanged(); + void bottomMarginChanged(); + void rightMarginChanged(); + +protected: + void paintEvent(QPaintEvent *event); + void mousePressEvent(QMouseEvent * event); + void mouseReleaseEvent(QMouseEvent * event); + void mouseMoveEvent(QMouseEvent * event); + void leaveEvent(QEvent* event ); +private: + bool m_showBorders; + int m_left, m_right, m_top, m_bottom; + bool m_dragging_left; + bool m_dragging_right; + bool m_dragging_top; + bool m_dragging_bottom; + QPoint m_startPos; + int m_zoom; + bool m_borderImage; +}; class PreviewDialog : public DragWidget { @@ -24,12 +67,24 @@ class PreviewDialog : public DragWidget public: PreviewDialog(QWidget *parent = 0); - void setPixmap(const QPixmap &p); + void setPixmap(const QPixmap &p, int zoom = 1); + void setZoom(int z); + void setIsBorderImage(bool b); + PreviewLabel *previewLabel() const; + int zoom() { return m_zoom; } + public slots: void onTogglePane(); +protected: + void wheelEvent(QWheelEvent* event); + private: - QLabel * m_label; + PreviewLabel *m_label; + QSlider *m_slider; + int m_zoom; + QPixmap m_pixmap; + bool m_borderImage; }; class ContextPaneWidgetImage : public QWidget @@ -37,10 +92,11 @@ class ContextPaneWidgetImage : public QWidget Q_OBJECT public: - explicit ContextPaneWidgetImage(QWidget *parent = 0); + explicit ContextPaneWidgetImage(QWidget *parent = 0, bool borderImage = false); ~ContextPaneWidgetImage(); void setProperties(QmlJS::PropertyReader *propertyReader); - void setPath(const QString& path); + void setPath(const QString& path); + PreviewDialog* previewDialog(); signals: void propertyChanged(const QString &, const QVariant &); @@ -49,17 +105,30 @@ signals: public slots: void onStretchChanged(); + void onVerticalStretchChanged(); + void onHorizontalStretchChanged(); void onFileNameChanged(); void onPixmapDoubleClicked(); void setPixmap(const QString &fileName); + void onLeftMarginsChanged(); + void onTopMarginsChanged(); + void onBottomMarginsChanged(); + void onRightMarginsChanged(); protected: void changeEvent(QEvent *e); + void hideEvent(QHideEvent* event); + void showEvent(QShowEvent* event); private: Ui::ContextPaneWidgetImage *ui; + Ui::ContextPaneWidgetBorderImage *uiBorderImage; QString m_path; - PreviewDialog *m_previewDialog; + QWeakPointer<PreviewDialog> m_previewDialog; + FileWidget *m_fileWidget; + QLabel *m_sizeLabel; + bool m_borderImage; + bool previewWasVisible; }; class LabelFilter: public QObject { @@ -73,6 +142,18 @@ protected: bool eventFilter(QObject *obj, QEvent *event); }; +class WheelFilter: public QObject { + + Q_OBJECT +public: + WheelFilter(QObject* parent =0) : QObject(parent) {} + void setTarget(QObject *target) { m_target = target; } +protected: + bool eventFilter(QObject *obj, QEvent *event); + QObject *m_target; +}; + +