OSDN Git Service

It's 2011 now.
[qt-creator-jp/qt-creator-jp.git] / src / libs / qmleditorwidgets / contextpanewidgetimage.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
8 **
9 ** No Commercial Usage
10 **
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 **
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights.  These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
31 **
32 **************************************************************************/
33
34 #include "contextpanewidgetimage.h"
35 #include "ui_contextpanewidgetimage.h"
36 #include "ui_contextpanewidgetborderimage.h"
37 #include <qmljs/qmljspropertyreader.h>
38 #include <QFile>
39 #include <QFileInfo>
40 #include <QDir>
41 #include <QPixmap>
42 #include <QPainter>
43 #include <QGraphicsEffect>
44 #include <QMouseEvent>
45 #include <QScrollArea>
46 #include <QSlider>
47 #include <QDebug>
48
49 namespace QmlEditorWidgets {
50
51 bool LabelFilter::eventFilter(QObject *obj, QEvent *event)
52 {
53     if (event->type() == QEvent::MouseButtonDblClick) {
54         emit doubleClicked();
55         event->accept();
56         return true;
57     }    
58     return QObject::eventFilter(obj, event);
59 }
60
61 bool WheelFilter::eventFilter(QObject *obj, QEvent *event)
62 {
63     if (event->type() == QEvent::Wheel) {
64         if (obj
65             && obj->isWidgetType()
66             && obj != m_target) {
67             QApplication::sendEvent(m_target, event);
68             return true;
69         }
70     }
71     return QObject::eventFilter(obj, event);
72 }
73
74 ContextPaneWidgetImage::ContextPaneWidgetImage(QWidget *parent, bool borderImage) :
75     QWidget(parent),
76     ui(0), uiBorderImage(0), previewWasVisible(false)
77 {
78     LabelFilter *labelFilter = new LabelFilter(this);
79
80     m_borderImage = borderImage;
81
82     if (m_borderImage) {
83         uiBorderImage = new Ui::ContextPaneWidgetBorderImage;
84         uiBorderImage->setupUi(this);
85         m_fileWidget = uiBorderImage->fileWidget;
86         m_sizeLabel = uiBorderImage->sizeLabel;
87         uiBorderImage->label->setToolTip(tr("double click for preview"));
88         uiBorderImage->label->installEventFilter(labelFilter);
89
90
91         connect(uiBorderImage->verticalTileRadioButton,  SIGNAL(toggled(bool)), this, SLOT(onVerticalStretchChanged()));
92         connect(uiBorderImage->verticalStretchRadioButton,  SIGNAL(toggled(bool)), this, SLOT(onVerticalStretchChanged()));
93         connect(uiBorderImage->verticalTileRadioButtonNoCrop,  SIGNAL(toggled(bool)), this, SLOT(onVerticalStretchChanged()));
94
95         connect(uiBorderImage->horizontalTileRadioButton,  SIGNAL(toggled(bool)), this, SLOT(onHorizontalStretchChanged()));
96         connect(uiBorderImage->horizontalStretchRadioButton,  SIGNAL(toggled(bool)), this, SLOT(onHorizontalStretchChanged()));
97         connect(uiBorderImage->horizontalTileRadioButtonNoCrop, SIGNAL(toggled(bool)), this, SLOT(onHorizontalStretchChanged()));
98         connect(previewDialog()->previewLabel(), SIGNAL(leftMarginChanged()), this, SLOT(onLeftMarginsChanged()));
99         connect(previewDialog()->previewLabel(), SIGNAL(rightMarginChanged()), this, SLOT(onRightMarginsChanged()));
100         connect(previewDialog()->previewLabel(), SIGNAL(topMarginChanged()), this, SLOT(onTopMarginsChanged()));
101         connect(previewDialog()->previewLabel(), SIGNAL(bottomMarginChanged()), this, SLOT(onBottomMarginsChanged()));
102
103     } else {
104         ui = new Ui::ContextPaneWidgetImage;
105         ui->setupUi(this);
106         ui->label->setToolTip(tr("double click for preview"));
107         ui->label->installEventFilter(labelFilter);
108         m_fileWidget = ui->fileWidget;
109         m_sizeLabel = ui->sizeLabel;
110
111         connect(ui->stretchRadioButton, SIGNAL(toggled(bool)), this, SLOT(onStretchChanged()));
112         connect(ui->tileRadioButton, SIGNAL(toggled(bool)), this, SLOT(onStretchChanged()));
113         connect(ui->horizontalStretchRadioButton, SIGNAL(toggled(bool)), this, SLOT(onStretchChanged()));
114         connect(ui->verticalStretchRadioButton, SIGNAL(toggled(bool)), this, SLOT(onStretchChanged()));
115         connect(ui->preserveAspectFitRadioButton, SIGNAL(toggled(bool)), this, SLOT(onStretchChanged()));
116         connect(ui->cropAspectFitRadioButton, SIGNAL(toggled(bool)), this, SLOT(onStretchChanged()));        
117     }
118     previewDialog();
119     m_fileWidget->setShowComboBox(true);
120     m_fileWidget->setFilter("*.png *.gif *.jpg");
121
122     connect(m_fileWidget, SIGNAL(fileNameChanged(QUrl)), this, SLOT(onFileNameChanged()));
123     connect(labelFilter, SIGNAL(doubleClicked()), this, SLOT(onPixmapDoubleClicked()));
124
125 }
126
127 ContextPaneWidgetImage::~ContextPaneWidgetImage()
128 {
129     if (ui)
130         delete ui;
131     if (uiBorderImage)
132         delete uiBorderImage;
133 }
134
135 void ContextPaneWidgetImage::setProperties(QmlJS::PropertyReader *propertyReader)
136 {
137     if (m_borderImage) {
138
139         int leftBorder = 0;
140         int rightBorder = 0;
141         int topBorder = 0;
142         int bottomBorder = 0;
143
144         if (propertyReader->hasProperty(QLatin1String("border.left")))
145             leftBorder =propertyReader->readProperty(QLatin1String("border.left")).toInt();
146         if (propertyReader->hasProperty(QLatin1String("border.right")))
147             rightBorder =propertyReader->readProperty(QLatin1String("border.right")).toInt();
148         if (propertyReader->hasProperty(QLatin1String("border.top")))
149             topBorder =propertyReader->readProperty(QLatin1String("border.top")).toInt();
150         if (propertyReader->hasProperty(QLatin1String("border.bottom")))
151             bottomBorder =propertyReader->readProperty(QLatin1String("border.bottom")).toInt();
152         previewDialog()->previewLabel()->setMargins(leftBorder, topBorder, rightBorder, bottomBorder);
153
154         if (propertyReader->hasProperty(QLatin1String("horizontalTileMode"))) {
155             QString fillMode = propertyReader->readProperty(QLatin1String("horizontalTileMode")).toString();
156             if (fillMode.contains("BorderImage."))
157                 fillMode.remove("BorderImage.");
158
159             uiBorderImage->horizontalStretchRadioButton->setChecked(true);
160
161             if (fillMode == "Stretch")
162                 uiBorderImage->horizontalStretchRadioButton->setChecked(true);
163             if (fillMode == "Repeat")
164                 uiBorderImage->horizontalTileRadioButton->setChecked(true);
165             if (fillMode == "Round")
166                 uiBorderImage->horizontalTileRadioButtonNoCrop->setChecked(true);
167         } else {
168             //uiBorderImage
169             uiBorderImage->horizontalStretchRadioButton->setChecked(true);
170         }
171         if (propertyReader->hasProperty(QLatin1String("verticalTileMode"))) {
172             QString fillMode = propertyReader->readProperty(QLatin1String("verticalTileMode")).toString();
173             if (fillMode.contains("BorderImage."))
174                 fillMode.remove("BorderImage.");
175
176             uiBorderImage->verticalStretchRadioButton->setChecked(true);
177
178             if (fillMode == "Stretch")
179                 uiBorderImage->verticalStretchRadioButton->setChecked(true);
180             if (fillMode == "Repeat")
181                 uiBorderImage->verticalTileRadioButton->setChecked(true);
182             if (fillMode == "Round")
183                 uiBorderImage->verticalTileRadioButtonNoCrop->setChecked(true);
184         } else {
185             //uiBorderImage
186             uiBorderImage->verticalStretchRadioButton->setChecked(true);
187         }
188     } else {
189         if (propertyReader->hasProperty(QLatin1String("fillMode"))) {
190             QString fillMode = propertyReader->readProperty(QLatin1String("fillMode")).toString();
191             if (fillMode.contains("Image."))
192                 fillMode.remove("Image.");
193
194             ui->stretchRadioButton->setChecked(true);
195
196             if (fillMode == "Image.Tile" || fillMode == "Tile")
197                 ui->tileRadioButton->setChecked(true);
198             if (fillMode == "Image.TileVertically" || fillMode == "TileVertically")
199                 ui->horizontalStretchRadioButton->setChecked(true);
200             if (fillMode == "Image.TileHorizontally" || fillMode == "TileHorizontally")
201                 ui->verticalStretchRadioButton->setChecked(true);
202             if (fillMode == "Image.PreserveAspectFit" || fillMode == "PreserveAspectFit")
203                 ui->preserveAspectFitRadioButton->setChecked(true);
204             if (fillMode == "Image.PreserveAspectCrop" || fillMode == "PreserveAspectCrop")
205                 ui->cropAspectFitRadioButton->setChecked(true);
206         } else {
207             ui->stretchRadioButton->setChecked(true);
208         }        
209     }
210     if (propertyReader->hasProperty(QLatin1String("source"))) {
211         QString source = propertyReader->readProperty(QLatin1String("source")).toString();
212         m_fileWidget->setFileName(source);
213         if (QFile::exists(m_path + '/' + source))
214             setPixmap(m_path + '/' + source);
215         else
216             setPixmap(source);
217     } else {
218         m_sizeLabel->setText("");
219     }
220 }
221
222 void ContextPaneWidgetImage::setPath(const QString& path)
223 {
224     m_path = path;
225     m_fileWidget->setPath(QUrl::fromLocalFile(m_path));
226 }
227
228 void PreviewDialog::setZoom(int z)
229 {
230     m_zoom = z;
231     m_label->setZoom(z);
232     switch (m_zoom) {
233     case 1:
234         m_zoomLabel->setText("100%");
235         m_slider->setValue(1);
236         break;
237     case 2:
238         m_zoomLabel->setText("200%");
239         m_slider->setValue(2);
240         break;
241     case 4:
242         m_zoomLabel->setText("400%");
243         m_slider->setValue(3);
244         break;
245     case 6:
246         m_zoomLabel->setText("600%");
247         m_slider->setValue(4);
248         break;
249     case 8:
250         m_zoomLabel->setText("800%");
251         m_slider->setValue(5);
252         break;
253     case 10:
254         m_zoomLabel->setText("1000%");
255         m_slider->setValue(6);
256         break;
257     default: break;
258     }
259     setPixmap(m_pixmap, m_zoom);
260 }
261
262 void PreviewDialog::setIsBorderImage(bool b)
263 {
264     m_borderImage = b;
265     m_label->setIsBorderImage(b);
266 }
267
268 PreviewLabel *PreviewDialog::previewLabel() const
269 {
270     return m_label;
271 }
272
273 void ContextPaneWidgetImage::onStretchChanged()
274 {
275     QString stretch;
276     if (ui->stretchRadioButton->isChecked())
277         stretch = QLatin1String("Image.Stretch");
278     else if (ui->tileRadioButton->isChecked())
279         stretch = QLatin1String("Image.Tile");
280     else if (ui->horizontalStretchRadioButton->isChecked())
281         stretch = QLatin1String("Image.TileVertically");
282     else if (ui->verticalStretchRadioButton->isChecked())
283         stretch = QLatin1String("Image.TileHorizontally");
284     else if (ui->preserveAspectFitRadioButton->isChecked())
285         stretch = QLatin1String("Image.PreserveAspectFit");
286     else if (ui->cropAspectFitRadioButton->isChecked())
287         stretch = QLatin1String("Image.PreserveAspectCrop");
288
289     if (stretch == QLatin1String("Image.Stretch"))
290         emit removeProperty(QLatin1String("fillMode"));
291     else
292         emit propertyChanged(QLatin1String("fillMode"), stretch);
293 }
294
295 void ContextPaneWidgetImage::onHorizontalStretchChanged()
296 {
297     QString stretch;
298     if (uiBorderImage->horizontalStretchRadioButton->isChecked())
299         stretch = QLatin1String("BorderImage.Stretch");
300     if (uiBorderImage->horizontalTileRadioButton->isChecked())
301         stretch = QLatin1String("BorderImage.Repeat");
302     if (uiBorderImage->horizontalTileRadioButtonNoCrop->isChecked())
303         stretch = QLatin1String("BorderImage.Round");
304
305     if (stretch == QLatin1String("BorderImage.Stretch"))
306         emit removeProperty(QLatin1String("horizontalTileMode"));
307     else
308         emit propertyChanged(QLatin1String("horizontalTileMode"), stretch);
309 }
310
311 void ContextPaneWidgetImage::onVerticalStretchChanged()
312 {
313     QString stretch;
314     if (uiBorderImage->verticalStretchRadioButton->isChecked())
315         stretch = QLatin1String("BorderImage.Stretch");
316     if (uiBorderImage->verticalTileRadioButton->isChecked())
317         stretch = QLatin1String("BorderImage.Repeat");
318     if (uiBorderImage->verticalTileRadioButtonNoCrop->isChecked())
319         stretch = QLatin1String("BorderImage.Round");
320
321     if (stretch == QLatin1String("BorderImage.Stretch"))
322         emit removeProperty(QLatin1String("verticalTileMode"));
323     else
324         emit propertyChanged(QLatin1String("verticalTileMode"), stretch);
325
326 }
327
328 void ContextPaneWidgetImage::onFileNameChanged()
329 {
330     if (m_fileWidget->fileName().isNull())
331         emit removeProperty(QLatin1String("source"));
332     else
333         emit propertyChanged(QLatin1String("source"), QString(QLatin1Char('\"') + m_fileWidget->fileName() + QLatin1Char('\"')));
334 }
335
336 void ContextPaneWidgetImage::onPixmapDoubleClicked()
337 {    
338     previewDialog()->setParent(parentWidget()->parentWidget());
339     previewDialog()->setMaximumSize(previewDialog()->parentWidget()->size() - QSize(150, 100));
340     if (m_borderImage)
341         previewDialog()->setZoom(4);
342     previewDialog()->setIsBorderImage(m_borderImage);
343
344     QPoint p = parentWidget()->pos();
345     p = p + QPoint(-2, -2);
346     previewDialog()->show();
347     previewDialog()->update();
348     previewDialog()->move(p);
349     //previewDialog()->adjustSize();
350     if ((previewDialog()->pos().x() + previewDialog()->width()) > previewDialog()->parentWidget()->width())
351         previewDialog()->move(previewDialog()->parentWidget()->width() - (previewDialog()->width()) - 40, p.y());
352
353     if ((previewDialog()->pos().y() + previewDialog()->height()) > previewDialog()->parentWidget()->height())
354         previewDialog()->move(previewDialog()->pos().x(), previewDialog()->parentWidget()->height() - (previewDialog()->height()) - 40);
355
356     if (previewDialog()->pos().x() < 0)
357         previewDialog()->move(0, previewDialog()->pos().y());
358     if (previewDialog()->pos().y() < 0)
359         previewDialog()->move(previewDialog()->pos().x(), 0);        
360
361     previewDialog()->raise();
362 }
363
364 void ContextPaneWidgetImage::onLeftMarginsChanged()
365 {
366     if (previewDialog()->previewLabel()->leftMarging())
367         propertyChanged(QLatin1String("border.left"), previewDialog()->previewLabel()->leftMarging());
368     else
369         emit removeProperty(QLatin1String("border.left"));
370 }
371
372 void ContextPaneWidgetImage::onRightMarginsChanged()
373 {
374     if (previewDialog()->previewLabel()->rightMarging())
375         propertyChanged(QLatin1String("border.right"), previewDialog()->previewLabel()->rightMarging());
376     else
377         emit removeProperty(QLatin1String("border.right"));
378
379
380 }
381
382 void ContextPaneWidgetImage::onTopMarginsChanged()
383 {
384     if (previewDialog()->previewLabel()->topMarging())
385         propertyChanged(QLatin1String("border.top"), previewDialog()->previewLabel()->topMarging());
386     else
387         emit removeProperty(QLatin1String("border.top"));
388 }
389
390 void ContextPaneWidgetImage::onBottomMarginsChanged()
391 {
392     if (previewDialog()->previewLabel()->bottomMarging())
393         propertyChanged(QLatin1String("border.bottom"), previewDialog()->previewLabel()->bottomMarging());
394     else
395         emit removeProperty(QLatin1String("border.bottom"));
396
397 }
398
399 static inline Qt::TileRule stringToRule(const QString &s)
400 {
401     if (s == QLatin1String("Stretch"))
402         return  Qt::StretchTile;
403     if (s == QLatin1String("Repeat"))
404         return  Qt::RepeatTile;
405     if (s == QLatin1String("Round"))
406         return Qt::RoundTile;
407
408     qWarning("QDeclarativeGridScaledImage: Invalid tile rule specified. Using Stretch.");
409     return  Qt::StretchTile;
410 }
411
412 static inline bool parseSciFile(const QString &fileName, QString &pixmapFileName, int &left, int &right, int &top, int &bottom, Qt::TileRule &horizontalTileRule, Qt::TileRule &verticalTileRule)
413 {
414     int l = -1;
415     int r = -1;
416     int t = -1;
417     int b = -1;
418     QString imgFile;
419
420     QFile data(fileName);
421     data.open(QIODevice::ReadOnly);
422
423     QByteArray raw;
424     while(raw = data.readLine(), !raw.isEmpty()) {
425         QString line = QString::fromUtf8(raw.trimmed());
426         if (line.isEmpty() || line.startsWith(QLatin1Char('#')))
427             continue;
428
429         QStringList list = line.split(QLatin1Char(':'));
430         if (list.count() != 2)
431             return false;
432
433         list[0] = list[0].trimmed();
434         list[1] = list[1].trimmed();
435
436         if (list[0] == QLatin1String("border.left"))
437             l = list[1].toInt();
438         else if (list[0] == QLatin1String("border.right"))
439             r = list[1].toInt();
440         else if (list[0] == QLatin1String("border.top"))
441             t = list[1].toInt();
442         else if (list[0] == QLatin1String("border.bottom"))
443             b = list[1].toInt();
444         else if (list[0] == QLatin1String("source"))
445             imgFile = list[1];
446         else if (list[0] == QLatin1String("horizontalTileRule"))
447             horizontalTileRule = stringToRule(list[1]);
448         else if (list[0] == QLatin1String("verticalTileRule"))
449            verticalTileRule = stringToRule(list[1]);
450     }
451
452     if (l < 0 || r < 0 || t < 0 || b < 0 || imgFile.isEmpty())
453         return false;
454
455     left = l; right = r; top = t; bottom = b;
456
457     pixmapFileName = imgFile;
458
459     return true;
460 }
461
462 void ContextPaneWidgetImage::setPixmap(const QString &fileName)
463 {
464     QPixmap pix(76,76);
465     pix.fill(Qt::black);
466
467     if (m_borderImage) {
468         QString localFileName(fileName);
469         if (QFile(fileName).exists()) {
470             if (fileName.endsWith(QLatin1String("sci"))) {
471                 QString pixmapFileName;
472                 int left = 0;
473                 int right = 0;
474                 int top = 0;
475                 int bottom = 0;
476
477                 Qt::TileRule horizontalTileRule;
478                 Qt::TileRule verticalTileRule;
479                 if (parseSciFile(fileName, pixmapFileName, left, right, top, bottom, horizontalTileRule, verticalTileRule)) {
480                     localFileName = QFileInfo(fileName).absoluteDir().absolutePath() + '/' + pixmapFileName;
481                     previewDialog()->previewLabel()->setMargins(left, top, right, bottom);
482                 } else { // sci file not parsed correctly
483                     uiBorderImage->sizeLabel->setText("");
484                     return;
485                 }
486             }
487             QPixmap source(localFileName);
488             if (source.isNull())
489                 source = pix;
490             previewDialog()->setPixmap(source, previewDialog()->zoom());
491             uiBorderImage->sizeLabel->setText(QString::number(source.width()) + 'x' + QString::number(source.height()));
492             QPainter p(&pix);
493             Qt::TileRule horizontalTileMode = Qt::StretchTile;
494             Qt::TileRule verticalTileMode = Qt::StretchTile;
495             if (uiBorderImage->horizontalTileRadioButton->isChecked())
496                 horizontalTileMode =Qt::RepeatTile;
497             if (uiBorderImage->horizontalTileRadioButtonNoCrop->isChecked())
498                 horizontalTileMode =Qt::RoundTile;
499             if (uiBorderImage->verticalTileRadioButton->isChecked())
500                 verticalTileMode =Qt::RepeatTile;
501             if (uiBorderImage->verticalTileRadioButtonNoCrop->isChecked())
502                 verticalTileMode =Qt::RoundTile;
503             QTileRules rules(horizontalTileMode, verticalTileMode);
504             QMargins margins(previewDialog()->previewLabel()->leftMarging() ,previewDialog()->previewLabel()->topMarging() ,previewDialog()->previewLabel()->rightMarging(), previewDialog()->previewLabel()->bottomMarging());
505             qDrawBorderPixmap(&p, QRect(0, 0, 76, 76), margins, source, source.rect(), margins, rules);
506             //p.drawPixmap(0,0,76,76, source);
507         } else {
508             uiBorderImage->sizeLabel->setText("");
509         }
510         uiBorderImage->label->setPixmap(pix);
511     } else {
512         if (QFile(fileName).exists()) {
513             QPixmap source(fileName);
514             previewDialog()->setPixmap(source, 1);
515             ui->sizeLabel->setText(QString::number(source.width()) + 'x' + QString::number(source.height()));
516             QPainter p(&pix);
517             if (ui->stretchRadioButton->isChecked()) {
518                 p.drawPixmap(0,0,76,76, source);
519             } else if (ui->tileRadioButton->isChecked()) {
520                 QPixmap small = source.scaled(38,38);
521                 p.drawTiledPixmap(0,0,76,76, small);
522             } else if (ui->horizontalStretchRadioButton->isChecked()) {
523                 QPixmap small = source.scaled(38,38);
524                 QPixmap half = pix.scaled(38, 76);
525                 QPainter p2(&half);
526                 p2.drawTiledPixmap(0,0,38,76, small);
527                 p.drawPixmap(0,0,76,76, half);
528             } else if (ui->verticalStretchRadioButton->isChecked()) {
529                 QPixmap small = source.scaled(38,38);
530                 QPixmap half = pix.scaled(76, 38);
531                 QPainter p2(&half);
532                 p2.drawTiledPixmap(0,0,76,38, small);
533                 p.drawPixmap(0,0,76,76, half);
534             } else if (ui->preserveAspectFitRadioButton->isChecked()) {
535                 QPixmap preserved = source.scaledToWidth(76);
536                 int offset = (76 - preserved.height()) / 2;
537                 p.drawPixmap(0, offset, 76, preserved.height(), source);
538             } else if (ui->cropAspectFitRadioButton->isChecked()) {
539                 QPixmap cropped = source.scaledToHeight(76);
540                 int offset = (76 - cropped.width()) / 2;
541                 p.drawPixmap(offset, 0, cropped.width(), 76, source);
542             }
543         } else {
544             ui->sizeLabel->setText("");
545         }
546
547         ui->label->setPixmap(pix);
548
549     }
550 }
551
552 PreviewDialog* ContextPaneWidgetImage::previewDialog()
553 {
554     if (!m_previewDialog) {
555         m_previewDialog = new PreviewDialog(this);
556         m_previewDialog->hide();
557     }
558
559     return m_previewDialog.data();
560 }
561
562 void ContextPaneWidgetImage::changeEvent(QEvent *e)
563 {
564     QWidget::changeEvent(e);
565     switch (e->type()) {
566     case QEvent::LanguageChange:
567         if (ui)
568             ui->retranslateUi(this);
569         if (uiBorderImage)
570             uiBorderImage->retranslateUi(this);
571         break;
572     default:
573         break;
574     }
575 }
576
577
578 void ContextPaneWidgetImage::hideEvent(QHideEvent * event)
579 {
580     previewWasVisible = previewDialog()->isVisible();
581     previewDialog()->hide();
582     QWidget::hideEvent(event);
583 }
584
585 void ContextPaneWidgetImage::showEvent(QShowEvent* event)
586 {
587     if (previewWasVisible)
588         previewDialog()->show();
589     QWidget::showEvent(event);
590 }
591
592 PreviewLabel::PreviewLabel(QWidget *parent)
593     : QLabel(parent),
594       m_dragging_left(false), m_dragging_right(false),
595       m_dragging_top(false), m_dragging_bottom(false)
596
597 {
598     m_zoom = 1;
599     m_showBorders = false;
600     m_left = 2;
601     m_right = 2;
602     m_top = 2;
603     m_bottom = 2;
604     setMouseTracking(true);
605     setCursor(QCursor(Qt::ArrowCursor));
606     m_hooverInfo = new QLabel(parentWidget());
607     m_hooverInfo->hide();
608
609     m_hooverInfo->setFrameShape(QFrame::StyledPanel);
610     m_hooverInfo->setFrameShadow(QFrame::Sunken);
611
612     QGraphicsDropShadowEffect *dropShadowEffect = new QGraphicsDropShadowEffect;
613     dropShadowEffect->setBlurRadius(4);
614     dropShadowEffect->setOffset(2, 2);
615     m_hooverInfo->setGraphicsEffect(dropShadowEffect);
616     m_hooverInfo->setAutoFillBackground(true);
617     m_hooverInfo->raise();
618 }
619
620 void PreviewLabel::setZoom(int z)
621 {
622     m_zoom = z;
623 }
624
625 void PreviewLabel::setIsBorderImage(bool b)
626 {
627     m_borderImage = b;
628 }
629
630 void PreviewLabel::setMargins(int left, int top, int right, int bottom)
631 {
632     m_left = left;
633     m_top = top;
634     m_right = right;
635     m_bottom = bottom;
636 }
637
638 void PreviewLabel::paintEvent(QPaintEvent *event)
639 {
640     QLabel::paintEvent(event);
641     if (m_borderImage) {
642
643         QPainter p(this);
644
645         p.setOpacity(0.5);
646
647         p.setBackgroundMode(Qt::TransparentMode);
648         {
649             QPen pen(Qt::SolidLine);
650             pen.setColor("#F0F0F0");
651             p.setPen(pen);
652
653             if (m_left >= 0)
654                 p.drawLine(m_left * m_zoom, 4, m_left * m_zoom, height() - 4);
655             if (m_right >= 0)
656                 p.drawLine(width() - m_right * m_zoom, 4, width() - m_right * m_zoom, height() - 4);
657             if (m_top >= 0)
658                 p.drawLine(4, m_top * m_zoom, width() - 4, m_top * m_zoom);
659             if (m_bottom >= 0)
660                 p.drawLine(4, height() - m_bottom * m_zoom, width() - 4, height() - m_bottom * m_zoom);
661         }
662
663         {
664             QBrush brush(Qt::Dense4Pattern);
665             brush.setColor("#101010");
666             QPen pen(brush, 1, Qt::DotLine);
667             pen.setColor("#101010");
668             p.setPen(pen);
669
670             if (m_left >= 0)
671                 p.drawLine(m_left * m_zoom, 4, m_left * m_zoom, height() - 4);
672             if (m_right >= 0)
673                 p.drawLine(width() - m_right * m_zoom, 4, width() - m_right * m_zoom, height() - 4);
674             if (m_top >= 0)
675                 p.drawLine(4, m_top * m_zoom, width() - 4, m_top * m_zoom);
676             if (m_bottom >= 0)
677                 p.drawLine(4, height() - m_bottom * m_zoom, width() - 4, height() - m_bottom * m_zoom);
678         }
679     }
680 }
681
682 static inline bool rangeCheck(int target, int pos)
683 {
684     return (target - 10 < pos) && (target + 10 > pos);
685 }
686
687 void PreviewLabel::mousePressEvent(QMouseEvent * event)
688 {
689     if (!m_borderImage)
690         return QLabel::mouseMoveEvent(event);
691
692     if (event->button() == Qt::LeftButton) {
693         if (QApplication::overrideCursor())
694             QApplication::restoreOverrideCursor();
695         if (rangeCheck(m_left * m_zoom, event->pos().x())) {
696             QApplication::setOverrideCursor(QCursor(Qt::SizeHorCursor));
697             m_dragging_left = true;
698             event->accept();
699             m_hooverInfo->setText("Left " + QString::number(m_left));
700             m_hooverInfo->show();
701         } else if (rangeCheck(m_top * m_zoom, event->pos().y())) {
702             QApplication::setOverrideCursor(QCursor(Qt::SizeVerCursor));
703             m_dragging_top = true;
704             event->accept();
705             m_hooverInfo->setText("Top " + QString::number(m_top));
706             m_hooverInfo->show();
707         } else if (rangeCheck(m_right * m_zoom, width() - event->pos().x())) {
708             QApplication::setOverrideCursor(QCursor(Qt::SizeHorCursor));
709             m_dragging_right = true;
710             event->accept();
711             m_hooverInfo->setText("Right " + QString::number(m_right));
712             m_hooverInfo->show();
713         } else if (rangeCheck(m_bottom * m_zoom, height() - event->pos().y())) {
714             QApplication::setOverrideCursor(QCursor(Qt::SizeVerCursor));
715             m_dragging_bottom = true;
716             event->accept();
717             m_hooverInfo->setText("Bottom " + QString::number(m_bottom));
718             m_hooverInfo->show();
719         } else {
720             QLabel::mousePressEvent(event);
721         }
722         m_startPos = event->pos();
723         m_hooverInfo->move(mapToParent(event->pos()) + QPoint(0, 40));
724         m_hooverInfo->resize(m_hooverInfo->sizeHint());
725         m_hooverInfo->raise();
726     }
727 }
728
729 void PreviewLabel::mouseReleaseEvent(QMouseEvent * event)
730 {
731     if (!m_borderImage)
732         return QLabel::mouseMoveEvent(event);
733
734     if (m_dragging_left || m_dragging_top || m_dragging_right|| m_dragging_bottom) {
735         m_hooverInfo->hide();
736         if (m_dragging_left)
737             emit leftMarginChanged();
738
739         if (m_dragging_top)
740             emit topMarginChanged();
741
742         if (m_dragging_bottom)
743             emit bottomMarginChanged();
744
745         if (m_dragging_right)
746             emit rightMarginChanged();
747
748         m_dragging_left = false;
749         m_dragging_top = false;
750         m_dragging_right = false;
751         m_dragging_bottom = false;
752         QApplication::restoreOverrideCursor();
753         event->accept();
754
755     } else {
756         QLabel::mouseReleaseEvent(event);
757     }
758 }
759
760
761 static inline int limitPositive(int i)
762 {
763     if (i >= 0)
764         return i;
765     return 0;
766 }
767
768 static inline int limit(int i, int zoom)
769 {
770     static bool flag1 = 1;
771     static bool flag2 = 1;
772     if (zoom == 1)
773         return i;
774     if (i < 0) {
775         int v = i / zoom;
776         if (v)
777             return v;
778         if (zoom == 2) {
779             flag1 =!flag1;
780             return flag1 ? -1 : 0;
781         }
782         flag1 =!flag1;
783         if (flag1)
784             flag2 =!flag2;
785
786         return flag1 && flag2 ? -1 : 0;
787     }
788     if (i > 0) {
789         int v = i / zoom;
790         if (v)
791             return v;
792         if (zoom == 2) {
793             flag1 =!flag1;
794             return flag1 ? 1 : 0;
795         }
796         flag1 =!flag1;
797         if (flag1)
798             flag2 =!flag2;
799
800         return flag1 && flag2 ? 1 : 0;
801     }
802     return 0;
803 }
804
805 void PreviewLabel::mouseMoveEvent(QMouseEvent * event)
806 {
807     if (!m_borderImage)
808         return QLabel::mouseMoveEvent(event);
809
810     QPoint p = event->pos();
811     if (m_dragging_left) {
812         m_left = p.x() / m_zoom;
813         m_left = limitPositive(m_left);
814         event->accept();
815         m_hooverInfo->setText("Left " + QString::number(m_left));
816         update();
817     } else if (m_dragging_top) {
818         m_top = p.y() / m_zoom;
819         m_top = limitPositive(m_top);
820         event->accept();
821         m_hooverInfo->setText("Top " + QString::number(m_top));
822         update();
823     }  else if (m_dragging_right) {
824         m_right = (width() - p.x()) / m_zoom;
825         m_right = limitPositive(m_right);
826         event->accept();
827         m_hooverInfo->setText("Right " + QString::number(m_right));
828         update();
829     } else if (m_dragging_bottom) {
830         m_bottom = (height() - p.y()) / m_zoom;
831         m_bottom = limitPositive(m_bottom);
832         event->accept();
833         m_hooverInfo->setText("Bottom " + QString::number(m_bottom));
834         update();
835     } else if (rangeCheck(m_left * m_zoom, p.x())) {
836         QApplication::setOverrideCursor(QCursor(Qt::SizeHorCursor));
837         event->accept();
838         m_hooverInfo->setText("Left " + QString::number(m_left));
839         m_hooverInfo->show();
840     } else if (rangeCheck(m_top * m_zoom, p.y())) {
841         QApplication::setOverrideCursor(QCursor(Qt::SizeVerCursor));
842         event->accept();
843         m_hooverInfo->setText("Top " + QString::number(m_top));
844         m_hooverInfo->show();
845     } else if (rangeCheck(m_right * m_zoom, width() - p.x())) {
846         QApplication::setOverrideCursor(QCursor(Qt::SizeHorCursor));
847         event->accept();
848         m_hooverInfo->setText("Right " + QString::number(m_right));
849         m_hooverInfo->show();
850     } else if (rangeCheck(m_bottom * m_zoom, height() - p.y())) {
851         QApplication::setOverrideCursor(QCursor(Qt::SizeVerCursor));
852         event->accept();
853         m_hooverInfo->setText("Bottom " + QString::number(m_bottom));
854         m_hooverInfo->show();
855     } else {
856         if (QApplication::overrideCursor())
857             QApplication::restoreOverrideCursor();
858         QLabel::mouseMoveEvent(event);
859         m_hooverInfo->hide();
860     }
861     m_startPos = p;
862     m_hooverInfo->move(mapToParent(p) + QPoint(0, 40));
863     m_hooverInfo->resize(m_hooverInfo->sizeHint());
864     m_hooverInfo->raise();
865 }
866
867 void PreviewLabel::leaveEvent(QEvent* event )
868 {
869     while (QApplication::overrideCursor())
870         QApplication::restoreOverrideCursor();
871     m_hooverInfo->hide();
872     QLabel::leaveEvent(event);
873 }
874
875 PreviewDialog::PreviewDialog(QWidget *parent) : DragWidget(parent)
876 {
877     m_borderImage = false;
878     setAutoFillBackground(true);
879
880     m_label = new PreviewLabel(this);
881     m_slider = new QSlider(this);
882
883     m_zoomLabel = new QLabel(this);
884
885     setZoom(1);
886
887     QVBoxLayout *layout = new QVBoxLayout(this);
888     QHBoxLayout *horizontalLayout = new QHBoxLayout();
889     QHBoxLayout *horizontalLayout2 = new QHBoxLayout();
890     layout->setMargin(0);
891     layout->setContentsMargins(2, 2, 2, 6);
892     layout->setSpacing(4);
893     QToolButton *toolButton = new QToolButton(this);
894     QIcon icon(style()->standardIcon(QStyle::SP_DockWidgetCloseButton));
895     toolButton->setIcon(icon);
896     toolButton->setToolButtonStyle(Qt::ToolButtonIconOnly);
897     toolButton->setFixedSize(icon.availableSizes().value(0) + QSize(4, 4));
898     connect(toolButton, SIGNAL(clicked()), this, SLOT(onTogglePane()));
899
900     QScrollArea *scrollArea = new QScrollArea(this);
901     WheelFilter *wheelFilter = new WheelFilter(scrollArea);
902     scrollArea->setWidget(m_label);
903     scrollArea->setFrameStyle(QFrame::NoFrame);
904     m_slider->setOrientation(Qt::Horizontal);
905     m_slider->setRange(1, 6);
906     m_slider->setFixedWidth(80);
907     m_zoomLabel->setFixedWidth(50);
908
909     horizontalLayout->addWidget(toolButton);
910     horizontalLayout->addSpacing(6);
911     horizontalLayout->addWidget(m_slider);
912     horizontalLayout->addSpacing(6);
913     horizontalLayout->addWidget(m_zoomLabel);
914     horizontalLayout->addStretch(1);
915
916     layout->addLayout(horizontalLayout);
917     horizontalLayout2->addSpacing(24);
918     horizontalLayout2->addWidget(scrollArea);
919     layout->addLayout(horizontalLayout2);
920
921     wheelFilter->setTarget(this);
922
923     connect(m_slider, SIGNAL(valueChanged(int)), this, SLOT(onSliderMoved(int)));
924
925     foreach (QWidget *childWidget, findChildren<QWidget*>()) {
926         childWidget->installEventFilter(wheelFilter);
927     }
928 }
929
930 void PreviewDialog::setPixmap(const QPixmap &p, int zoom)
931 {
932     m_pixmap = p;
933     if (!p.isNull())
934         m_label->setPixmap(p.scaled(p.width() * zoom, p.height() * zoom));
935     else
936         m_label->setPixmap(QPixmap());
937     m_label->adjustSize();
938     m_zoom = zoom;
939     m_label->setZoom(m_zoom);
940     QSize size = m_label->pixmap()->size() + QSize(54, 44);
941     if (size.width() < 180)
942         size.setWidth(180);
943     resize(size);
944 }
945
946 void PreviewDialog::wheelEvent(QWheelEvent* event)
947 {
948     int delta = event->delta();
949     event->accept();
950     if (delta >  0) {
951         if (m_zoom == 1)
952             setZoom(2);
953         else if (m_zoom == 2)
954             setZoom(4);
955         else if (m_zoom == 4)
956             setZoom(6);
957         else if (m_zoom == 6)
958             setZoom(8);
959         else if (m_zoom == 8)
960             setZoom(10);
961     } else {
962         if (m_zoom == 10)
963             setZoom(8);
964         else if (m_zoom == 8)
965             setZoom(6);
966         else if (m_zoom == 6)
967             setZoom(4);
968         else if (m_zoom == 4)
969             setZoom(2);
970         else if (m_zoom == 2)
971             setZoom(1);
972     }
973     setPixmap(m_pixmap, m_zoom);
974 }
975
976 void PreviewDialog::onTogglePane()
977 {
978     hide();
979 }
980
981 void PreviewDialog::onSliderMoved(int value)
982 {
983     switch (value) {
984     case 1: setZoom(1); break;
985     case 2: setZoom(2); break;
986     case 3: setZoom(4); break;
987     case 4: setZoom(6); break;
988     case 5: setZoom(8); break;
989     case 6: setZoom(10); break;
990     default: break;
991     }
992 }
993
994 } //QmlDesigner