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