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