]> git.sesse.net Git - kdenlive/blob - src/titlewidget.cpp
r6477@lapL: simon | 2010-06-02 17:42:57 +0200
[kdenlive] / src / titlewidget.cpp
1 /***************************************************************************
2                           titlewidget.cpp  -  description
3                              -------------------
4     begin                : Feb 28 2008
5     copyright            : (C) 2008 by Marco Gittler
6     email                : g.marco@freenet.de
7  ***************************************************************************/
8
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17
18 #include "titlewidget.h"
19 #include "kdenlivesettings.h"
20 #include "KoSliderCombo.h"
21 #include "kthumb.h"
22 #include <cmath>
23
24 #include <KDebug>
25 #include <KGlobalSettings>
26 #include <KFileDialog>
27 #include <KStandardDirs>
28 #include <KMessageBox>
29 #include <kio/netaccess.h>
30 #include <kdeversion.h>
31
32 #include <QDomDocument>
33 #include <QGraphicsItem>
34 #include <QGraphicsSvgItem>
35 #include <QTimer>
36 #include <QToolBar>
37 #include <QMenu>
38 #include <QSignalMapper>
39 #include <QTextBlockFormat>
40 #include <QTextCursor>
41 #include <QComboBox>
42 #include <QCryptographicHash>
43
44 #if QT_VERSION >= 0x040600
45 #include <QGraphicsEffect>
46 #include <QGraphicsBlurEffect>
47 #include <QGraphicsDropShadowEffect>
48 #endif
49
50 #include <iostream>
51
52 static QList<TitleTemplate> titletemplates;
53
54 // What exactly is this variable good for?
55 int settingUp = false;
56
57 const int IMAGEITEM = 7;
58 const int RECTITEM = 3;
59 const int TEXTITEM = 8;
60
61 const int NOEFFECT = 0;
62 const int BLUREFFECT = 1;
63 const int SHADOWEFFECT = 2;
64 const int TYPEWRITEREFFECT = 3;
65
66 TitleWidget::TitleWidget(KUrl url, Timecode tc, QString projectTitlePath, Render *render, QWidget *parent) :
67     QDialog(parent),
68     Ui::TitleWidget_UI(),
69     m_startViewport(NULL),
70     m_endViewport(NULL),
71     m_render(render),
72     m_count(0),
73     m_unicodeDialog(new UnicodeDialog(UnicodeDialog::InputHex)),
74     m_projectTitlePath(projectTitlePath),
75     m_tc(tc)
76 {
77     setupUi(this);
78     setFont(KGlobalSettings::toolBarFont());
79     frame_properties->setEnabled(false);
80     frame_properties->setFixedHeight(frame_toolbar->height());
81
82     // Set combo sliders values
83     textAlpha->setMinimum(0);
84     textAlpha->setMaximum(255);
85     textAlpha->setDecimals(0);
86     textAlpha->setValue(255);
87     textAlpha->setToolTip(i18n("Font color opacity"));
88
89     textOutlineAlpha->setMinimum(0);
90     textOutlineAlpha->setMaximum(255);
91     textOutlineAlpha->setDecimals(0);
92     textOutlineAlpha->setValue(255);
93     textOutlineAlpha->setToolTip(i18n("Outline color opacity"));
94
95     textOutline->setMinimum(0);
96     textOutline->setMaximum(200);
97     textOutline->setDecimals(0);
98     textOutline->setValue(0);
99     textOutline->setToolTip(i18n("Outline width"));
100
101     backgroundAlpha->setMinimum(0);
102     backgroundAlpha->setMaximum(255);
103     backgroundAlpha->setDecimals(0);
104     backgroundAlpha->setValue(0);
105     backgroundAlpha->setToolTip(i18n("Background color opacity"));
106
107     itemrotatex->setMinimum(-360);
108     itemrotatex->setMaximum(360);
109     itemrotatex->setDecimals(0);
110     itemrotatex->setValue(0);
111     itemrotatex->setToolTip(i18n("Rotation around the X axis"));
112
113     itemrotatey->setMinimum(-360);
114     itemrotatey->setMaximum(360);
115     itemrotatey->setDecimals(0);
116     itemrotatey->setValue(0);
117     itemrotatey->setToolTip(i18n("Rotation around the Y axis"));
118
119     itemrotatez->setMinimum(-360);
120     itemrotatez->setMaximum(360);
121     itemrotatez->setDecimals(0);
122     itemrotatez->setValue(0);
123     itemrotatez->setToolTip(i18n("Rotation around the Z axis"));
124
125     rectBAlpha->setMinimum(0);
126     rectBAlpha->setMaximum(255);
127     rectBAlpha->setDecimals(0);
128     rectBAlpha->setValue(255);
129     rectBAlpha->setToolTip(i18n("Color opacity"));
130
131     rectFAlpha->setMinimum(0);
132     rectFAlpha->setMaximum(255);
133     rectFAlpha->setDecimals(0);
134     rectFAlpha->setValue(255);
135     rectFAlpha->setToolTip(i18n("Border opacity"));
136
137     rectLineWidth->setMinimum(0);
138     rectLineWidth->setMaximum(100);
139     rectLineWidth->setDecimals(0);
140     rectLineWidth->setValue(0);
141     rectLineWidth->setToolTip(i18n("Border width"));
142
143     itemzoom->setSuffix(i18n("%"));
144     m_frameWidth = render->renderWidth();
145     m_frameHeight = render->renderHeight();
146     showToolbars(TITLE_SELECT);
147
148     //If project is drop frame, set the input mask as such.
149     title_duration->setInputMask("");
150     title_duration->setValidator(m_tc.validator());
151     title_duration->setText(m_tc.reformatSeparators(KdenliveSettings::title_duration()));
152
153     connect(backgroundColor, SIGNAL(clicked()), this, SLOT(slotChangeBackground())) ;
154     connect(backgroundAlpha, SIGNAL(valueChanged(qreal, bool)), this, SLOT(slotChangeBackground())) ;
155
156     connect(fontColorButton, SIGNAL(clicked()), this, SLOT(slotUpdateText())) ;
157     connect(textOutlineColor, SIGNAL(clicked()), this, SLOT(slotUpdateText())) ;
158     connect(font_family, SIGNAL(currentFontChanged(const QFont &)), this, SLOT(slotUpdateText())) ;
159     connect(font_size, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateText())) ;
160     connect(textAlpha, SIGNAL(valueChanged(qreal, bool)), this, SLOT(slotUpdateText()));
161     connect(textOutline, SIGNAL(valueChanged(qreal, bool)), this, SLOT(slotUpdateText()));
162     connect(textOutlineAlpha, SIGNAL(valueChanged(qreal, bool)), this, SLOT(slotUpdateText()));
163     connect(font_weight_box, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdateText()));
164
165     connect(font_family, SIGNAL(editTextChanged(const QString &)), this, SLOT(slotFontText(const QString&)));
166
167     connect(rectFAlpha, SIGNAL(valueChanged(qreal, bool)), this, SLOT(rectChanged()));
168     connect(rectBAlpha, SIGNAL(valueChanged(qreal, bool)), this, SLOT(rectChanged()));
169     connect(rectFColor, SIGNAL(clicked()), this, SLOT(rectChanged()));
170     connect(rectBColor, SIGNAL(clicked()), this, SLOT(rectChanged()));
171     connect(rectLineWidth, SIGNAL(valueChanged(qreal, bool)), this, SLOT(rectChanged()));
172
173     /*connect(startViewportX, SIGNAL(valueChanged(int)), this, SLOT(setupViewports()));
174     connect(startViewportY, SIGNAL(valueChanged(int)), this, SLOT(setupViewports()));
175     connect(startViewportSize, SIGNAL(valueChanged(int)), this, SLOT(setupViewports()));
176     connect(endViewportX, SIGNAL(valueChanged(int)), this, SLOT(setupViewports()));
177     connect(endViewportY, SIGNAL(valueChanged(int)), this, SLOT(setupViewports()));
178     connect(endViewportSize, SIGNAL(valueChanged(int)), this, SLOT(setupViewports()));*/
179
180     // Fill effects
181     effect_list->addItem(i18n("None"), NOEFFECT);
182     effect_list->addItem(i18n("Typewriter"), TYPEWRITEREFFECT);
183     effect_list->addItem(i18n("Blur"), BLUREFFECT);
184
185
186     connect(zValue, SIGNAL(valueChanged(int)), this, SLOT(zIndexChanged(int)));
187     connect(itemzoom, SIGNAL(valueChanged(int)), this, SLOT(itemScaled(int)));
188     connect(itemrotatex, SIGNAL(valueChanged(qreal, bool)), this, SLOT(itemRotateX(qreal)));
189     connect(itemrotatey, SIGNAL(valueChanged(qreal, bool)), this, SLOT(itemRotateY(qreal)));
190     connect(itemrotatez, SIGNAL(valueChanged(qreal, bool)), this, SLOT(itemRotateZ(qreal)));
191     connect(itemhcenter, SIGNAL(clicked()), this, SLOT(itemHCenter()));
192     connect(itemvcenter, SIGNAL(clicked()), this, SLOT(itemVCenter()));
193     connect(itemtop, SIGNAL(clicked()), this, SLOT(itemTop()));
194     connect(itembottom, SIGNAL(clicked()), this, SLOT(itemBottom()));
195     connect(itemleft, SIGNAL(clicked()), this, SLOT(itemLeft()));
196     connect(itemright, SIGNAL(clicked()), this, SLOT(itemRight()));
197     connect(effect_list, SIGNAL(currentIndexChanged(int)), this, SLOT(slotAddEffect(int)));
198     connect(typewriter_delay, SIGNAL(valueChanged(int)), this, SLOT(slotEditTypewriter(int)));
199     connect(typewriter_start, SIGNAL(valueChanged(int)), this, SLOT(slotEditTypewriter(int)));
200     connect(blur_radius, SIGNAL(valueChanged(int)), this, SLOT(slotEditBlur(int)));
201     connect(shadow_radius, SIGNAL(valueChanged(int)), this, SLOT(slotEditShadow()));
202     connect(shadow_x, SIGNAL(valueChanged(int)), this, SLOT(slotEditShadow()));
203     connect(shadow_y, SIGNAL(valueChanged(int)), this, SLOT(slotEditShadow()));
204     effect_stack->setHidden(true);
205     effect_frame->setEnabled(false);
206
207     connect(origin_x_left, SIGNAL(clicked()), this, SLOT(slotOriginXClicked()));
208     connect(origin_y_top, SIGNAL(clicked()), this, SLOT(slotOriginYClicked()));
209
210     m_signalMapper = new QSignalMapper(this);
211     m_signalMapper->setMapping(value_w, ValueWidth);
212     m_signalMapper->setMapping(value_h, ValueHeight);
213     connect(value_w, SIGNAL(valueChanged(int)), m_signalMapper, SLOT(map()));
214     connect(value_h, SIGNAL(valueChanged(int)), m_signalMapper, SLOT(map()));
215     connect(m_signalMapper, SIGNAL(mapped(int)), this, SLOT(slotValueChanged(int)));
216
217     connect(value_x, SIGNAL(valueChanged(int)), this, SLOT(slotAdjustSelectedItem()));
218     connect(value_y, SIGNAL(valueChanged(int)), this, SLOT(slotAdjustSelectedItem()));
219     connect(value_w, SIGNAL(valueChanged(int)), this, SLOT(slotAdjustSelectedItem()));
220     connect(value_h, SIGNAL(valueChanged(int)), this, SLOT(slotAdjustSelectedItem()));
221     connect(buttonFitZoom, SIGNAL(clicked()), this, SLOT(slotAdjustZoom()));
222     connect(buttonRealSize, SIGNAL(clicked()), this, SLOT(slotZoomOneToOne()));
223     connect(buttonItalic, SIGNAL(clicked()), this, SLOT(slotUpdateText()));
224     connect(buttonUnder, SIGNAL(clicked()), this, SLOT(slotUpdateText()));
225     connect(buttonAlignLeft, SIGNAL(clicked()), this, SLOT(slotUpdateText()));
226     connect(buttonAlignRight, SIGNAL(clicked()), this, SLOT(slotUpdateText()));
227     connect(buttonAlignCenter, SIGNAL(clicked()), this, SLOT(slotUpdateText()));
228     connect(buttonAlignNone, SIGNAL(clicked()), this, SLOT(slotUpdateText()));
229     connect(displayBg, SIGNAL(stateChanged(int)), this, SLOT(displayBackgroundFrame()));
230
231     connect(m_unicodeDialog, SIGNAL(charSelected(QString)), this, SLOT(slotInsertUnicodeString(QString)));
232
233     // mbd
234     connect(this, SIGNAL(accepted()), this, SLOT(slotAccepted()));
235
236     font_weight_box->blockSignals(true);
237     font_weight_box->addItem(i18nc("Font style", "Light"), QFont::Light);
238     font_weight_box->addItem(i18nc("Font style", "Normal"), QFont::Normal);
239     font_weight_box->addItem(i18nc("Font style", "Demi-Bold"), QFont::DemiBold);
240     font_weight_box->addItem(i18nc("Font style", "Bold"), QFont::Bold);
241     font_weight_box->addItem(i18nc("Font style", "Black"), QFont::Black);
242     font_weight_box->setToolTip(i18n("Font weight"));
243     font_weight_box->setCurrentIndex(1);
244     font_weight_box->blockSignals(false);
245
246     buttonFitZoom->setIcon(KIcon("zoom-fit-best"));
247     buttonRealSize->setIcon(KIcon("zoom-original"));
248     buttonItalic->setIcon(KIcon("format-text-italic"));
249     buttonUnder->setIcon(KIcon("format-text-underline"));
250     buttonAlignCenter->setIcon(KIcon("format-justify-center"));
251     buttonAlignLeft->setIcon(KIcon("format-justify-left"));
252     buttonAlignRight->setIcon(KIcon("format-justify-right"));
253     buttonAlignNone->setIcon(KIcon("kdenlive-align-none"));
254
255     buttonAlignNone->setToolTip(i18n("No alignment"));
256     buttonAlignRight->setToolTip(i18n("Align right"));
257     buttonAlignLeft->setToolTip(i18n("Align left"));
258     buttonAlignCenter->setToolTip(i18n("Align center"));
259
260     m_unicodeAction = new QAction(KIcon("kdenlive-insert-unicode"), QString(), this);
261     m_unicodeAction->setShortcut(Qt::SHIFT + Qt::CTRL + Qt::Key_U);
262     m_unicodeAction->setToolTip(i18n("Insert Unicode character") + ' ' + m_unicodeAction->shortcut().toString());
263     connect(m_unicodeAction, SIGNAL(triggered()), this, SLOT(slotInsertUnicode()));
264     buttonInsertUnicode->setDefaultAction(m_unicodeAction);
265
266     m_zUp = new QAction(KIcon("kdenlive-zindex-up"), QString(), this);
267     m_zUp->setShortcut(Qt::Key_PageUp);
268     m_zUp->setToolTip(i18n("Raise object"));
269     connect(m_zUp, SIGNAL(triggered()), this, SLOT(slotZIndexUp()));
270     zUp->setDefaultAction(m_zUp);
271
272     m_zDown = new QAction(KIcon("kdenlive-zindex-down"), QString(), this);
273     m_zDown->setShortcut(Qt::Key_PageDown);
274     m_zDown->setToolTip(i18n("Lower object"));
275     connect(m_zDown, SIGNAL(triggered()), this, SLOT(slotZIndexDown()));
276     zDown->setDefaultAction(m_zDown);
277
278     m_zTop = new QAction(KIcon("kdenlive-zindex-top"), QString(), this);
279     // TODO mbt 1414: Shortcut should change z index only if
280     // cursor is NOT in a text field ...
281     //m_zTop->setShortcut(Qt::Key_Home);
282     m_zTop->setToolTip(i18n("Raise object to top"));
283     connect(m_zTop, SIGNAL(triggered()), this, SLOT(slotZIndexTop()));
284     zTop->setDefaultAction(m_zTop);
285
286     m_zBottom = new QAction(KIcon("kdenlive-zindex-bottom"), QString(), this);
287     // TODO mbt 1414
288     //m_zBottom->setShortcut(Qt::Key_End);
289     m_zBottom->setToolTip(i18n("Lower object to bottom"));
290     connect(m_zBottom, SIGNAL(triggered()), this, SLOT(slotZIndexBottom()));
291     zBottom->setDefaultAction(m_zBottom);
292     
293     m_selectAll = new QAction(KIcon("kdenlive-zindex-bottom"), QString(), this);
294     m_selectAll->setShortcut(Qt::CTRL + Qt::Key_A);
295     connect(m_selectAll, SIGNAL(triggered()), this, SLOT(slotSelectAll()));
296     buttonSelectAll->setDefaultAction(m_selectAll);
297     
298     m_selectText = new QAction(KIcon("kdenlive-zindex-bottom"), QString(), this);
299     m_selectText->setShortcut(Qt::CTRL + Qt::Key_T);
300     connect(m_selectText, SIGNAL(triggered()), this, SLOT(slotSelectText()));
301     buttonSelectText->setDefaultAction(m_selectText);
302     
303     m_selectRects = new QAction(KIcon("kdenlive-zindex-bottom"), QString(), this);
304     m_selectRects->setShortcut(Qt::CTRL + Qt::Key_R);
305     connect(m_selectRects, SIGNAL(triggered()), this, SLOT(slotSelectRects()));
306     buttonSelectRects->setDefaultAction(m_selectRects);
307     
308     m_selectImages = new QAction(KIcon("kdenlive-zindex-bottom"), QString(), this);
309     m_selectImages->setShortcut(Qt::CTRL + Qt::Key_I);
310     connect(m_selectImages, SIGNAL(triggered()), this, SLOT(slotSelectImages()));
311     buttonSelectImages->setDefaultAction(m_selectImages);
312     
313     m_unselectAll = new QAction(KIcon("kdenlive-zindex-bottom"), QString(), this);
314     m_unselectAll->setShortcut(Qt::SHIFT + Qt::CTRL + Qt::Key_A);
315     connect(m_unselectAll, SIGNAL(triggered()), this, SLOT(slotSelectNone()));
316     buttonUnselectAll->setDefaultAction(m_unselectAll);
317
318     zDown->setIcon(KIcon("kdenlive-zindex-down"));
319     zTop->setIcon(KIcon("kdenlive-zindex-top"));
320     zBottom->setIcon(KIcon("kdenlive-zindex-bottom"));
321     connect(zDown, SIGNAL(clicked()), this, SLOT(slotZIndexDown()));
322     connect(zTop, SIGNAL(clicked()), this, SLOT(slotZIndexTop()));
323     connect(zBottom, SIGNAL(clicked()), this, SLOT(slotZIndexBottom()));
324
325     origin_x_left->setToolTip(i18n("Invert x axis and change 0 point"));
326     origin_y_top->setToolTip(i18n("Invert y axis and change 0 point"));
327     rectBColor->setToolTip(i18n("Select fill color"));
328     rectFColor->setToolTip(i18n("Select border color"));
329     rectBAlpha->setToolTip(i18n("Fill opacity"));
330     rectFAlpha->setToolTip(i18n("Border opacity"));
331     zoom_slider->setToolTip(i18n("Zoom"));
332     buttonRealSize->setToolTip(i18n("Original size (1:1)"));
333     buttonFitZoom->setToolTip(i18n("Fit zoom"));
334     backgroundColor->setToolTip(i18n("Select background color"));
335     backgroundAlpha->setToolTip(i18n("Background opacity"));
336     buttonSelectAll->setToolTip(i18n("Select all"));
337     buttonSelectText->setToolTip(i18n("Select text items in current selection"));
338     buttonSelectRects->setToolTip(i18n("Select rect items in current selection"));
339     buttonSelectImages->setToolTip(i18n("Select image items in current selection"));
340     buttonUnselectAll->setToolTip(i18n("Unselect all"));
341
342     itemhcenter->setIcon(KIcon("kdenlive-align-hor"));
343     itemhcenter->setToolTip(i18n("Align item horizontally"));
344     itemvcenter->setIcon(KIcon("kdenlive-align-vert"));
345     itemvcenter->setToolTip(i18n("Align item vertically"));
346     itemtop->setIcon(KIcon("kdenlive-align-top"));
347     itemtop->setToolTip(i18n("Align item to top"));
348     itembottom->setIcon(KIcon("kdenlive-align-bottom"));
349     itembottom->setToolTip(i18n("Align item to bottom"));
350     itemright->setIcon(KIcon("kdenlive-align-right"));
351     itemright->setToolTip(i18n("Align item to right"));
352     itemleft->setIcon(KIcon("kdenlive-align-left"));
353     itemleft->setToolTip(i18n("Align item to left"));
354
355
356     QHBoxLayout *layout = new QHBoxLayout;
357     frame_toolbar->setLayout(layout);
358     layout->setContentsMargins(0, 0, 0, 0);
359     QToolBar *m_toolbar = new QToolBar("titleToolBar", this);
360     int s = style()->pixelMetric(QStyle::PM_SmallIconSize);
361     m_toolbar->setIconSize(QSize(s, s));
362
363     m_buttonCursor = m_toolbar->addAction(KIcon("transform-move"), QString());
364     m_buttonCursor->setCheckable(true);
365     m_buttonCursor->setShortcut(Qt::ALT + Qt::Key_S);
366     m_buttonCursor->setToolTip(i18n("Selection Tool") + ' ' + m_buttonCursor->shortcut().toString());
367     connect(m_buttonCursor, SIGNAL(triggered()), this, SLOT(slotSelectTool()));
368
369     m_buttonText = m_toolbar->addAction(KIcon("insert-text"), QString());
370     m_buttonText->setCheckable(true);
371     m_buttonText->setShortcut(Qt::ALT + Qt::Key_T);
372     m_buttonText->setToolTip(i18n("Add Text") + ' ' + m_buttonText->shortcut().toString());
373     connect(m_buttonText, SIGNAL(triggered()), this, SLOT(slotTextTool()));
374
375     m_buttonRect = m_toolbar->addAction(KIcon("kdenlive-insert-rect"), QString());
376     m_buttonRect->setCheckable(true);
377     m_buttonRect->setShortcut(Qt::ALT + Qt::Key_R);
378     m_buttonRect->setToolTip(i18n("Add Rectangle") + ' ' + m_buttonRect->shortcut().toString());
379     connect(m_buttonRect, SIGNAL(triggered()), this, SLOT(slotRectTool()));
380
381     m_buttonImage = m_toolbar->addAction(KIcon("insert-image"), QString());
382     m_buttonImage->setCheckable(false);
383     m_buttonImage->setShortcut(Qt::ALT + Qt::Key_I);
384     m_buttonImage->setToolTip(i18n("Add Image") + ' ' + m_buttonImage->shortcut().toString());
385     connect(m_buttonImage, SIGNAL(triggered()), this, SLOT(slotImageTool()));
386
387     m_toolbar->addSeparator();
388
389     m_buttonLoad = m_toolbar->addAction(KIcon("document-open"), i18n("Open Document"));
390     m_buttonLoad->setCheckable(false);
391     m_buttonLoad->setShortcut(Qt::CTRL + Qt::Key_O);
392     connect(m_buttonLoad, SIGNAL(triggered()), this, SLOT(loadTitle()));
393
394     m_buttonSave = m_toolbar->addAction(KIcon("document-save-as"), i18n("Save As"));
395     m_buttonSave->setCheckable(false);
396     m_buttonSave->setShortcut(Qt::CTRL + Qt::Key_S);
397     connect(m_buttonSave, SIGNAL(triggered()), this, SLOT(saveTitle()));
398
399     layout->addWidget(m_toolbar);
400
401     // initialize graphic scene
402     m_scene = new GraphicsSceneRectMove(this);
403     graphicsView->setScene(m_scene);
404     graphicsView->setMouseTracking(true);
405     m_titledocument.setScene(m_scene, m_frameWidth, m_frameHeight);
406     connect(m_scene, SIGNAL(changed(QList<QRectF>)), this, SLOT(slotChanged()));
407     connect(font_size, SIGNAL(valueChanged(int)), m_scene, SLOT(slotUpdateFontSize(int)));
408
409     // a gradient background
410     /*QRadialGradient *gradient = new QRadialGradient(0, 0, 10);
411     gradient->setSpread(QGradient::ReflectSpread);
412     scene->setBackgroundBrush(*gradient);*/
413
414     m_frameImage = new QGraphicsPixmapItem();
415     QTransform qtrans;
416     qtrans.scale(2.0, 2.0);
417     m_frameImage->setTransform(qtrans);
418     m_frameImage->setZValue(-1200);
419     m_frameImage->setFlags(0);
420     displayBackgroundFrame();
421     graphicsView->scene()->addItem(m_frameImage);
422
423     connect(m_scene, SIGNAL(selectionChanged()), this , SLOT(selectionChanged()));
424     connect(m_scene, SIGNAL(itemMoved()), this , SLOT(selectionChanged()));
425     connect(m_scene, SIGNAL(sceneZoom(bool)), this , SLOT(slotZoom(bool)));
426     connect(m_scene, SIGNAL(actionFinished()), this , SLOT(slotSelectTool()));
427     //connect(m_scene, SIGNAL(actionFinished()), this , SLOT(selectionChanged()));
428     connect(m_scene, SIGNAL(newRect(QGraphicsRectItem *)), this , SLOT(slotNewRect(QGraphicsRectItem *)));
429     connect(m_scene, SIGNAL(newText(QGraphicsTextItem *)), this , SLOT(slotNewText(QGraphicsTextItem *)));
430     connect(zoom_slider, SIGNAL(valueChanged(int)), this , SLOT(slotUpdateZoom(int)));
431
432     QPen framepen(Qt::DotLine);
433     framepen.setColor(Qt::red);
434
435     m_frameBorder = new QGraphicsRectItem(QRectF(0, 0, m_frameWidth, m_frameHeight));
436     m_frameBorder->setPen(framepen);
437     m_frameBorder->setZValue(-1100);
438     m_frameBorder->setBrush(Qt::transparent);
439     m_frameBorder->setFlags(0);
440     graphicsView->scene()->addItem(m_frameBorder);
441
442     // mbd: load saved settings
443     readChoices();
444
445     graphicsView->show();
446     //graphicsView->setRenderHint(QPainter::Antialiasing);
447     graphicsView->setInteractive(true);
448     //graphicsView->resize(400, 300);
449     kDebug() << "// TITLE WIDGWT: " << graphicsView->viewport()->width() << "x" << graphicsView->viewport()->height();
450     //toolBox->setItemEnabled(2, false);
451     m_startViewport = new QGraphicsRectItem(QRectF(0, 0, m_frameWidth, m_frameHeight));
452     m_endViewport = new QGraphicsRectItem(QRectF(0, 0, m_frameWidth, m_frameHeight));
453     m_startViewport->setData(0, m_frameWidth);
454     m_startViewport->setData(1, m_frameHeight);
455     m_endViewport->setData(0, m_frameWidth);
456     m_endViewport->setData(1, m_frameHeight);
457
458     if(!url.isEmpty()) loadTitle(url);
459     else {
460         slotTextTool();
461         QTimer::singleShot(200, this, SLOT(slotAdjustZoom()));
462     }
463     initAnimation();
464     connect(anim_start, SIGNAL(toggled(bool)), this, SLOT(slotAnimStart(bool)));
465     connect(anim_end, SIGNAL(toggled(bool)), this, SLOT(slotAnimEnd(bool)));
466     connect(templateBox, SIGNAL(currentIndexChanged(int)), this, SLOT(templateIndexChanged(int)));
467
468     buttonBox->button(QDialogButtonBox::Ok)->setEnabled(KdenliveSettings::hastitleproducer());
469     refreshTitleTemplates();
470     //templateBox->setIconSize(QSize(60,60));
471     templateBox->clear();
472     templateBox->addItem("");
473     foreach(TitleTemplate t, titletemplates) {
474         templateBox->addItem(t.icon, t.name, t.file);
475     }
476     lastDocumentHash = QCryptographicHash::hash(xml().toString().toAscii(), QCryptographicHash::Md5).toHex();
477 }
478
479 TitleWidget::~TitleWidget()
480 {
481     delete m_buttonRect;
482     delete m_buttonText;
483     delete m_buttonImage;
484     delete m_buttonCursor;
485     delete m_buttonSave;
486     delete m_buttonLoad;
487     delete m_unicodeAction;
488     delete m_zUp;
489     delete m_zDown;
490     delete m_zTop;
491     delete m_zBottom;
492     delete m_selectAll;
493     delete m_selectText;
494     delete m_selectRects;
495     delete m_selectImages;
496     delete m_unselectAll;
497
498     delete m_unicodeDialog;
499     delete m_frameBorder;
500     delete m_frameImage;
501     delete m_startViewport;
502     delete m_endViewport;
503     delete m_scene;
504     delete m_signalMapper;
505 }
506
507 //static
508 QStringList TitleWidget::getFreeTitleInfo(const KUrl &projectUrl, bool isClone)
509 {
510     QStringList result;
511     QString titlePath = projectUrl.path(KUrl::AddTrailingSlash) + "titles/";
512     KStandardDirs::makeDir(titlePath);
513     titlePath.append((isClone == false) ? "title" : "clone");
514     int counter = 0;
515     QString path;
516     while(path.isEmpty() || QFile::exists(path)) {
517         counter++;
518         path = titlePath + QString::number(counter).rightJustified(3, '0', false) + ".png";
519     }
520     result.append(((isClone == false) ? i18n("Title") : i18n("Clone")) + ' ' + QString::number(counter).rightJustified(3, '0', false));
521     result.append(path);
522     return result;
523 }
524
525 // static
526 QString TitleWidget::getTitleResourceFromName(const KUrl &projectUrl, const QString &titleName)
527 {
528     QStringList result;
529     QString titlePath = projectUrl.path(KUrl::AddTrailingSlash) + "titles/";
530     KStandardDirs::makeDir(titlePath);
531     return titlePath + titleName + ".png";
532 }
533
534 // static
535 QStringList TitleWidget::extractImageList(QString xml)
536 {
537     QStringList result;
538     if(xml.isEmpty()) return result;
539     QDomDocument doc;
540     doc.setContent(xml);
541     QDomNodeList images = doc.elementsByTagName("content");
542     for(int i = 0; i < images.count(); i++) {
543         if(images.at(i).toElement().hasAttribute("url"))
544             result.append(images.at(i).toElement().attribute("url"));
545     }
546     return result;
547 }
548
549 // static
550 QStringList TitleWidget::extractFontList(QString xml)
551 {
552     QStringList result;
553     if(xml.isEmpty()) return result;
554     QDomDocument doc;
555     doc.setContent(xml);
556     QDomNodeList images = doc.elementsByTagName("content");
557     for(int i = 0; i < images.count(); i++) {
558         if(images.at(i).toElement().hasAttribute("font"))
559             result.append(images.at(i).toElement().attribute("font"));
560     }
561     return result;
562 }
563 //static
564 void TitleWidget::refreshTitleTemplates()
565 {
566     QStringList titlenamelist = QStringList() << i18n("None");
567     QStringList titlefiles = QStringList() << QString();
568     QStringList filters;
569     filters << "*.kdenlivetitle" ;
570     titletemplates.clear();
571     QStringList titleTemplates = KGlobal::dirs()->findDirs("appdata", "titles");
572     foreach(const QString & folder, titleTemplates) {
573         QStringList filesnames = QDir(folder).entryList(filters, QDir::Files);
574         foreach(const QString & fname, filesnames) {
575             //titlenamelist.append(fname);
576             //titlefiles.append(KUrl(folder).path(KUrl::AddTrailingSlash) + fname);
577             TitleTemplate t;
578             t.name = fname;
579             t.file = KUrl(folder).path(KUrl::AddTrailingSlash) + fname;
580             t.icon = QIcon(KThumb::getImage(t.file, 0, 60, 60));
581             titletemplates.append(t);
582         }
583     }
584     kDebug()  << titlenamelist << titlefiles;
585 }
586 void TitleWidget::templateIndexChanged(int index)
587 {
588     QString item = templateBox->itemData(index).toString();
589     if(item != "") {
590         if(lastDocumentHash != QCryptographicHash::hash(xml().toString().toAscii(), QCryptographicHash::Md5).toHex()) {
591             if(KMessageBox::questionYesNo(this, i18n("Do you really want to load a new template? Changes in this title will be lost!")) == KMessageBox::No) return;
592         }
593         loadTitle(item);
594
595         // mbt 1607: Add property to distinguish between unchanged template titles and user titles.
596         // Text of unchanged template titles should be selected when clicked.
597         QList<QGraphicsItem *> list = graphicsView->scene()->items();
598         foreach(QGraphicsItem * qgItem, list) {
599             if(qgItem->type() == TEXTITEM) {
600                 QGraphicsTextItem *i;
601                 i = static_cast<QGraphicsTextItem *>(qgItem);
602                 i->setProperty("isTemplate", "true");
603                 i->setProperty("templateText", i->toHtml());
604             }
605
606         }
607         lastDocumentHash = QCryptographicHash::hash(xml().toString().toAscii(), QCryptographicHash::Md5).toHex();
608     }
609 }
610 //virtual
611 void TitleWidget::resizeEvent(QResizeEvent * /*event*/)
612 {
613     //slotAdjustZoom();
614 }
615
616 void TitleWidget::slotTextTool()
617 {
618     m_scene->setTool(TITLE_TEXT);
619     showToolbars(TITLE_TEXT);
620     checkButton(TITLE_TEXT);
621 }
622
623 void TitleWidget::slotRectTool()
624 {
625     m_scene->setTool(TITLE_RECTANGLE);
626     showToolbars(TITLE_RECTANGLE);
627     checkButton(TITLE_RECTANGLE);
628 }
629
630 void TitleWidget::slotSelectTool()
631 {
632     m_scene->setTool(TITLE_SELECT);
633
634     // Find out which toolbars need to be shown, depending on selected item
635     TITLETOOL t = TITLE_SELECT;
636     QList<QGraphicsItem *> l = graphicsView->scene()->selectedItems();
637     if(l.size() > 0) {
638         switch(l.at(0)->type()) {
639         case TEXTITEM:
640             t = TITLE_TEXT;
641             break;
642         case RECTITEM:
643             t = TITLE_RECTANGLE;
644             break;
645         case IMAGEITEM:
646             t = TITLE_IMAGE;
647             break;
648         }
649     }
650
651     enableToolbars(t);
652     if(t == TITLE_RECTANGLE && (l.at(0) == m_endViewport || l.at(0) == m_startViewport)) {
653         //graphicsView->centerOn(l.at(0));
654         t = TITLE_SELECT;
655     }
656     showToolbars(t);
657
658     if(l.size() > 0) {
659         updateCoordinates(l.at(0));
660         updateDimension(l.at(0));
661         updateRotZoom(l.at(0));
662     }
663
664     checkButton(TITLE_SELECT);
665 }
666
667 void TitleWidget::slotImageTool()
668 {
669     // TODO: find a way to get a list of all supported image types...
670     QString allExtensions = "image/gif image/jpeg image/png image/x-tga image/x-bmp image/svg+xml image/tiff image/x-xcf-gimp image/x-vnd.adobe.photoshop image/x-pcx image/x-exr";
671     KUrl url = KFileDialog::getOpenUrl(KUrl(), allExtensions, this, i18n("Load Image")); //"*.svg *.png *.jpg *.jpeg *.gif *.raw"
672     if(!url.isEmpty()) {
673         if(url.path().endsWith(".svg")) {
674             QGraphicsSvgItem *svg = new QGraphicsSvgItem(url.toLocalFile());
675             svg->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
676             svg->setZValue(m_count++);
677             svg->setData(Qt::UserRole, url.path());
678             graphicsView->scene()->addItem(svg);
679         } else {
680             QPixmap pix(url.path());
681             QGraphicsPixmapItem *image = new QGraphicsPixmapItem(pix);
682             image->setShapeMode(QGraphicsPixmapItem::BoundingRectShape);
683             image->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
684             image->setData(Qt::UserRole, url.path());
685             image->setZValue(m_count++);
686             graphicsView->scene()->addItem(image);
687         }
688     }
689     m_scene->setTool(TITLE_SELECT);
690     showToolbars(TITLE_SELECT);
691     checkButton(TITLE_SELECT);
692 }
693
694 void TitleWidget::showToolbars(TITLETOOL toolType)
695 {
696     toolbar_stack->setCurrentIndex((int) toolType);
697 }
698
699 void TitleWidget::enableToolbars(TITLETOOL toolType)
700 {
701     // TITLETOOL is defined in graphicsscenerectmove.h
702     bool enable = false;
703     if(toolType == TITLE_RECTANGLE || toolType == TITLE_IMAGE) enable = true;
704     value_w->setEnabled(enable);
705     value_h->setEnabled(enable);
706 }
707
708 void TitleWidget::checkButton(TITLETOOL toolType)
709 {
710     bool bSelect = false;
711     bool bText = false;
712     bool bRect = false;
713     bool bImage = false;
714
715     switch(toolType) {
716     case TITLE_SELECT:
717         bSelect = true;
718         break;
719     case TITLE_TEXT:
720         bText = true;
721         break;
722     case TITLE_RECTANGLE:
723         bRect = true;
724         break;
725     case TITLE_IMAGE:
726         bImage = true;
727         break;
728     default:
729         break;
730     }
731
732     m_buttonCursor->setChecked(bSelect);
733     m_buttonText->setChecked(bText);
734     m_buttonRect->setChecked(bRect);
735     m_buttonImage->setChecked(bImage);
736 }
737
738 void TitleWidget::displayBackgroundFrame()
739 {
740     if(!displayBg->isChecked()) {
741         QPixmap bg(m_frameWidth / 2, m_frameHeight / 2);
742         QPixmap pattern(20, 20);
743         pattern.fill();
744         QColor bgcolor(210, 210, 210);
745         QPainter p;
746         p.begin(&pattern);
747         p.fillRect(QRect(0, 0, 10, 10), bgcolor);
748         p.fillRect(QRect(10, 10, 20, 20), bgcolor);
749         p.end();
750         QBrush br(pattern);
751
752         p.begin(&bg);
753         p.fillRect(bg.rect(), br);
754         p.end();
755         m_frameImage->setPixmap(bg);
756     } else {
757         m_frameImage->setPixmap(QPixmap::fromImage(m_render->extractFrame((int) m_render->seekPosition().frames(m_render->fps()), m_frameWidth / 2, m_frameHeight / 2)));
758     }
759 }
760
761 void TitleWidget::initAnimation()
762 {
763     align_box->setEnabled(false);
764     QPen startpen(Qt::DotLine);
765     QPen endpen(Qt::DashDotLine);
766     startpen.setColor(QColor(100, 200, 100, 140));
767     endpen.setColor(QColor(200, 100, 100, 140));
768
769     m_startViewport->setPen(startpen);
770     m_endViewport->setPen(endpen);
771
772     m_startViewport->setZValue(-1000);
773     m_endViewport->setZValue(-1000);
774
775     m_startViewport->setFlags(0);
776     m_endViewport->setFlags(0);
777
778     graphicsView->scene()->addItem(m_startViewport);
779     graphicsView->scene()->addItem(m_endViewport);
780
781     connect(keep_aspect, SIGNAL(toggled(bool)), this, SLOT(slotKeepAspect(bool)));
782     connect(resize50, SIGNAL(clicked()), this, SLOT(slotResize50()));
783     connect(resize100, SIGNAL(clicked()), this, SLOT(slotResize100()));
784     connect(resize200, SIGNAL(clicked()), this, SLOT(slotResize200()));
785 }
786
787 void TitleWidget::slotUpdateZoom(int pos)
788 {
789     m_scene->setZoom((double) pos / 100);
790     zoom_label->setText(QString::number(pos) + '%');
791 }
792
793 void TitleWidget::slotZoom(bool up)
794 {
795     int pos = zoom_slider->value();
796     if(up) pos++;
797     else pos--;
798     zoom_slider->setValue(pos);
799 }
800
801 void TitleWidget::slotAdjustZoom()
802 {
803     /*double scalex = graphicsView->width() / (double)(m_frameWidth * 1.2);
804     double scaley = graphicsView->height() / (double)(m_frameHeight * 1.2);
805     if (scalex > scaley) scalex = scaley;
806     int zoompos = (int)(scalex * 7 + 0.5);*/
807     graphicsView->fitInView(m_frameBorder, Qt::KeepAspectRatio);
808     int zoompos = graphicsView->matrix().m11() * 100;
809     zoom_slider->setValue(zoompos);
810     graphicsView->centerOn(m_frameBorder);
811 }
812
813 void TitleWidget::slotZoomOneToOne()
814 {
815     zoom_slider->setValue(100);
816     graphicsView->centerOn(m_frameBorder);
817 }
818
819 void TitleWidget::slotNewRect(QGraphicsRectItem * rect)
820 {
821     updateAxisButtons(rect); // back to default
822
823     QColor f = rectFColor->color();
824     f.setAlpha(rectFAlpha->value());
825     QPen penf(f);
826     penf.setWidth(rectLineWidth->value());
827     penf.setJoinStyle(Qt::RoundJoin);
828     rect->setPen(penf);
829     QColor b = rectBColor->color();
830     b.setAlpha(rectBAlpha->value());
831     rect->setBrush(QBrush(b));
832     rect->setZValue(m_count++);
833     rect->setData(ZOOMFACTOR, 100);
834     //setCurrentItem(rect);
835     //graphicsView->setFocus();
836 }
837
838 void TitleWidget::slotNewText(QGraphicsTextItem *tt)
839 {
840     updateAxisButtons(tt); // back to default
841
842     QFont font = font_family->currentFont();
843     font.setPixelSize(font_size->value());
844     // mbd: issue 551:
845     font.setWeight(font_weight_box->itemData(font_weight_box->currentIndex()).toInt());
846     font.setItalic(buttonItalic->isChecked());
847     font.setUnderline(buttonUnder->isChecked());
848
849     tt->setFont(font);
850     QColor color = fontColorButton->color();
851     color.setAlpha(textAlpha->value());
852     tt->setDefaultTextColor(color);
853
854     QTextCursor cur(tt->document());
855     cur.select(QTextCursor::Document);
856     QTextBlockFormat format = cur.blockFormat();
857     QTextCharFormat cformat = cur.charFormat();
858     QColor outlineColor = textOutlineColor->color();
859     outlineColor.setAlpha(textOutlineAlpha->value());
860     double outlineWidth = textOutline->value() / 10.0;
861
862     tt->setData(101, outlineWidth);
863     tt->setData(102, outlineColor);
864     if(outlineWidth > 0.0) cformat.setTextOutline(QPen(outlineColor, outlineWidth));
865
866     cformat.setForeground(QBrush(color));
867     cur.setCharFormat(cformat);
868     cur.setBlockFormat(format);
869     tt->setTextCursor(cur);
870     tt->setZValue(m_count++);
871     setCurrentItem(tt);
872 }
873
874 void TitleWidget::setFontBoxWeight(int weight)
875 {
876     int index = font_weight_box->findData(weight);
877     if(index < 0) {
878         index = font_weight_box->findData(QFont::Normal);
879     }
880     font_weight_box->setCurrentIndex(index);
881 }
882
883 void TitleWidget::setCurrentItem(QGraphicsItem *item)
884 {
885     m_scene->setSelectedItem(item);
886 }
887
888 void TitleWidget::zIndexChanged(int v)
889 {
890     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
891     if(l.size() >= 1) {
892         l[0]->setZValue(v);
893     }
894 }
895
896 void TitleWidget::selectionChanged()
897 {
898     if(m_scene->tool() != TITLE_SELECT) return;
899
900     std::cout << "Number of selected items: " << graphicsView->scene()->selectedItems().length() << "\n";
901
902     QList<QGraphicsItem *> l;
903
904     // mbt 1607: One text item might have grabbed the keyboard.
905     // Ungrab it for all items that are not selected, otherwise
906     // text input would only work for the text item that grabbed
907     // the keyboard last.
908     l = graphicsView->scene()->items();
909     foreach(QGraphicsItem * item, l) {
910         if(item->type() == TEXTITEM && !item->isSelected()) {
911             QGraphicsTextItem *i = static_cast<QGraphicsTextItem *>(item);
912             i->ungrabKeyboard();
913         }
914     }
915
916     l = graphicsView->scene()->selectedItems();
917     
918     if (l.size() > 0) {
919         buttonUnselectAll->setEnabled(true);
920     } else {
921         buttonUnselectAll->setEnabled(false);
922     }
923     if (l.size() >= 2) {
924         buttonSelectText->setEnabled(true);
925         buttonSelectRects->setEnabled(true);
926         buttonSelectImages->setEnabled(true);
927     } else {
928         buttonSelectText->setEnabled(false);
929         buttonSelectRects->setEnabled(false);
930         buttonSelectImages->setEnabled(false);
931     }
932     
933     
934     //toolBox->setItemEnabled(2, false);
935     //toolBox->setItemEnabled(3, false);
936     effect_list->blockSignals(true);
937     value_x->blockSignals(true);
938     value_y->blockSignals(true);
939     value_w->blockSignals(true);
940     value_h->blockSignals(true);
941     itemzoom->blockSignals(true);
942     itemrotatex->blockSignals(true);
943     itemrotatey->blockSignals(true);
944     itemrotatez->blockSignals(true);
945     if(l.size() == 0) {
946         effect_stack->setHidden(true);
947         effect_frame->setEnabled(false);
948         effect_list->setCurrentIndex(0);
949         bool blockX = !origin_x_left->signalsBlocked();
950         bool blockY = !origin_y_top->signalsBlocked();
951         if(blockX) origin_x_left->blockSignals(true);
952         if(blockY) origin_y_top->blockSignals(true);
953         origin_x_left->setChecked(false);
954         origin_y_top->setChecked(false);
955         updateTextOriginX();
956         updateTextOriginY();
957         enableToolbars(TITLE_SELECT);
958         if(blockX) origin_x_left->blockSignals(false);
959         if(blockY) origin_y_top->blockSignals(false);
960         itemzoom->setEnabled(false);
961         itemrotatex->setEnabled(false);
962         itemrotatey->setEnabled(false);
963         itemrotatez->setEnabled(false);
964         frame_properties->setEnabled(false);
965     } else if(l.size() == 1) {
966         effect_frame->setEnabled(true);
967         frame_properties->setEnabled(true);
968         if(l.at(0) != m_startViewport && l.at(0) != m_endViewport) {
969             itemzoom->setEnabled(true);
970             itemrotatex->setEnabled(true);
971             itemrotatey->setEnabled(true);
972             itemrotatez->setEnabled(true);
973         } else {
974             itemzoom->setEnabled(false);
975             itemrotatex->setEnabled(false);
976             itemrotatey->setEnabled(false);
977             itemrotatez->setEnabled(false);
978             updateInfoText();
979         }
980         if(l.at(0)->type() == TEXTITEM) {
981             showToolbars(TITLE_TEXT);
982             QGraphicsTextItem* i = static_cast <QGraphicsTextItem *>(l.at(0));
983             if(!i->data(100).isNull()) {
984                 // Item has an effect
985                 QStringList effdata = i->data(100).toStringList();
986                 QString effectName = effdata.takeFirst();
987                 if(effectName == "typewriter") {
988                     QStringList params = effdata.at(0).split(';');
989                     typewriter_delay->setValue(params.at(0).toInt());
990                     typewriter_start->setValue(params.at(1).toInt());
991                     effect_list->setCurrentIndex(effect_list->findData((int) TYPEWRITEREFFECT));
992                     effect_stack->setHidden(false);
993                 }
994             } else {
995 #if QT_VERSION >= 0x040600
996                 if(i->graphicsEffect()) {
997                     QGraphicsBlurEffect *blur = static_cast <QGraphicsBlurEffect *>(i->graphicsEffect());
998                     if(blur) {
999                         effect_list->setCurrentIndex(effect_list->findData((int) BLUREFFECT));
1000                         int rad = (int) blur->blurRadius();
1001                         blur_radius->setValue(rad);
1002                         effect_stack->setHidden(false);
1003                     } else {
1004                         QGraphicsDropShadowEffect *shad = static_cast <QGraphicsDropShadowEffect *>(i->graphicsEffect());
1005                         if(shad) {
1006                             effect_list->setCurrentIndex(effect_list->findData((int) SHADOWEFFECT));
1007                             shadow_radius->setValue(shad->blurRadius());
1008                             shadow_x->setValue(shad->xOffset());
1009                             shadow_y->setValue(shad->yOffset());
1010                             effect_stack->setHidden(false);
1011                         }
1012                     }
1013                 } else {
1014                     effect_list->setCurrentIndex(effect_list->findData((int) NOEFFECT));
1015                     effect_stack->setHidden(true);
1016                 }
1017 #else
1018                 effect_list->setCurrentIndex(effect_list->findData((int) NOEFFECT));
1019                 effect_stack->setHidden(true);
1020 #endif
1021             }
1022             //if (l[0]->hasFocus())
1023             //toolBox->setCurrentIndex(0);
1024             //toolBox->setItemEnabled(2, true);
1025             font_size->blockSignals(true);
1026             font_family->blockSignals(true);
1027             font_weight_box->blockSignals(true);
1028             buttonItalic->blockSignals(true);
1029             buttonUnder->blockSignals(true);
1030             fontColorButton->blockSignals(true);
1031             textAlpha->blockSignals(true);
1032             buttonAlignLeft->blockSignals(true);
1033             buttonAlignRight->blockSignals(true);
1034             buttonAlignNone->blockSignals(true);
1035             buttonAlignCenter->blockSignals(true);
1036
1037             QFont font = i->font();
1038             font_family->setCurrentFont(font);
1039             font_size->setValue(font.pixelSize());
1040             m_scene->slotUpdateFontSize(font.pixelSize());
1041             buttonItalic->setChecked(font.italic());
1042             buttonUnder->setChecked(font.underline());
1043             setFontBoxWeight(font.weight());
1044
1045             QTextCursor cursor(i->document());
1046             cursor.select(QTextCursor::Document);
1047             QColor color = cursor.charFormat().foreground().color();
1048             textAlpha->setValue(color.alpha());
1049             color.setAlpha(255);
1050             fontColorButton->setColor(color);
1051
1052             if(!i->data(101).isNull()) {
1053                 textOutline->blockSignals(true);
1054                 textOutline->setValue(i->data(101).toDouble() * 10);
1055                 textOutline->blockSignals(false);
1056             }
1057             if(!i->data(102).isNull()) {
1058                 textOutlineColor->blockSignals(true);
1059                 textOutlineAlpha->blockSignals(true);
1060                 color = QColor(i->data(102).toString());
1061                 textOutlineAlpha->setValue(color.alpha());
1062                 color.setAlpha(255);
1063                 textOutlineColor->setColor(color);
1064                 textOutlineColor->blockSignals(false);
1065                 textOutlineAlpha->blockSignals(false);
1066             }
1067             QTextCursor cur = i->textCursor();
1068             QTextBlockFormat format = cur.blockFormat();
1069             if(i->textWidth() == -1) buttonAlignNone->setChecked(true);
1070             else if(format.alignment() == Qt::AlignHCenter) buttonAlignCenter->setChecked(true);
1071             else if(format.alignment() == Qt::AlignRight) buttonAlignRight->setChecked(true);
1072             else if(format.alignment() == Qt::AlignLeft) buttonAlignLeft->setChecked(true);
1073
1074             font_size->blockSignals(false);
1075             font_family->blockSignals(false);
1076             font_weight_box->blockSignals(false);
1077             buttonItalic->blockSignals(false);
1078             buttonUnder->blockSignals(false);
1079             fontColorButton->blockSignals(false);
1080             textAlpha->blockSignals(false);
1081             buttonAlignLeft->blockSignals(false);
1082             buttonAlignRight->blockSignals(false);
1083             buttonAlignNone->blockSignals(false);
1084             buttonAlignCenter->blockSignals(false);
1085
1086             // mbt 1607: Select text if the text item is an unchanged template item.
1087             if(i->property("isTemplate").isValid()) {
1088                 cur.setPosition(0, QTextCursor::MoveAnchor);
1089                 cur.select(QTextCursor::Document);
1090                 i->setTextCursor(cur);
1091                 // Make text editable now.
1092                 i->grabKeyboard();
1093                 i->setTextInteractionFlags(Qt::TextEditorInteraction);
1094             }
1095
1096             updateAxisButtons(i);
1097             updateCoordinates(i);
1098             updateDimension(i);
1099             enableToolbars(TITLE_TEXT);
1100
1101         } else if((l.at(0))->type() == RECTITEM) {
1102             showToolbars(TITLE_RECTANGLE);
1103             settingUp = true;
1104             QGraphicsRectItem *rec = static_cast <QGraphicsRectItem *>(l.at(0));
1105             if(rec == m_startViewport || rec == m_endViewport) {
1106                 /*toolBox->setCurrentIndex(3);
1107                 toolBox->widget(0)->setEnabled(false);
1108                 toolBox->widget(1)->setEnabled(false);*/
1109                 enableToolbars(TITLE_SELECT);
1110             } else {
1111                 /*toolBox->widget(0)->setEnabled(true);
1112                 toolBox->widget(1)->setEnabled(true);
1113                 toolBox->setCurrentIndex(0);*/
1114                 //toolBox->setItemEnabled(3, true);
1115                 rectFAlpha->setValue(rec->pen().color().alpha());
1116                 rectBAlpha->setValue(rec->brush().color().alpha());
1117                 //kDebug() << rec->brush().color().alpha();
1118                 QColor fcol = rec->pen().color();
1119                 QColor bcol = rec->brush().color();
1120                 //fcol.setAlpha(255);
1121                 //bcol.setAlpha(255);
1122                 rectFColor->setColor(fcol);
1123                 rectBColor->setColor(bcol);
1124                 settingUp = false;
1125                 rectLineWidth->setValue(rec->pen().width());
1126                 enableToolbars(TITLE_RECTANGLE);
1127             }
1128
1129             updateAxisButtons(l.at(0));
1130             updateCoordinates(rec);
1131             updateDimension(rec);
1132
1133         } else if(l.at(0)->type() == IMAGEITEM) {
1134             showToolbars(TITLE_IMAGE);
1135
1136             updateCoordinates(l.at(0));
1137             updateDimension(l.at(0));
1138
1139             enableToolbars(TITLE_IMAGE);
1140
1141         } else {
1142             //toolBox->setCurrentIndex(0);
1143             showToolbars(TITLE_SELECT);
1144             enableToolbars(TITLE_SELECT);
1145             frame_properties->setEnabled(false);
1146         }
1147         zValue->setValue((int)l.at(0)->zValue());
1148         if(!l.at(0)->data(ZOOMFACTOR).isNull()) itemzoom->setValue(l.at(0)->data(ZOOMFACTOR).toInt());
1149         else itemzoom->setValue((int)(m_transformations.value(l.at(0)).scalex * 100.0 + 0.5));
1150         itemrotatex->setValue((int)(m_transformations.value(l.at(0)).rotatex));
1151         itemrotatey->setValue((int)(m_transformations.value(l.at(0)).rotatey));
1152         itemrotatez->setValue((int)(m_transformations.value(l.at(0)).rotatez));
1153         value_x->blockSignals(false);
1154         value_y->blockSignals(false);
1155         value_w->blockSignals(false);
1156         value_h->blockSignals(false);
1157         itemzoom->blockSignals(false);
1158         itemrotatex->blockSignals(false);
1159         itemrotatey->blockSignals(false);
1160         itemrotatez->blockSignals(false);
1161     } else {
1162         // More than one item selected
1163         //TODO
1164     }
1165     // Tools working on more than one element.
1166     if(l.size() > 0)
1167         effect_list->blockSignals(false);
1168
1169 }
1170
1171 void TitleWidget::slotValueChanged(int type)
1172 {
1173     QList<QGraphicsItem *> l = graphicsView->scene()->selectedItems();
1174     if(l.size() > 0 && l.at(0)->type() == IMAGEITEM) {
1175
1176         int val = 0;
1177         switch(type) {
1178         case ValueWidth:
1179             val = value_w->value();
1180             break;
1181         case ValueHeight:
1182             val = value_h->value();
1183             break;
1184         }
1185
1186         QGraphicsItem *i = l.at(0);
1187         Transform t = m_transformations.value(i);
1188
1189         // Ratio width:height
1190         double phi = (double) i->boundingRect().width() / i->boundingRect().height();
1191         // TODO: proper calculation for rotation around 3 axes
1192         double alpha = (double) t.rotatez / 180.0 * M_PI;
1193
1194         // New length
1195         double length = val;
1196
1197         // Scaling factor
1198         double scale = 1;
1199
1200         switch(type) {
1201         case ValueWidth:
1202             // Add 0.5 because otherwise incrementing by 1 might have no effect
1203             length = val / (cos(alpha) + 1 / phi * sin(alpha)) + 0.5;
1204             scale = length / i->boundingRect().width();
1205             break;
1206         case ValueHeight:
1207             length = val / (phi * sin(alpha) + cos(alpha)) + 0.5;
1208             scale = length / i->boundingRect().height();
1209             break;
1210         }
1211
1212         t.scalex = scale;
1213         t.scaley = scale;
1214         QTransform qtrans;
1215         qtrans.scale(scale, scale);
1216         qtrans.rotate(t.rotatex, Qt::XAxis);
1217         qtrans.rotate(t.rotatey, Qt::YAxis);
1218         qtrans.rotate(t.rotatez, Qt::ZAxis);
1219         i->setTransform(qtrans);
1220         m_transformations[i] = t;
1221
1222         updateDimension(i);
1223         updateRotZoom(i);
1224     }
1225 }
1226
1227 void TitleWidget::slotAdjustSelectedItem()
1228 {
1229     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1230     if(l.size() >= 1) {
1231         if(l.at(0)->type() == RECTITEM) {
1232             //rect item
1233             QGraphicsRectItem *rec = static_cast <QGraphicsRectItem *>(l.at(0));
1234             updatePosition(rec);
1235             rec->setRect(QRect(0, 0, value_w->value(), value_h->value()));
1236         } else if(l.at(0)->type() == TEXTITEM) {
1237             //text item
1238             updatePosition(l.at(0));
1239         } else if(l.at(0)->type() == IMAGEITEM) {
1240             //image item
1241             updatePosition(l.at(0));
1242         }
1243     }
1244 }
1245
1246 void TitleWidget::updateDimension(QGraphicsItem *i)
1247 {
1248     value_w->blockSignals(true);
1249     value_h->blockSignals(true);
1250     zValue->blockSignals(true);
1251
1252     zValue->setValue((int) i->zValue());
1253     if(i->type() == IMAGEITEM) {
1254         // Get multipliers for rotation/scaling
1255
1256         /*Transform t = m_transformations.value(i);
1257         QRectF r = i->boundingRect();
1258         int width = (int) ( abs(r.width()*t.scalex * cos(t.rotate/180.0*M_PI))
1259                     + abs(r.height()*t.scaley * sin(t.rotate/180.0*M_PI)) );
1260         int height = (int) ( abs(r.height()*t.scaley * cos(t.rotate/180*M_PI))
1261                     + abs(r.width()*t.scalex * sin(t.rotate/180*M_PI)) );*/
1262
1263         value_w->setValue(i->sceneBoundingRect().width());
1264         value_h->setValue(i->sceneBoundingRect().height());
1265     } else if(i->type() == RECTITEM) {
1266         QGraphicsRectItem *r = static_cast <QGraphicsRectItem *>(i);
1267         value_w->setValue((int) r->rect().width());
1268         value_h->setValue((int) r->rect().height());
1269     } else if(i->type() == TEXTITEM) {
1270         QGraphicsTextItem *t = static_cast <QGraphicsTextItem *>(i);
1271         value_w->setValue((int) t->boundingRect().width());
1272         value_h->setValue((int) t->boundingRect().height());
1273     }
1274
1275     zValue->blockSignals(false);
1276     value_w->blockSignals(false);
1277     value_h->blockSignals(false);
1278 }
1279
1280 void TitleWidget::updateCoordinates(QGraphicsItem *i)
1281 {
1282     // Block signals emitted by this method
1283     value_x->blockSignals(true);
1284     value_y->blockSignals(true);
1285
1286     if(i->type() == TEXTITEM) {
1287
1288         QGraphicsTextItem *rec = static_cast <QGraphicsTextItem *>(i);
1289
1290         // Set the correct x coordinate value
1291         if(origin_x_left->isChecked()) {
1292             // Origin (0 point) is at m_frameWidth, coordinate axis is inverted
1293             value_x->setValue((int)(m_frameWidth - rec->pos().x() - rec->boundingRect().width()));
1294         } else {
1295             // Origin is at 0 (default)
1296             value_x->setValue((int) rec->pos().x());
1297         }
1298
1299         // Same for y
1300         if(origin_y_top->isChecked()) {
1301             value_y->setValue((int)(m_frameHeight - rec->pos().y() - rec->boundingRect().height()));
1302         } else {
1303             value_y->setValue((int) rec->pos().y());
1304         }
1305
1306     } else if(i->type() == RECTITEM) {
1307
1308         QGraphicsRectItem *rec = static_cast <QGraphicsRectItem *>(i);
1309
1310         if(origin_x_left->isChecked()) {
1311             // Origin (0 point) is at m_frameWidth
1312             value_x->setValue((int)(m_frameWidth - rec->pos().x() - rec->rect().width()));
1313         } else {
1314             // Origin is at 0 (default)
1315             value_x->setValue((int) rec->pos().x());
1316         }
1317
1318         if(origin_y_top->isChecked()) {
1319             value_y->setValue((int)(m_frameHeight - rec->pos().y() - rec->rect().height()));
1320         } else {
1321             value_y->setValue((int) rec->pos().y());
1322         }
1323
1324     } else if(i->type() == IMAGEITEM) {
1325
1326         if(origin_x_left->isChecked()) {
1327             value_x->setValue((int)(m_frameWidth - i->pos().x() - i->sceneBoundingRect().width()));
1328         } else {
1329             value_x->setValue((int) i->pos().x());
1330         }
1331
1332         if(origin_y_top->isChecked()) {
1333             value_y->setValue((int)(m_frameHeight - i->pos().y() - i->sceneBoundingRect().height()));
1334         } else {
1335             value_y->setValue((int) i->pos().y());
1336         }
1337
1338     }
1339
1340     // Stop blocking signals now
1341     value_x->blockSignals(false);
1342     value_y->blockSignals(false);
1343 }
1344
1345 void TitleWidget::updateRotZoom(QGraphicsItem *i)
1346 {
1347     itemzoom->blockSignals(true);
1348     itemrotatex->blockSignals(true);
1349     itemrotatey->blockSignals(true);
1350     itemrotatez->blockSignals(true);
1351
1352     Transform t = m_transformations.value(i);
1353
1354     if(!i->data(ZOOMFACTOR).isNull()) itemzoom->setValue(i->data(ZOOMFACTOR).toInt());
1355     else itemzoom->setValue((int)(t.scalex * 100.0 + 0.5));
1356
1357     itemrotatex->setValue((int)(t.rotatex));
1358     itemrotatey->setValue((int)(t.rotatey));
1359     itemrotatez->setValue((int)(t.rotatez));
1360
1361     itemzoom->blockSignals(false);
1362     itemrotatex->blockSignals(false);
1363     itemrotatey->blockSignals(false);
1364     itemrotatez->blockSignals(false);
1365 }
1366
1367 void TitleWidget::updatePosition(QGraphicsItem *i)
1368 {
1369     if(i->type() == TEXTITEM) {
1370         QGraphicsTextItem *rec = static_cast <QGraphicsTextItem *>(i);
1371
1372         int posX;
1373         if(origin_x_left->isChecked()) {
1374             /*
1375              * Origin of the X axis is at m_frameWidth, and distance from right
1376              * border of the item to the right border of the frame is taken. See
1377              * comment to slotOriginXClicked().
1378              */
1379             posX = m_frameWidth - value_x->value() - rec->boundingRect().width();
1380         } else {
1381             posX = value_x->value();
1382         }
1383
1384         int posY;
1385         if(origin_y_top->isChecked()) {
1386             /* Same for y axis */
1387             posY = m_frameHeight - value_y->value() - rec->boundingRect().height();
1388         } else {
1389             posY = value_y->value();
1390         }
1391
1392         rec->setPos(posX, posY);
1393
1394     } else if(i->type() == RECTITEM) {
1395
1396         QGraphicsRectItem *rec = static_cast <QGraphicsRectItem *>(i);
1397
1398         int posX;
1399         if(origin_x_left->isChecked()) {
1400             posX = m_frameWidth - value_x->value() - rec->rect().width();
1401         } else {
1402             posX = value_x->value();
1403         }
1404
1405         int posY;
1406         if(origin_y_top->isChecked()) {
1407             posY = m_frameHeight - value_y->value() - rec->rect().height();
1408         } else {
1409             posY = value_y->value();
1410         }
1411
1412         rec->setPos(posX, posY);
1413
1414     } else if(i->type() == IMAGEITEM) {
1415         int posX;
1416         if(origin_x_left->isChecked()) {
1417             // Use the sceneBoundingRect because this also regards transformations like zoom
1418             posX = m_frameWidth - value_x->value() - i->sceneBoundingRect().width();
1419         } else {
1420             posX = value_x->value();
1421         }
1422
1423         int posY;
1424         if(origin_y_top->isChecked()) {
1425             posY = m_frameHeight - value_y->value() - i->sceneBoundingRect().height();
1426         } else {
1427             posY = value_y->value();
1428         }
1429
1430         i->setPos(posX, posY);
1431
1432     }
1433
1434 }
1435
1436 void TitleWidget::updateTextOriginX()
1437 {
1438     if(origin_x_left->isChecked()) {
1439         origin_x_left->setText(i18n("\u2212X"));
1440     } else {
1441         origin_x_left->setText(i18n("+X"));
1442     }
1443 }
1444
1445 void TitleWidget::slotOriginXClicked()
1446 {
1447     // Update the text displayed on the button.
1448     updateTextOriginX();
1449
1450     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1451     if(l.size() >= 1) {
1452         updateCoordinates(l.at(0));
1453
1454         // Remember x axis setting
1455         l.at(0)->setData(TitleDocument::OriginXLeft, origin_x_left->isChecked() ?
1456                          TitleDocument::AxisInverted : TitleDocument::AxisDefault);
1457     }
1458     graphicsView->setFocus();
1459 }
1460
1461 void TitleWidget::updateTextOriginY()
1462 {
1463     if(origin_y_top->isChecked()) {
1464         origin_y_top->setText(i18n("\u2212Y"));
1465     } else {
1466         origin_y_top->setText(i18n("+Y"));
1467     }
1468 }
1469
1470 void TitleWidget::slotOriginYClicked()
1471 {
1472     // Update the text displayed on the button.
1473     updateTextOriginY();
1474
1475     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1476     if(l.size() >= 1) {
1477         updateCoordinates(l.at(0));
1478
1479         l.at(0)->setData(TitleDocument::OriginYTop, origin_y_top->isChecked() ?
1480                          TitleDocument::AxisInverted : TitleDocument::AxisDefault);
1481
1482     }
1483     graphicsView->setFocus();
1484 }
1485
1486 void TitleWidget::updateAxisButtons(QGraphicsItem *i)
1487 {
1488     int xAxis = i->data(TitleDocument::OriginXLeft).toInt();
1489     int yAxis = i->data(TitleDocument::OriginYTop).toInt();
1490     origin_x_left->blockSignals(true);
1491     origin_y_top->blockSignals(true);
1492
1493     if(xAxis == TitleDocument::AxisInverted) {
1494         origin_x_left->setChecked(true);
1495     } else {
1496         origin_x_left->setChecked(false);
1497     }
1498     updateTextOriginX();
1499
1500     if(yAxis == TitleDocument::AxisInverted) {
1501         origin_y_top->setChecked(true);
1502     } else {
1503         origin_y_top->setChecked(false);
1504     }
1505     updateTextOriginY();
1506
1507     origin_x_left->blockSignals(false);
1508     origin_y_top->blockSignals(false);
1509 }
1510
1511 void TitleWidget::slotChangeBackground()
1512 {
1513     QColor color = backgroundColor->color();
1514     color.setAlpha(backgroundAlpha->value());
1515     m_frameBorder->setBrush(QBrush(color));
1516 }
1517
1518 void TitleWidget::slotChanged()
1519 {
1520     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1521     if(l.size() >= 1 && l.at(0)->type() == TEXTITEM) {
1522         textChanged(static_cast <QGraphicsTextItem *>(l.at(0)));
1523     }
1524 }
1525
1526 void TitleWidget::textChanged(QGraphicsTextItem *i)
1527 {
1528     /*
1529      * If the user has set origin_x_left (the same for y), we need to look
1530      * whether a text element has been selected. If yes, we need to ensure that
1531      * the right border of the text field remains fixed also when some text has
1532      * been entered.
1533      *
1534      * This is also known as right-justified, with the difference that it is not
1535      * valid for text but for its boundingRect. Text may still be
1536      * left-justified.
1537      */
1538     updateDimension(i);
1539
1540     if(origin_x_left->isChecked() || origin_y_top->isChecked()) {
1541         if(!i->toPlainText().isEmpty())
1542             updatePosition(i);
1543         else {
1544             /*
1545              * Don't do anything if the string is empty. If the position were
1546              * updated here, a newly created text field would be set to the
1547              * position of the last selected text field.
1548              */
1549         }
1550     }
1551
1552     // mbt 1607: Template text has changed; don't auto-select content anymore.
1553     if(i->property("isTemplate").isValid()) {
1554         if(i->property("templateText").isValid()) {
1555             if(i->property("templateText") == i->toHtml()) {
1556                 // Unchanged, do nothing.
1557             } else {
1558                 i->setProperty("isTemplate", QVariant::Invalid);
1559                 i->setProperty("templateText", QVariant::Invalid);
1560             }
1561         }
1562     }
1563 }
1564
1565 void TitleWidget::slotInsertUnicode()
1566 {
1567     m_unicodeDialog->exec();
1568 }
1569
1570 void TitleWidget::slotInsertUnicodeString(QString text)
1571 {
1572     QList<QGraphicsItem *> l = graphicsView->scene()->selectedItems();
1573     if(l.size() > 0) {
1574         if(l.at(0)->type() == TEXTITEM) {
1575             QGraphicsTextItem *t = static_cast <QGraphicsTextItem *>(l.at(0));
1576             t->textCursor().insertText(text);
1577         }
1578     }
1579 }
1580
1581 void TitleWidget::slotUpdateText()
1582 {
1583     QFont font = font_family->currentFont();
1584     font.setPixelSize(font_size->value());
1585     font.setItalic(buttonItalic->isChecked());
1586     font.setUnderline(buttonUnder->isChecked());
1587     font.setWeight(font_weight_box->itemData(font_weight_box->currentIndex()).toInt());
1588     QColor color = fontColorButton->color();
1589     color.setAlpha(textAlpha->value());
1590
1591     QColor outlineColor = textOutlineColor->color();
1592     outlineColor.setAlpha(textOutlineAlpha->value());
1593     double outlineWidth = textOutline->value() / 10.0;
1594
1595     int i;
1596     for(i = 0; i < graphicsView->scene()->selectedItems().length(); i++) {
1597         QGraphicsTextItem* item = NULL;
1598         QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1599         if(l.at(i)->type() == TEXTITEM) {
1600             item = static_cast <QGraphicsTextItem *>(l.at(i));
1601         }
1602         if(!item) {
1603             // No text item, try next one.
1604             continue;
1605         }
1606
1607         // Set alignment of all text in the text item
1608         QTextCursor cur(item->document());
1609         cur.select(QTextCursor::Document);
1610         QTextBlockFormat format = cur.blockFormat();
1611         if(buttonAlignLeft->isChecked() || buttonAlignCenter->isChecked() || buttonAlignRight->isChecked()) {
1612             item->setTextWidth(item->boundingRect().width());
1613             if(buttonAlignCenter->isChecked()) format.setAlignment(Qt::AlignHCenter);
1614             else if(buttonAlignRight->isChecked()) format.setAlignment(Qt::AlignRight);
1615             else if(buttonAlignLeft->isChecked()) format.setAlignment(Qt::AlignLeft);
1616         } else {
1617             format.setAlignment(Qt::AlignLeft);
1618             item->setTextWidth(-1);
1619         }
1620
1621         // Set font properties
1622         item->setFont(font);
1623         QTextCharFormat cformat = cur.charFormat();
1624
1625         item->setData(101, outlineWidth);
1626         item->setData(102, outlineColor);
1627         if(outlineWidth > 0.0) cformat.setTextOutline(QPen(outlineColor, outlineWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
1628
1629         cformat.setForeground(QBrush(color));
1630         cur.setCharFormat(cformat);
1631         cur.setBlockFormat(format);
1632 //  item->setTextCursor(cur);
1633         cur.clearSelection();
1634         item->setTextCursor(cur);
1635     }
1636 }
1637
1638 void TitleWidget::rectChanged()
1639 {
1640     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1641     int i;
1642     for(i = 0; i < l.length(); i++) {
1643         if(l.at(i)->type() == RECTITEM && !settingUp) {
1644             QGraphicsRectItem *rec = static_cast<QGraphicsRectItem *>(l.at(i));
1645             QColor f = rectFColor->color();
1646             f.setAlpha(rectFAlpha->value());
1647             QPen penf(f);
1648             penf.setWidth(rectLineWidth->value());
1649             penf.setJoinStyle(Qt::RoundJoin);
1650             rec->setPen(penf);
1651             QColor b = rectBColor->color();
1652             b.setAlpha(rectBAlpha->value());
1653             rec->setBrush(QBrush(b));
1654         }
1655     }
1656 }
1657
1658 void TitleWidget::itemScaled(int val)
1659 {
1660     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1661     if(l.size() == 1) {
1662         Transform x = m_transformations.value(l.at(0));
1663         x.scalex = (double)val / 100.0;
1664         x.scaley = (double)val / 100.0;
1665         QTransform qtrans;
1666         qtrans.scale(x.scalex, x.scaley);
1667         qtrans.rotate(x.rotatex, Qt::XAxis);
1668         qtrans.rotate(x.rotatey, Qt::YAxis);
1669         qtrans.rotate(x.rotatez, Qt::ZAxis);
1670         l[0]->setTransform(qtrans);
1671         l[0]->setData(ZOOMFACTOR, val);
1672         m_transformations[l.at(0)] = x;
1673         updateDimension(l.at(0));
1674     }
1675 }
1676
1677 void TitleWidget::itemRotateX(qreal val)
1678 {
1679     itemRotate(val, 0);
1680 }
1681
1682 void TitleWidget::itemRotateY(qreal val)
1683 {
1684     itemRotate(val, 1);
1685 }
1686
1687 void TitleWidget::itemRotateZ(qreal val)
1688 {
1689     itemRotate(val, 2);
1690 }
1691
1692 void TitleWidget::itemRotate(qreal val, int axis)
1693 {
1694     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1695     if(l.size() == 1) {
1696         Transform x = m_transformations[l.at(0)];
1697         switch(axis) {
1698         case 0:
1699             x.rotatex = val;
1700             break;
1701         case 1:
1702             x.rotatey = val;
1703             break;
1704         case 2:
1705             x.rotatez = val;
1706             break;
1707         }
1708
1709         l[0]->setData(ROTATEFACTOR, QList<QVariant>() << QVariant(x.rotatex) << QVariant(x.rotatey) << QVariant(x.rotatez));
1710
1711         QTransform qtrans;
1712         qtrans.scale(x.scalex, x.scaley);
1713         qtrans.rotate(x.rotatex, Qt::XAxis);
1714         qtrans.rotate(x.rotatey, Qt::YAxis);
1715         qtrans.rotate(x.rotatez, Qt::ZAxis);
1716         l[0]->setTransform(qtrans);
1717         m_transformations[l.at(0)] = x;
1718         if(l[0]->data(ZOOMFACTOR).isNull()) l[0]->setData(ZOOMFACTOR, 100);
1719         updateDimension(l.at(0));
1720     }
1721 }
1722
1723 void TitleWidget::itemHCenter()
1724 {
1725     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1726     if(l.size() == 1) {
1727         QGraphicsItem *item = l.at(0);
1728         QRectF br = item->sceneBoundingRect();
1729         int width = (int)br.width();
1730         int newPos = (int)((m_frameWidth - width) / 2);
1731         newPos += item->pos().x() - br.left(); // Check item transformation
1732         item->setPos(newPos, item->pos().y());
1733         updateCoordinates(item);
1734     }
1735 }
1736
1737 void TitleWidget::itemVCenter()
1738 {
1739     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1740     if(l.size() == 1) {
1741         QGraphicsItem *item = l.at(0);
1742         QRectF br = item->sceneBoundingRect();
1743         int height = (int)br.height();
1744         int newPos = (int)((m_frameHeight - height) / 2);
1745         newPos += item->pos().y() - br.top(); // Check item transformation
1746         item->setPos(item->pos().x(), newPos);
1747         updateCoordinates(item);
1748     }
1749 }
1750
1751 void TitleWidget::itemTop()
1752 {
1753     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1754     if(l.size() == 1) {
1755         QGraphicsItem *item = l.at(0);
1756         QRectF br = item->sceneBoundingRect();
1757         double diff;
1758         if(br.top() > 0) diff = -br.top();
1759         else diff = -br.bottom();
1760         item->moveBy(0, diff);
1761         updateCoordinates(item);
1762     }
1763 }
1764
1765 void TitleWidget::itemBottom()
1766 {
1767     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1768     if(l.size() == 1) {
1769         QGraphicsItem *item = l.at(0);
1770         QRectF br = item->sceneBoundingRect();
1771         double diff;
1772         if(br.bottom() > m_frameHeight) diff = m_frameHeight - br.top();
1773         else diff = m_frameHeight - br.bottom();
1774         item->moveBy(0, diff);
1775         updateCoordinates(item);
1776     }
1777 }
1778
1779 void TitleWidget::itemLeft()
1780 {
1781     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1782     if(l.size() == 1) {
1783         QGraphicsItem *item = l.at(0);
1784         QRectF br = item->sceneBoundingRect();
1785         double diff;
1786         if(br.left() > 0) diff = -br.left();
1787         else diff = -br.right();
1788         item->moveBy(diff, 0);
1789         updateCoordinates(item);
1790     }
1791 }
1792
1793 void TitleWidget::itemRight()
1794 {
1795     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1796     if(l.size() == 1) {
1797         QGraphicsItem *item = l.at(0);
1798         QRectF br = item->sceneBoundingRect();
1799         double diff;
1800         if(br.right() < m_frameWidth) diff = m_frameWidth - br.right();
1801         else diff = m_frameWidth - br.left();
1802         item->moveBy(diff, 0);
1803         updateCoordinates(item);
1804     }
1805 }
1806
1807 void TitleWidget::setupViewports()
1808 {
1809     //double aspect_ratio = 4.0 / 3.0;//read from project
1810     //better zoom centered, but render uses only the created rect, so no problem to change the zoom function
1811     /*QRectF sp(0, 0, startViewportSize->value() * m_frameWidth / 100.0 , startViewportSize->value()* m_frameHeight / 100.0);
1812     QRectF ep(0, 0, endViewportSize->value() * m_frameWidth / 100.0, endViewportSize->value() * m_frameHeight / 100.0);
1813     // use a polygon thiat uses 16:9 and 4:3 rects forpreview the size in all aspect ratios ?
1814     QPolygonF spoly(sp);
1815     QPolygonF epoly(ep);
1816     spoly.translate(startViewportX->value(), startViewportY->value());
1817     epoly.translate(endViewportX->value(), endViewportY->value());
1818     m_startViewport->setPolygon(spoly);
1819     m_endViewport->setPolygon(epoly);
1820     if (! insertingValues) {
1821         m_startViewport->setData(0, startViewportX->value());
1822         m_startViewport->setData(1, startViewportY->value());
1823         m_startViewport->setData(2, startViewportSize->value());
1824
1825         m_endViewport->setData(0, endViewportX->value());
1826         m_endViewport->setData(1, endViewportY->value());
1827         m_endViewport->setData(2, endViewportSize->value());
1828     }*/
1829 }
1830
1831 void TitleWidget::loadTitle(KUrl url)
1832 {
1833     if(url.isEmpty()) url = KFileDialog::getOpenUrl(KUrl(m_projectTitlePath), "application/x-kdenlivetitle", this, i18n("Load Title"));
1834     if(!url.isEmpty()) {
1835         QList<QGraphicsItem *> items = m_scene->items();
1836         for(int i = 0; i < items.size(); i++) {
1837             if(items.at(i)->zValue() > -1000) delete items.at(i);
1838         }
1839         m_scene->clearTextSelection();
1840         QDomDocument doc;
1841         QString tmpfile;
1842
1843         if(KIO::NetAccess::download(url, tmpfile, 0)) {
1844             QFile file(tmpfile);
1845             if(file.open(QIODevice::ReadOnly)) {
1846                 doc.setContent(&file, false);
1847                 file.close();
1848             } else return;
1849             KIO::NetAccess::removeTempFile(tmpfile);
1850         }
1851         setXml(doc);
1852
1853         /*int out;
1854         m_count = m_titledocument.loadDocument(url, m_startViewport, m_endViewport, &out) + 1;
1855         adjustFrameSize();
1856         title_duration->setText(m_tc.getTimecode(GenTime(out, m_render->fps())));
1857         insertingValues = true;
1858         startViewportX->setValue(m_startViewport->data(0).toInt());
1859         startViewportY->setValue(m_startViewport->data(1).toInt());
1860         startViewportSize->setValue(m_startViewport->data(2).toInt());
1861         endViewportX->setValue(m_endViewport->data(0).toInt());
1862         endViewportY->setValue(m_endViewport->data(1).toInt());
1863         endViewportSize->setValue(m_endViewport->data(2).toInt());
1864
1865         insertingValues = false;
1866         slotSelectTool();
1867         slotAdjustZoom();*/
1868     }
1869 }
1870
1871 void TitleWidget::saveTitle(KUrl url)
1872 {
1873     if(anim_start->isChecked()) slotAnimStart(false);
1874     if(anim_end->isChecked()) slotAnimEnd(false);
1875     if(url.isEmpty()) {
1876         KFileDialog *fs = new KFileDialog(KUrl(m_projectTitlePath), "application/x-kdenlivetitle", this);
1877         fs->setOperationMode(KFileDialog::Saving);
1878         fs->setMode(KFile::File);
1879 #if KDE_IS_VERSION(4,2,0)
1880         fs->setConfirmOverwrite(true);
1881 #endif
1882         fs->setKeepLocation(true);
1883         fs->exec();
1884         url = fs->selectedUrl();
1885         delete fs;
1886     }
1887     if(!url.isEmpty()) {
1888         if(m_titledocument.saveDocument(url, m_startViewport, m_endViewport, m_tc.getFrameCount(title_duration->text()) - 1) == false)
1889             KMessageBox::error(this, i18n("Cannot write to file %1", url.path()));
1890     }
1891 }
1892
1893 QDomDocument TitleWidget::xml()
1894 {
1895     QDomDocument doc = m_titledocument.xml(m_startViewport, m_endViewport);
1896     doc.documentElement().setAttribute("out", m_tc.getFrameCount(title_duration->text()) - 1);
1897     return doc;
1898 }
1899
1900 int TitleWidget::outPoint() const
1901 {
1902     return m_tc.getFrameCount(title_duration->text()) - 1;
1903 }
1904
1905 void TitleWidget::setXml(QDomDocument doc)
1906 {
1907     int out;
1908     m_count = m_titledocument.loadFromXml(doc, m_startViewport, m_endViewport, &out);
1909     adjustFrameSize();
1910     title_duration->setText(m_tc.getTimecode(GenTime(out + 1, m_render->fps())));
1911     /*if (doc.documentElement().hasAttribute("out")) {
1912     GenTime duration = GenTime(doc.documentElement().attribute("out").toDouble() / 1000.0);
1913     title_duration->setText(m_tc.getTimecode(duration));
1914     }
1915     else title_duration->setText(m_tc.getTimecode(GenTime(5000)));*/
1916
1917     QDomElement e = doc.documentElement();
1918     m_transformations.clear();
1919     QList <QGraphicsItem *> items = graphicsView->scene()->items();
1920     const double PI = 4.0 * atan(1.0);
1921     for(int i = 0; i < items.count(); i++) {
1922         QTransform t = items.at(i)->transform();
1923         Transform x;
1924         x.scalex = t.m11();
1925         x.scaley = t.m22();
1926         if(!items.at(i)->data(ROTATEFACTOR).isNull()) {
1927             QList<QVariant> rotlist = items.at(i)->data(ROTATEFACTOR).toList();
1928             if(rotlist.count() >= 3) {
1929                 x.rotatex = rotlist[0].toDouble();
1930                 x.rotatey = rotlist[1].toDouble();
1931                 x.rotatez = rotlist[2].toDouble();
1932
1933                 // Try to adjust zoom
1934                 t.rotate(x.rotatex *(-1), Qt::XAxis);
1935                 t.rotate(x.rotatey *(-1), Qt::YAxis);
1936                 t.rotate(x.rotatez *(-1), Qt::ZAxis);
1937                 x.scalex = t.m11();
1938                 x.scaley = t.m22();
1939             } else {
1940                 x.rotatex = 0;
1941                 x.rotatey = 0;
1942                 x.rotatez = 0;
1943             }
1944         } else {
1945             x.rotatex = 0;
1946             x.rotatey = 0;
1947             x.rotatez = 180. / PI * atan2(-t.m21(), t.m11());
1948         }
1949         m_transformations[items.at(i)] = x;
1950     }
1951     // mbd: Update the GUI color selectors to match the stuff from the loaded document
1952     QColor background_color = m_titledocument.getBackgroundColor();
1953     backgroundAlpha->blockSignals(true);
1954     backgroundColor->blockSignals(true);
1955     backgroundAlpha->setValue(background_color.alpha());
1956     background_color.setAlpha(255);
1957     backgroundColor->setColor(background_color);
1958     backgroundAlpha->blockSignals(false);
1959     backgroundColor->blockSignals(false);
1960
1961     /*startViewportX->setValue(m_startViewport->data(0).toInt());
1962     startViewportY->setValue(m_startViewport->data(1).toInt());
1963     startViewportSize->setValue(m_startViewport->data(2).toInt());
1964     endViewportX->setValue(m_endViewport->data(0).toInt());
1965     endViewportY->setValue(m_endViewport->data(1).toInt());
1966     endViewportSize->setValue(m_endViewport->data(2).toInt());*/
1967
1968     QTimer::singleShot(200, this, SLOT(slotAdjustZoom()));
1969     slotSelectTool();
1970     selectionChanged();
1971 }
1972
1973 void TitleWidget::slotAccepted()
1974 {
1975     if(anim_start->isChecked()) slotAnimStart(false);
1976     if(anim_end->isChecked()) slotAnimEnd(false);
1977     writeChoices();
1978 }
1979
1980 void TitleWidget::writeChoices()
1981 {
1982     // Get a pointer to a shared configuration instance, then get the TitleWidget group.
1983     KSharedConfigPtr config = KGlobal::config();
1984     KConfigGroup titleConfig(config, "TitleWidget");
1985     // Write the entries
1986     titleConfig.writeEntry("font_family", font_family->currentFont());
1987     //titleConfig.writeEntry("font_size", font_size->value());
1988     titleConfig.writeEntry("font_pixel_size", font_size->value());
1989     titleConfig.writeEntry("font_color", fontColorButton->color());
1990     titleConfig.writeEntry("font_alpha", textAlpha->value());
1991     titleConfig.writeEntry("font_outline", textOutline->value());
1992     titleConfig.writeEntry("font_outline_color", textOutlineColor->color());
1993     titleConfig.writeEntry("font_outline_alpha", textOutlineAlpha->value());
1994     titleConfig.writeEntry("font_weight", font_weight_box->itemData(font_weight_box->currentIndex()).toInt());
1995     titleConfig.writeEntry("font_italic", buttonItalic->isChecked());
1996     titleConfig.writeEntry("font_underlined", buttonUnder->isChecked());
1997
1998     titleConfig.writeEntry("rect_foreground_color", rectFColor->color());
1999     titleConfig.writeEntry("rect_foreground_alpha", rectFAlpha->value());
2000     titleConfig.writeEntry("rect_background_color", rectBColor->color());
2001     titleConfig.writeEntry("rect_background_alpha", rectBAlpha->value());
2002     titleConfig.writeEntry("rect_line_width", rectLineWidth->value());
2003
2004     titleConfig.writeEntry("background_color", backgroundColor->color());
2005     titleConfig.writeEntry("background_alpha", backgroundAlpha->value());
2006
2007     //! \todo Not sure if I should sync - it is probably safe to do it
2008     config->sync();
2009
2010 }
2011
2012 void TitleWidget::readChoices()
2013 {
2014     // Get a pointer to a shared configuration instance, then get the TitleWidget group.
2015     KSharedConfigPtr config = KGlobal::config();
2016     KConfigGroup titleConfig(config, "TitleWidget");
2017     // read the entries
2018     font_family->setCurrentFont(titleConfig.readEntry("font_family", font_family->currentFont()));
2019     font_size->setValue(titleConfig.readEntry("font_pixel_size", font_size->value()));
2020     m_scene->slotUpdateFontSize(font_size->value());
2021     fontColorButton->setColor(titleConfig.readEntry("font_color", fontColorButton->color()));
2022     textAlpha->setValue(titleConfig.readEntry("font_alpha", textAlpha->value()));
2023
2024     textOutlineColor->setColor(titleConfig.readEntry("font_outline_color", textOutlineColor->color()));
2025     textOutlineAlpha->setValue(titleConfig.readEntry("font_outline_alpha", textOutlineAlpha->value()));
2026     textOutline->setValue(titleConfig.readEntry("font_outline", textOutline->value()));
2027
2028     int weight;
2029     if(titleConfig.readEntry("font_bold", false)) weight = QFont::Bold;
2030     else weight = titleConfig.readEntry("font_weight", font_weight_box->itemData(font_weight_box->currentIndex()).toInt());
2031     setFontBoxWeight(weight);
2032     buttonItalic->setChecked(titleConfig.readEntry("font_italic", buttonItalic->isChecked()));
2033     buttonUnder->setChecked(titleConfig.readEntry("font_underlined", buttonUnder->isChecked()));
2034
2035     rectFColor->setColor(titleConfig.readEntry("rect_foreground_color", rectFColor->color()));
2036     rectFAlpha->setValue(titleConfig.readEntry("rect_foreground_alpha", rectFAlpha->value()));
2037     rectBColor->setColor(titleConfig.readEntry("rect_background_color", rectBColor->color()));
2038     rectBAlpha->setValue(titleConfig.readEntry("rect_background_alpha", rectBAlpha->value()));
2039     rectLineWidth->setValue(titleConfig.readEntry("rect_line_width", rectLineWidth->value()));
2040
2041     backgroundColor->setColor(titleConfig.readEntry("background_color", backgroundColor->color()));
2042     backgroundAlpha->setValue(titleConfig.readEntry("background_alpha", backgroundAlpha->value()));
2043 }
2044
2045 void TitleWidget::adjustFrameSize()
2046 {
2047     m_frameWidth = m_titledocument.frameWidth();
2048     m_frameHeight = m_titledocument.frameHeight();
2049     m_frameBorder->setRect(0, 0, m_frameWidth, m_frameHeight);
2050     displayBackgroundFrame();
2051 }
2052
2053 void TitleWidget::slotAnimStart(bool anim)
2054 {
2055     if(anim && anim_end->isChecked()) {
2056         anim_end->setChecked(false);
2057         m_endViewport->setZValue(-1000);
2058         m_endViewport->setBrush(QBrush());
2059     }
2060     slotSelectTool();
2061     QList<QGraphicsItem *> list = m_scene->items();
2062     for(int i = 0; i < list.count(); i++) {
2063         if(list.at(i)->zValue() > -1000) {
2064             list.at(i)->setFlag(QGraphicsItem::ItemIsMovable, !anim);
2065             list.at(i)->setFlag(QGraphicsItem::ItemIsSelectable, !anim);
2066         }
2067     }
2068     align_box->setEnabled(anim);
2069     itemzoom->setEnabled(!anim);
2070     itemrotatex->setEnabled(!anim);
2071     itemrotatey->setEnabled(!anim);
2072     itemrotatez->setEnabled(!anim);
2073     frame_toolbar->setEnabled(!anim);
2074     toolbar_stack->setEnabled(!anim);
2075     if(anim) {
2076         keep_aspect->setChecked(!m_startViewport->data(0).isNull());
2077         m_startViewport->setZValue(1100);
2078         QColor col = m_startViewport->pen().color();
2079         col.setAlpha(100);
2080         m_startViewport->setBrush(col);
2081         m_startViewport->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
2082         m_startViewport->setSelected(true);
2083         selectionChanged();
2084         slotSelectTool();
2085         if(m_startViewport->childItems().isEmpty()) addAnimInfoText();
2086     } else {
2087         m_startViewport->setZValue(-1000);
2088         m_startViewport->setBrush(QBrush());
2089         m_startViewport->setFlags(0);
2090         if(!anim_end->isChecked()) deleteAnimInfoText();
2091     }
2092
2093 }
2094
2095 void TitleWidget::slotAnimEnd(bool anim)
2096 {
2097     if(anim && anim_start->isChecked()) {
2098         anim_start->setChecked(false);
2099         m_startViewport->setZValue(-1000);
2100         m_startViewport->setBrush(QBrush());
2101     }
2102     slotSelectTool();
2103     QList<QGraphicsItem *> list = m_scene->items();
2104     for(int i = 0; i < list.count(); i++) {
2105         if(list.at(i)->zValue() > -1000) {
2106             list.at(i)->setFlag(QGraphicsItem::ItemIsMovable, !anim);
2107             list.at(i)->setFlag(QGraphicsItem::ItemIsSelectable, !anim);
2108         }
2109     }
2110     align_box->setEnabled(anim);
2111     itemzoom->setEnabled(!anim);
2112     itemrotatex->setEnabled(!anim);
2113     itemrotatey->setEnabled(!anim);
2114     itemrotatez->setEnabled(!anim);
2115     frame_toolbar->setEnabled(!anim);
2116     toolbar_stack->setEnabled(!anim);
2117     if(anim) {
2118         keep_aspect->setChecked(!m_endViewport->data(0).isNull());
2119         m_endViewport->setZValue(1100);
2120         QColor col = m_endViewport->pen().color();
2121         col.setAlpha(100);
2122         m_endViewport->setBrush(col);
2123         m_endViewport->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
2124         m_endViewport->setSelected(true);
2125         selectionChanged();
2126         slotSelectTool();
2127         if(m_endViewport->childItems().isEmpty()) addAnimInfoText();
2128     } else {
2129         m_endViewport->setZValue(-1000);
2130         m_endViewport->setBrush(QBrush());
2131         m_endViewport->setFlags(0);
2132         if(!anim_start->isChecked()) deleteAnimInfoText();
2133     }
2134 }
2135
2136 void TitleWidget::addAnimInfoText()
2137 {
2138     // add text to anim viewport
2139     QGraphicsTextItem *t = new QGraphicsTextItem(i18n("Start"), m_startViewport);
2140     QGraphicsTextItem *t2 = new QGraphicsTextItem(i18n("End"), m_endViewport);
2141     QFont font = t->font();
2142     font.setPixelSize(m_startViewport->rect().width() / 10);
2143     QColor col = m_startViewport->pen().color();
2144     col.setAlpha(255);
2145     t->setDefaultTextColor(col);
2146     t->setFont(font);
2147     font.setPixelSize(m_endViewport->rect().width() / 10);
2148     col = m_endViewport->pen().color();
2149     col.setAlpha(255);
2150     t2->setDefaultTextColor(col);
2151     t2->setFont(font);
2152 }
2153
2154 void TitleWidget::updateInfoText()
2155 {
2156     // update info text font
2157     if(!m_startViewport->childItems().isEmpty()) {
2158         QGraphicsTextItem *item = static_cast <QGraphicsTextItem *>(m_startViewport->childItems().at(0));
2159         if(item) {
2160             QFont font = item->font();
2161             font.setPixelSize(m_startViewport->rect().width() / 10);
2162             item->setFont(font);
2163         }
2164     }
2165     if(!m_endViewport->childItems().isEmpty()) {
2166         QGraphicsTextItem *item = static_cast <QGraphicsTextItem *>(m_endViewport->childItems().at(0));
2167         if(item) {
2168             QFont font = item->font();
2169             font.setPixelSize(m_endViewport->rect().width() / 10);
2170             item->setFont(font);
2171         }
2172     }
2173 }
2174
2175 void TitleWidget::deleteAnimInfoText()
2176 {
2177     // end animation editing, remove info text
2178     while(!m_startViewport->childItems().isEmpty()) {
2179         QGraphicsItem *item = m_startViewport->childItems().at(0);
2180         m_scene->removeItem(item);
2181         delete item;
2182     }
2183     while(!m_endViewport->childItems().isEmpty()) {
2184         QGraphicsItem *item = m_endViewport->childItems().at(0);
2185         m_scene->removeItem(item);
2186         delete item;
2187     }
2188 }
2189
2190 void TitleWidget::slotKeepAspect(bool keep)
2191 {
2192     if(m_endViewport->zValue() == 1100) {
2193         m_endViewport->setData(0, keep == true ? m_frameWidth : QVariant());
2194         m_endViewport->setData(1, keep == true ? m_frameHeight : QVariant());
2195     } else {
2196         m_startViewport->setData(0, keep == true ? m_frameWidth : QVariant());
2197         m_startViewport->setData(1, keep == true ? m_frameHeight : QVariant());
2198     }
2199 }
2200
2201 void TitleWidget::slotResize50()
2202 {
2203     if(m_endViewport->zValue() == 1100) {
2204         m_endViewport->setRect(0, 0, m_frameWidth / 2, m_frameHeight / 2);
2205     } else m_startViewport->setRect(0, 0, m_frameWidth / 2, m_frameHeight / 2);
2206 }
2207
2208 void TitleWidget::slotResize100()
2209 {
2210     if(m_endViewport->zValue() == 1100) {
2211         m_endViewport->setRect(0, 0, m_frameWidth, m_frameHeight);
2212     } else m_startViewport->setRect(0, 0, m_frameWidth, m_frameHeight);
2213 }
2214
2215 void TitleWidget::slotResize200()
2216 {
2217     if(m_endViewport->zValue() == 1100) {
2218         m_endViewport->setRect(0, 0, m_frameWidth * 2, m_frameHeight * 2);
2219     } else m_startViewport->setRect(0, 0, m_frameWidth * 2, m_frameHeight * 2);
2220 }
2221
2222 void TitleWidget::slotAddEffect(int ix)
2223 {
2224     QList<QGraphicsItem *> list = graphicsView->scene()->selectedItems();
2225     int effect = effect_list->itemData(ix).toInt();
2226
2227     if(list.size() == 1) {
2228         if(effect == NOEFFECT)
2229             effect_stack->setHidden(true);
2230         else {
2231             effect_stack->setCurrentIndex(effect - 1);
2232             effect_stack->setHidden(false);
2233         }
2234     } else // Hide the effects stack when more than one element is selected.
2235         effect_stack->setHidden(true);
2236
2237     foreach(QGraphicsItem * item, list) {
2238         switch(effect) {
2239         case NOEFFECT:
2240             item->setData(100, QVariant());
2241 #if QT_VERSION >= 0x040600
2242             item->setGraphicsEffect(0);
2243 #endif
2244             break;
2245         case TYPEWRITEREFFECT:
2246             /*
2247              * Allow the user to set the typewriter effect to more than one
2248              * element, but do not add it to non-text elements.
2249              */
2250             if(item->type() == TEXTITEM) {
2251                 QStringList effdata = QStringList() << "typewriter" << QString::number(typewriter_delay->value()) + ";" + QString::number(typewriter_start->value());
2252                 item->setData(100, effdata);
2253             }
2254             break;
2255 #if QT_VERSION >= 0x040600
2256             // Do not remove the non-QGraphicsEffects.
2257         case BLUREFFECT:
2258             item->setGraphicsEffect(new QGraphicsBlurEffect());
2259             break;
2260         case SHADOWEFFECT:
2261             item->setGraphicsEffect(new QGraphicsDropShadowEffect());
2262             break;
2263 #endif
2264         }
2265     }
2266 }
2267
2268 void TitleWidget::slotFontText(const QString& s)
2269 {
2270     const QFont f(s);
2271     if(f.exactMatch()) {
2272         // Font really exists (could also just be a «d» if the user
2273         // starts typing «dejavu» for example).
2274         font_family->setCurrentFont(f);
2275     }
2276     // Note: Typing dejavu serif does not recognize the font (takes sans)
2277     // in older Qt versions. Case must match there (except for first letter)
2278 }
2279
2280 void TitleWidget::slotEditTypewriter(int /*ix*/)
2281 {
2282     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
2283     if(l.size() == 1) {
2284         QStringList effdata = QStringList() << "typewriter" << QString::number(typewriter_delay->value()) + ";" + QString::number(typewriter_start->value());
2285         l[0]->setData(100, effdata);
2286     }
2287 }
2288
2289 void TitleWidget::slotEditBlur(int ix)
2290 {
2291 #if QT_VERSION < 0x040600
2292     return;
2293 #else
2294     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
2295     if(l.size() == 1) {
2296         QGraphicsEffect *eff = l[0]->graphicsEffect();
2297         QGraphicsBlurEffect *blur = static_cast <QGraphicsBlurEffect *>(eff);
2298         if(blur) blur->setBlurRadius(ix);
2299     }
2300 #endif
2301 }
2302
2303 void TitleWidget::slotEditShadow()
2304 {
2305 #if QT_VERSION < 0x040600
2306     return;
2307 #else
2308     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
2309     if(l.size() == 1) {
2310         QGraphicsEffect *eff = l[0]->graphicsEffect();
2311         QGraphicsDropShadowEffect *shadow = static_cast <QGraphicsDropShadowEffect *>(eff);
2312         if(shadow) {
2313             shadow->setBlurRadius(shadow_radius->value());
2314             shadow->setOffset(shadow_x->value(), shadow_y->value());
2315         }
2316     }
2317 #endif
2318 }
2319
2320 qreal TitleWidget::zIndexBounds(bool maxBound, bool intersectingOnly)
2321 {
2322     qreal bound = maxBound ? -99 : 99;
2323     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
2324     if(l.size() > 0) {
2325         QList<QGraphicsItem*> lItems;
2326         // Get items (all or intersecting only)
2327         if(intersectingOnly) {
2328             lItems = graphicsView->scene()->items(l[0]->sceneBoundingRect(), Qt::IntersectsItemShape);
2329         } else {
2330             lItems = graphicsView->scene()->items();
2331         }
2332         if(lItems.size() > 0) {
2333             int n = lItems.size();
2334             qreal z;
2335             if(maxBound) {
2336                 for(int i = 0; i < n; i++) {
2337                     z = lItems[i]->zValue();
2338                     if(z > bound && !lItems[i]->isSelected()) {
2339                         bound = z;
2340                     }
2341                 }
2342             } else {
2343                 // Get minimum z index.
2344                 for(int i = 0; i < n; i++) {
2345                     z = lItems[i]->zValue();
2346                     if(z < bound && !lItems[i]->isSelected() && z > -999) {
2347                         // There are items at the very bottom (background e.g.) with z-index < -1000.
2348                         bound = z;
2349                     }
2350                 }
2351             }
2352         }
2353     }
2354     return bound;
2355 }
2356
2357 void TitleWidget::slotZIndexUp()
2358 {
2359     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
2360     if(l.size() >= 1) {
2361         qreal currentZ = l[0]->zValue();
2362         qreal max = zIndexBounds(true, true);
2363         if(currentZ <= max) {
2364             l[0]->setZValue(currentZ + 1);
2365             updateDimension(l[0]);
2366         }
2367     }
2368 }
2369
2370 void TitleWidget::slotZIndexTop()
2371 {
2372     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
2373     if(l.size() >= 1) {
2374         qreal currentZ = l[0]->zValue();
2375         qreal max = zIndexBounds(true, false);
2376         if(currentZ <= max) {
2377             l[0]->setZValue(max + 1);
2378             updateDimension(l[0]);
2379         }
2380     }
2381 }
2382
2383 void TitleWidget::slotZIndexDown()
2384 {
2385     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
2386     if(l.size() >= 1) {
2387         qreal currentZ = l[0]->zValue();
2388         qreal min = zIndexBounds(false, true);
2389         if(currentZ >= min) {
2390             l[0]->setZValue(currentZ - 1);
2391             updateDimension(l[0]);
2392         }
2393     }
2394 }
2395
2396 void TitleWidget::slotZIndexBottom()
2397 {
2398     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
2399     if(l.size() >= 1) {
2400         qreal currentZ = l[0]->zValue();
2401         qreal min = zIndexBounds(false, false);
2402         if(currentZ >= min) {
2403             l[0]->setZValue(min - 1);
2404             updateDimension(l[0]);
2405         }
2406     }
2407 }
2408
2409 void TitleWidget::slotSelectAll()
2410 {
2411     graphicsView->blockSignals(true);
2412     QList<QGraphicsItem*> l = graphicsView->scene()->items();
2413     for (int i = 0; i < l.size(); i++) {
2414         l.at(i)->setSelected(true);
2415     }
2416     graphicsView->blockSignals(false);
2417     // Notify the GUI of the selection change
2418     selectionChanged();
2419 }
2420
2421 void TitleWidget::selectItems(int itemType)
2422 {
2423     graphicsView->blockSignals(true);
2424     QList<QGraphicsItem*> l;
2425     if (graphicsView->scene()->selectedItems().size() > 0) {
2426         l = graphicsView->scene()->selectedItems();
2427         for (int i = 0; i < l.size(); i++) {
2428             if (l.at(i)->type() != itemType) {
2429                 l.at(i)->setSelected(false);
2430             }
2431         }
2432     } else {
2433         l = graphicsView->scene()->items();
2434         for (int i = 0; i < l.size(); i++) {
2435             if (l.at(i)->type() == itemType) {
2436                 l.at(i)->setSelected(true);
2437             }
2438         }
2439     }
2440     graphicsView->blockSignals(false);
2441     selectionChanged();
2442 }
2443
2444 void TitleWidget::slotSelectText()
2445 {
2446     selectItems(TEXTITEM);
2447 }
2448
2449 void TitleWidget::slotSelectRects()
2450 {
2451     selectItems(RECTITEM);
2452 }
2453
2454 void TitleWidget::slotSelectImages()
2455 {
2456     selectItems(IMAGEITEM);
2457 }
2458
2459 void TitleWidget::slotSelectNone()
2460 {
2461     graphicsView->blockSignals(true);
2462     QList<QGraphicsItem*> l = graphicsView->scene()->items();
2463     for (int i = 0; i < l.size(); i++) {
2464         l.at(i)->setSelected(false);
2465     }
2466     graphicsView->blockSignals(false);
2467     selectionChanged();
2468 }