Commit 7620746e authored by Thomas Hartmann's avatar Thomas Hartmann
Browse files

QmlDesigner.propertyEditor: adding new classes and forms

adding panes for Image and Rectangle
parent 479bcbd5
#include "contextpanewidgetimage.h"
#include "ui_contextpanewidgetimage.h"
#include <qmljs/qmljspropertyreader.h>
#include <QFile>
#include <QPixmap>
#include <QPainter>
namespace QmlDesigner {
ContextPaneWidgetImage::ContextPaneWidgetImage(QWidget *parent) :
QWidget(parent),
ui(new Ui::ContextPaneWidgetImage)
{
ui->setupUi(this);
ui->fileWidget->setShowComboBox(true);
ui->fileWidget->setFilter("*.png *.gif *.jpg");
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()));
}
ContextPaneWidgetImage::~ContextPaneWidgetImage()
{
delete ui;
}
void ContextPaneWidgetImage::setProperties(QmlJS::PropertyReader *propertyReader)
{
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 == "Tile")
ui->tileRadioButton->setChecked(true);
if (fillMode == "TileVertically")
ui->horizontalStretchRadioButton->setChecked(true);
if (fillMode == "TileHorizontally")
ui->verticalStretchRadioButton->setChecked(true);
if (fillMode == "PreserveAspectFit")
ui->preserveAspectFitRadioButton->setChecked(true);
if (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);
setPixmap(m_path + '/' + source);
}
}
void ContextPaneWidgetImage::setPath(const QString& path)
{
m_path = path;
ui->fileWidget->setPath(QUrl::fromLocalFile(m_path));
}
void ContextPaneWidgetImage::onStretchChanged()
{
QString stretch;
if (ui->stretchRadioButton->isChecked())
stretch = QLatin1String("Stretch");
else if (ui->tileRadioButton->isChecked())
stretch = QLatin1String("Tile");
else if (ui->horizontalStretchRadioButton->isChecked())
stretch = QLatin1String("TileVertically");
else if (ui->verticalStretchRadioButton->isChecked())
stretch = QLatin1String("TileHorizontally");
else if (ui->preserveAspectFitRadioButton->isChecked())
stretch = QLatin1String("PreserveAspectFit");
else if (ui->cropAspectFitRadioButton->isChecked())
stretch = QLatin1String("PreserveAspectCrop");
if (stretch == QLatin1String("Stretch"))
emit removeProperty(QLatin1String("fillMode"));
else
emit propertyChanged(QLatin1String("fillMode"), stretch);
}
void ContextPaneWidgetImage::onFileNameChanged()
{
if (ui->fileWidget->fileName().isNull())
emit removeProperty(QLatin1String("source"));
else
emit propertyChanged(QLatin1String("source"), QString(QLatin1Char('\"') + ui->fileWidget->fileName() + QLatin1Char('\"')));
}
void ContextPaneWidgetImage::setPixmap(const QString &fileName)
{
QPixmap pix(76,76);
pix.fill(Qt::black);
if (QFile(fileName).exists()) {
QPixmap source(fileName);
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);
}
}
ui->label->setPixmap(pix);
}
void ContextPaneWidgetImage::changeEvent(QEvent *e)
{
QWidget::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
ui->retranslateUi(this);
break;
default:
break;
}
}
} //QmlDesigner
#ifndef CONTEXTPANEWIDGETIMAGE_H
#define CONTEXTPANEWIDGETIMAGE_H
#include <QWidget>
namespace Ui {
class ContextPaneWidgetImage;
}
namespace QmlJS {
class PropertyReader;
}
namespace QmlDesigner {
class ContextPaneWidgetImage : public QWidget
{
Q_OBJECT
public:
explicit ContextPaneWidgetImage(QWidget *parent = 0);
~ContextPaneWidgetImage();
void setProperties(QmlJS::PropertyReader *propertyReader);
void setPath(const QString& path);
signals:
void propertyChanged(const QString &, const QVariant &);
void removeProperty(const QString &);
void removeAndChangeProperty(const QString &, const QString &, const QVariant &, bool removeFirst);
public slots:
void onStretchChanged();
void onFileNameChanged();
void setPixmap(const QString &fileName);
protected:
void changeEvent(QEvent *e);
private:
Ui::ContextPaneWidgetImage *ui;
QString m_path;
};
} //QmlDesigner
#endif // CONTEXTPANEWIDGETIMAGE_H
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ContextPaneWidgetImage</class>
<widget class="QWidget" name="ContextPaneWidgetImage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>290</width>
<height>84</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="horizontalSpacing">
<number>6</number>
</property>
<property name="verticalSpacing">
<number>0</number>
</property>
<property name="margin">
<number>4</number>
</property>
<item row="0" column="1" colspan="3">
<widget class="FileWidget" name="fileWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>200</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QRadioButton" name="stretchRadioButton">
<property name="toolTip">
<string>The image is scaled to fit</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../resources/resources.qrc">
<normaloff>:/qmldesigner/images/scale-icon.png</normaloff>:/qmldesigner/images/scale-icon.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QRadioButton" name="horizontalStretchRadioButton">
<property name="toolTip">
<string>The image is stretched horizontally and tiled vertically</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../resources/resources.qrc">
<normaloff>:/qmldesigner/images/horizontal-scale-icon.png</normaloff>:/qmldesigner/images/horizontal-scale-icon.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QRadioButton" name="verticalStretchRadioButton">
<property name="toolTip">
<string>The image is stretched vertically and tiled horizontally</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../resources/resources.qrc">
<normaloff>:/qmldesigner/images/vertical-scale-icon.png</normaloff>:/qmldesigner/images/vertical-scale-icon.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QRadioButton" name="tileRadioButton">
<property name="toolTip">
<string>The image is duplicated horizontally and vertically</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../resources/resources.qrc">
<normaloff>:/qmldesigner/images/tile-icon.png</normaloff>:/qmldesigner/images/tile-icon.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QRadioButton" name="preserveAspectFitRadioButton">
<property name="toolTip">
<string>The image is scaled uniformly to fit without cropping</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../resources/resources.qrc">
<normaloff>:/qmldesigner/images/aspect-fit-icon.png</normaloff>:/qmldesigner/images/aspect-fit-icon.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QRadioButton" name="cropAspectFitRadioButton">
<property name="toolTip">
<string>The image is scaled uniformly to fill, cropping if necessary</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../resources/resources.qrc">
<normaloff>:/qmldesigner/images/aspect-crop-icon.png</normaloff>:/qmldesigner/images/aspect-crop-icon.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
<item row="0" column="0" rowspan="3">
<widget class="QLabel" name="label">
<property name="minimumSize">
<size>
<width>76</width>
<height>76</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>76</width>
<height>76</height>
</size>
</property>
<property name="palette">
<palette>
<active>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>57</red>
<green>57</green>
<blue>57</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>57</red>
<green>57</green>
<blue>57</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>57</red>
<green>57</green>
<blue>57</blue>
</color>
</brush>
</colorrole>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>57</red>
<green>57</green>
<blue>57</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>FileWidget</class>
<extends>QComboBox</extends>
<header location="global">filewidget.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../resources/resources.qrc"/>
</resources>
<connections/>
</ui>
#include "contextpanewidgetrectangle.h"
#include "ui_contextpanewidgetrectangle.h"
#include "contextpanewidget.h"
#include <qmljs/qmljspropertyreader.h>
#include <QDebug>
namespace QmlDesigner {
ContextPaneWidgetRectangle::ContextPaneWidgetRectangle(QWidget *parent) :
QWidget(parent),
ui(new Ui::ContextPaneWidgetRectangle),
m_gradientLineDoubleClicked(false),
m_gradientTimer(-1)
{
ui->setupUi(this);
ui->colorColorButton->setShowArrow(false);
ui->borderColorButton->setShowArrow(false);
connect(ui->colorColorButton, SIGNAL(toggled(bool)), this, SLOT(onColorButtonToggled(bool)));
connect(ui->borderColorButton, SIGNAL(toggled(bool)), this, SLOT(onBorderColorButtonToggled(bool)));
connect(ui->colorSolid, SIGNAL(clicked()), this, SLOT(onColorSolidClicked()));
connect(ui->borderSolid, SIGNAL(clicked()), this, SLOT(onBorderSolidClicked()));
connect(ui->colorNone, SIGNAL(clicked()), this, SLOT(onColorNoneClicked()));
connect(ui->borderNone, SIGNAL(clicked()), this, SLOT(onBorderNoneClicked()));
connect(ui->colorGradient, SIGNAL(clicked()), this, SLOT(onGradientClicked()));
ContextPaneWidget *parentContextWidget = qobject_cast<ContextPaneWidget*>(parentWidget());
connect(parentContextWidget->colorDialog(), SIGNAL(accepted(QColor)), this, SLOT(onColorDialogApplied(QColor)));
connect(parentContextWidget->colorDialog(), SIGNAL(rejected()), this, SLOT(onColorDialogCancled()));
connect(ui->gradientLine, SIGNAL(openColorDialog(QPoint)), this, SLOT(onGradientLineDoubleClicked(QPoint)));
connect(ui->gradientLine, SIGNAL(gradientChanged()), this, SLOT(onUpdateGradient()));
}
ContextPaneWidgetRectangle::~ContextPaneWidgetRectangle()
{
delete ui;
}
void ContextPaneWidgetRectangle::setProperties(QmlJS::PropertyReader *propertyReader)
{
m_hasGradient = propertyReader->hasProperty(QLatin1String("gradient"));
m_none = false;
m_hasBorder = false;
if (propertyReader->hasProperty(QLatin1String("color"))) {
QString str = propertyReader->readProperty("color").toString();
if (QColor(str).alpha() == 0)
m_none = true;
ui->colorColorButton->setColor(str);
} else {
ui->colorColorButton->setColor(QLatin1String("black"));
}
if (propertyReader->hasProperty(QLatin1String("border.color"))) {
ui->borderColorButton->setColor(propertyReader->readProperty("border.color").toString());
m_hasBorder = true;
} else {
ui->borderColorButton->setColor(QLatin1String("black"));
}
if (propertyReader->hasProperty(QLatin1String("border.width")))
m_hasBorder = true;
ui->colorSolid->setChecked(true);
ui->borderNone->setChecked(true);
ui->borderSolid->setChecked(m_hasBorder);
if (m_none)
ui->colorNone->setChecked(true);
if (m_hasGradient) {
ui->colorGradient->setChecked(true);
ui->gradientLine->setEnabled(true);
ui->gradientLabel->setEnabled(true);
ui->gradientLine->setGradient(propertyReader->parseGradient("gradient"));
} else {
ui->gradientLine->setEnabled(false);
ui->gradientLabel->setEnabled(false);
}
if (m_gradientTimer > 0) {
killTimer(m_gradientTimer);
m_gradientTimer = -1;
}
}
void ContextPaneWidgetRectangle::onBorderColorButtonToggled(bool flag)
{
if (flag) {
ui->colorColorButton->setChecked(false);
m_gradientLineDoubleClicked = false;
}
ContextPaneWidget *parentContextWidget = qobject_cast<ContextPaneWidget*>(parentWidget());
QPoint p = mapToGlobal(ui->borderColorButton->pos());
parentContextWidget->colorDialog()->setupColor(ui->borderColorButton->color());
p = parentContextWidget->colorDialog()->parentWidget()->mapFromGlobal(p);
parentContextWidget->onShowColorDialog(flag, p);
}
void ContextPaneWidgetRectangle::onColorButtonToggled(bool flag )
{
if (flag) {
ui->borderColorButton->setChecked(false);
m_gradientLineDoubleClicked = false;
}