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