]> git.sesse.net Git - kdenlive/blob - src/titlewidget.cpp
outline-text
[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     tt->setZValue(m_count++);
672     setCurrentItem(tt);
673 }
674
675 void TitleWidget::setFontBoxWeight(int weight)
676 {
677     int index = font_weight_box->findData(weight);
678     if (index < 0) {
679         index = font_weight_box->findData(QFont::Normal);
680     }
681     font_weight_box->setCurrentIndex(index);
682 }
683
684 void TitleWidget::setCurrentItem(QGraphicsItem *item)
685 {
686     m_scene->setSelectedItem(item);
687 }
688
689 void TitleWidget::zIndexChanged(int v)
690 {
691     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
692     if (l.size() >= 1) {
693         l[0]->setZValue(v);
694     }
695 }
696
697 void TitleWidget::selectionChanged()
698 {
699     if (m_scene->tool() != TITLE_SELECT) return;
700     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
701     //toolBox->setItemEnabled(2, false);
702     //toolBox->setItemEnabled(3, false);
703     value_x->blockSignals(true);
704     value_y->blockSignals(true);
705     value_w->blockSignals(true);
706     value_h->blockSignals(true);
707     itemzoom->blockSignals(true);
708     itemrotate->blockSignals(true);
709     if (l.size() == 0) {
710         effect_stack->setHidden(true);
711         effect_frame->setEnabled(false);
712         effect_list->setCurrentIndex(0);
713         bool blockX = !origin_x_left->signalsBlocked();
714         bool blockY = !origin_y_top->signalsBlocked();
715         if (blockX) origin_x_left->blockSignals(true);
716         if (blockY) origin_y_top->blockSignals(true);
717         origin_x_left->setChecked(false);
718         origin_y_top->setChecked(false);
719         updateTextOriginX();
720         updateTextOriginY();
721         enableToolbars(TITLE_SELECT);
722         if (blockX) origin_x_left->blockSignals(false);
723         if (blockY) origin_y_top->blockSignals(false);
724         itemzoom->setEnabled(false);
725         itemrotate->setEnabled(false);
726         frame_properties->setEnabled(false);
727     } else if (l.size() == 1) {
728         effect_frame->setEnabled(true);
729         frame_properties->setEnabled(true);
730         if (l.at(0) != m_startViewport && l.at(0) != m_endViewport) {
731             itemzoom->setEnabled(true);
732             itemrotate->setEnabled(true);
733         } else {
734             itemzoom->setEnabled(false);
735             itemrotate->setEnabled(false);
736             updateInfoText();
737         }
738         if (l.at(0)->type() == TEXTITEM) {
739             showToolbars(TITLE_TEXT);
740             QGraphicsTextItem* i = static_cast <QGraphicsTextItem *>(l.at(0));
741             if (!i->data(100).isNull()) {
742                 // Item has an effect
743                 QStringList effdata = i->data(100).toStringList();
744                 QString effectName = effdata.takeFirst();
745                 if (effectName == "typewriter") {
746                     QStringList params = effdata.at(0).split(';');
747                     typewriter_delay->setValue(params.at(0).toInt());
748                     typewriter_start->setValue(params.at(1).toInt());
749                     effect_list->setCurrentIndex(effect_list->findData((int) TYPEWRITEREFFECT));
750                     effect_stack->setHidden(false);
751                 }
752             } else {
753 #if QT_VERSION >= 0x040600
754                 if (i->graphicsEffect()) {
755                     QGraphicsBlurEffect *blur = static_cast <QGraphicsBlurEffect *>(i->graphicsEffect());
756                     if (blur) {
757                         effect_list->setCurrentIndex(effect_list->findData((int) BLUREFFECT));
758                         int rad = (int) blur->blurRadius();
759                         blur_radius->setValue(rad);
760                         effect_stack->setHidden(false);
761                     } else {
762                         QGraphicsDropShadowEffect *shad = static_cast <QGraphicsDropShadowEffect *>(i->graphicsEffect());
763                         if (shad) {
764                             effect_list->setCurrentIndex(effect_list->findData((int) SHADOWEFFECT));
765                             shadow_radius->setValue(shad->blurRadius());
766                             shadow_x->setValue(shad->xOffset());
767                             shadow_y->setValue(shad->yOffset());
768                             effect_stack->setHidden(false);
769                         }
770                     }
771                 } else {
772                     effect_list->blockSignals(true);
773                     effect_list->setCurrentIndex(effect_list->findData((int) NOEFFECT));
774                     effect_list->blockSignals(false);
775                     effect_stack->setHidden(true);
776                 }
777 #else
778                 effect_list->blockSignals(true);
779                 effect_list->setCurrentIndex(effect_list->findData((int) NOEFFECT));
780                 effect_list->blockSignals(false);
781                 effect_stack->setHidden(true);
782 #endif
783             }
784             //if (l[0]->hasFocus())
785             //toolBox->setCurrentIndex(0);
786             //toolBox->setItemEnabled(2, true);
787             font_size->blockSignals(true);
788             font_family->blockSignals(true);
789             font_weight_box->blockSignals(true);
790             buttonItalic->blockSignals(true);
791             buttonUnder->blockSignals(true);
792             fontColorButton->blockSignals(true);
793             textAlpha->blockSignals(true);
794             buttonAlignLeft->blockSignals(true);
795             buttonAlignRight->blockSignals(true);
796             buttonAlignNone->blockSignals(true);
797             buttonAlignCenter->blockSignals(true);
798
799             QFont font = i->font();
800             font_family->setCurrentFont(font);
801             font_size->setValue(font.pixelSize());
802             m_scene->slotUpdateFontSize(font.pixelSize());
803             buttonItalic->setChecked(font.italic());
804             buttonUnder->setChecked(font.underline());
805             setFontBoxWeight(font.weight());
806
807             QColor color = i->defaultTextColor();
808             QTextCursor cursor(i->document());
809             cursor.select(QTextCursor::Document);
810             color=cursor.charFormat().foreground().color();
811             fontColorButton->setColor(color);
812             textAlpha->setValue(color.alpha());
813
814             if (!i->data(101).isNull()){
815                         textOutline->blockSignals(true);
816                 textOutline->setValue(i->data(101).toDouble()*10);
817                         textOutline->blockSignals(false);
818             }
819             if (!i->data(102).isNull()){
820                         textOutlineColor->blockSignals(true);
821                         textOutlineAlpha->blockSignals(true);
822                 textOutlineColor->setColor(i->data(102).toString());
823                 textOutlineAlpha->setValue(QColor(i->data(102).toString()).alpha());
824                         textOutlineColor->blockSignals(false);
825                         textOutlineAlpha->blockSignals(false);
826             }
827             QTextCursor cur = i->textCursor();
828             QTextBlockFormat format = cur.blockFormat();
829             if (i->textWidth() == -1) buttonAlignNone->setChecked(true);
830             else if (format.alignment() == Qt::AlignHCenter) buttonAlignCenter->setChecked(true);
831             else if (format.alignment() == Qt::AlignRight) buttonAlignRight->setChecked(true);
832             else if (format.alignment() == Qt::AlignLeft) buttonAlignLeft->setChecked(true);
833
834             font_size->blockSignals(false);
835             font_family->blockSignals(false);
836             font_weight_box->blockSignals(false);
837             buttonItalic->blockSignals(false);
838             buttonUnder->blockSignals(false);
839             fontColorButton->blockSignals(false);
840             textAlpha->blockSignals(false);
841             buttonAlignLeft->blockSignals(false);
842             buttonAlignRight->blockSignals(false);
843             buttonAlignNone->blockSignals(false);
844             buttonAlignCenter->blockSignals(false);
845
846             updateAxisButtons(i);
847             updateCoordinates(i);
848             updateDimension(i);
849             enableToolbars(TITLE_TEXT);
850
851         } else if ((l.at(0))->type() == RECTITEM) {
852             showToolbars(TITLE_RECTANGLE);
853             settingUp = true;
854             QGraphicsRectItem *rec = static_cast <QGraphicsRectItem *>(l.at(0));
855             if (rec == m_startViewport || rec == m_endViewport) {
856                 /*toolBox->setCurrentIndex(3);
857                 toolBox->widget(0)->setEnabled(false);
858                 toolBox->widget(1)->setEnabled(false);*/
859                 enableToolbars(TITLE_SELECT);
860             } else {
861                 /*toolBox->widget(0)->setEnabled(true);
862                 toolBox->widget(1)->setEnabled(true);
863                 toolBox->setCurrentIndex(0);*/
864                 //toolBox->setItemEnabled(3, true);
865                 rectFAlpha->setValue(rec->pen().color().alpha());
866                 rectBAlpha->setValue(rec->brush().color().alpha());
867                 //kDebug() << rec->brush().color().alpha();
868                 QColor fcol = rec->pen().color();
869                 QColor bcol = rec->brush().color();
870                 //fcol.setAlpha(255);
871                 //bcol.setAlpha(255);
872                 rectFColor->setColor(fcol);
873                 rectBColor->setColor(bcol);
874                 settingUp = false;
875                 rectLineWidth->setValue(rec->pen().width());
876                 enableToolbars(TITLE_RECTANGLE);
877             }
878
879             updateAxisButtons(l.at(0));
880             updateCoordinates(rec);
881             updateDimension(rec);
882
883         } else if (l.at(0)->type() == IMAGEITEM) {
884             showToolbars(TITLE_IMAGE);
885
886             updateCoordinates(l.at(0));
887             updateDimension(l.at(0));
888
889             enableToolbars(TITLE_IMAGE);
890
891         } else {
892             //toolBox->setCurrentIndex(0);
893             showToolbars(TITLE_SELECT);
894             enableToolbars(TITLE_SELECT);
895             frame_properties->setEnabled(false);
896         }
897         zValue->setValue((int)l.at(0)->zValue());
898         itemzoom->setValue((int)(m_transformations.value(l.at(0)).scalex * 100.0 + 0.5));
899         itemrotate->setValue((int)(m_transformations.value(l.at(0)).rotate));
900         value_x->blockSignals(false);
901         value_y->blockSignals(false);
902         value_w->blockSignals(false);
903         value_h->blockSignals(false);
904         itemzoom->blockSignals(false);
905         itemrotate->blockSignals(false);
906     }
907 }
908
909 void TitleWidget::slotValueChanged(int type)
910 {
911     QList<QGraphicsItem *> l = graphicsView->scene()->selectedItems();
912     if (l.size() > 0 && l.at(0)->type() == IMAGEITEM) {
913
914         int val = 0;
915         switch (type) {
916         case ValueWidth:
917             val = value_w->value();
918             break;
919         case ValueHeight:
920             val = value_h->value();
921             break;
922         }
923
924         QGraphicsItem *i = l.at(0);
925         Transform t = m_transformations.value(i);
926
927         // Ratio width:height
928         double phi = (double) i->boundingRect().width() / i->boundingRect().height();
929         double alpha = (double) t.rotate / 180.0 * M_PI;
930
931         // New length
932         double length = val;
933
934         // Scaling factor
935         double scale = 1;
936
937         switch (type) {
938         case ValueWidth:
939             // Add 0.5 because otherwise incrementing by 1 might have no effect
940             length = val / (cos(alpha) + 1 / phi * sin(alpha)) + 0.5;
941             scale = length / i->boundingRect().width();
942             break;
943         case ValueHeight:
944             length = val / (phi * sin(alpha) + cos(alpha)) + 0.5;
945             scale = length / i->boundingRect().height();
946             break;
947         }
948
949         t.scalex = scale;
950         t.scaley = scale;
951         QTransform qtrans;
952         qtrans.scale(scale, scale);
953         qtrans.rotate(t.rotate);
954         i->setTransform(qtrans);
955         m_transformations[i] = t;
956
957         updateDimension(i);
958         updateRotZoom(i);
959     }
960 }
961
962 /** \brief Updates position/size of the selected item when a value
963  * of an item (coordinates, size) has changed */
964 void TitleWidget::slotAdjustSelectedItem()
965 {
966     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
967     if (l.size() >= 1) {
968         if (l.at(0)->type() == RECTITEM) {
969             //rect item
970             QGraphicsRectItem *rec = static_cast <QGraphicsRectItem *>(l.at(0));
971             updatePosition(rec);
972             rec->setRect(QRect(0, 0, value_w->value(), value_h->value()));
973         } else if (l.at(0)->type() == TEXTITEM) {
974             //text item
975             updatePosition(l.at(0));
976         } else if (l.at(0)->type() == IMAGEITEM) {
977             //image item
978             updatePosition(l.at(0));
979         }
980     }
981 }
982
983 /** \brief Updates width/height int the text fields, regarding transformation matrix */
984 void TitleWidget::updateDimension(QGraphicsItem *i)
985 {
986     value_w->blockSignals(true);
987     value_h->blockSignals(true);
988     zValue->blockSignals(true);
989
990     zValue->setValue((int) i->zValue());
991     if (i->type() == IMAGEITEM) {
992         // Get multipliers for rotation/scaling
993
994         /*Transform t = m_transformations.value(i);
995         QRectF r = i->boundingRect();
996         int width = (int) ( abs(r.width()*t.scalex * cos(t.rotate/180.0*M_PI))
997                     + abs(r.height()*t.scaley * sin(t.rotate/180.0*M_PI)) );
998         int height = (int) ( abs(r.height()*t.scaley * cos(t.rotate/180*M_PI))
999                     + abs(r.width()*t.scalex * sin(t.rotate/180*M_PI)) );*/
1000
1001         value_w->setValue(i->sceneBoundingRect().width());
1002         value_h->setValue(i->sceneBoundingRect().height());
1003     } else if (i->type() == RECTITEM) {
1004         QGraphicsRectItem *r = static_cast <QGraphicsRectItem *>(i);
1005         value_w->setValue((int) r->rect().width());
1006         value_h->setValue((int) r->rect().height());
1007     } else if (i->type() == TEXTITEM) {
1008         QGraphicsTextItem *t = static_cast <QGraphicsTextItem *>(i);
1009         value_w->setValue((int) t->boundingRect().width());
1010         value_h->setValue((int) t->boundingRect().height());
1011     }
1012
1013     zValue->blockSignals(false);
1014     value_w->blockSignals(false);
1015     value_h->blockSignals(false);
1016 }
1017
1018 /** \brief Updates the coordinates in the text fields from the item */
1019 void TitleWidget::updateCoordinates(QGraphicsItem *i)
1020 {
1021     // Block signals emitted by this method
1022     value_x->blockSignals(true);
1023     value_y->blockSignals(true);
1024
1025     if (i->type() == TEXTITEM) {
1026
1027         QGraphicsTextItem *rec = static_cast <QGraphicsTextItem *>(i);
1028
1029         // Set the correct x coordinate value
1030         if (origin_x_left->isChecked()) {
1031             // Origin (0 point) is at m_frameWidth, coordinate axis is inverted
1032             value_x->setValue((int)(m_frameWidth - rec->pos().x() - rec->boundingRect().width()));
1033         } else {
1034             // Origin is at 0 (default)
1035             value_x->setValue((int) rec->pos().x());
1036         }
1037
1038         // Same for y
1039         if (origin_y_top->isChecked()) {
1040             value_y->setValue((int)(m_frameHeight - rec->pos().y() - rec->boundingRect().height()));
1041         } else {
1042             value_y->setValue((int) rec->pos().y());
1043         }
1044
1045     } else if (i->type() == RECTITEM) {
1046
1047         QGraphicsRectItem *rec = static_cast <QGraphicsRectItem *>(i);
1048
1049         if (origin_x_left->isChecked()) {
1050             // Origin (0 point) is at m_frameWidth
1051             value_x->setValue((int)(m_frameWidth - rec->pos().x() - rec->rect().width()));
1052         } else {
1053             // Origin is at 0 (default)
1054             value_x->setValue((int) rec->pos().x());
1055         }
1056
1057         if (origin_y_top->isChecked()) {
1058             value_y->setValue((int)(m_frameHeight - rec->pos().y() - rec->rect().height()));
1059         } else {
1060             value_y->setValue((int) rec->pos().y());
1061         }
1062
1063     } else if (i->type() == IMAGEITEM) {
1064
1065         if (origin_x_left->isChecked()) {
1066             value_x->setValue((int)(m_frameWidth - i->pos().x() - i->sceneBoundingRect().width()));
1067         } else {
1068             value_x->setValue((int) i->pos().x());
1069         }
1070
1071         if (origin_y_top->isChecked()) {
1072             value_y->setValue((int)(m_frameHeight - i->pos().y() - i->sceneBoundingRect().height()));
1073         } else {
1074             value_y->setValue((int) i->pos().y());
1075         }
1076
1077     }
1078
1079     // Stop blocking signals now
1080     value_x->blockSignals(false);
1081     value_y->blockSignals(false);
1082 }
1083
1084 void TitleWidget::updateRotZoom(QGraphicsItem *i)
1085 {
1086     itemzoom->blockSignals(true);
1087     itemrotate->blockSignals(false);
1088
1089     Transform t = m_transformations.value(i);
1090     itemzoom->setValue((int)(t.scalex * 100.0 + 0.5));
1091     itemrotate->setValue((int)(t.rotate));
1092
1093     itemzoom->blockSignals(false);
1094     itemrotate->blockSignals(false);
1095 }
1096
1097 /** \brief Updates the position of an item by reading coordinates from the text fields */
1098 void TitleWidget::updatePosition(QGraphicsItem *i)
1099 {
1100     if (i->type() == TEXTITEM) {
1101         QGraphicsTextItem *rec = static_cast <QGraphicsTextItem *>(i);
1102
1103         int posX;
1104         if (origin_x_left->isChecked()) {
1105             /* Origin of the x axis is at m_frameWidth,
1106              * and distance from right border of the item to the right
1107              * border of the frame is taken.
1108              * See comment to slotOriginXClicked().
1109              */
1110             posX = m_frameWidth - value_x->value() - rec->boundingRect().width();
1111         } else {
1112             posX = value_x->value();
1113         }
1114
1115         int posY;
1116         if (origin_y_top->isChecked()) {
1117             /* Same for y axis */
1118             posY = m_frameHeight - value_y->value() - rec->boundingRect().height();
1119         } else {
1120             posY = value_y->value();
1121         }
1122
1123         rec->setPos(posX, posY);
1124
1125     } else if (i->type() == RECTITEM) {
1126
1127         QGraphicsRectItem *rec = static_cast <QGraphicsRectItem *>(i);
1128
1129         int posX;
1130         if (origin_x_left->isChecked()) {
1131             posX = m_frameWidth - value_x->value() - rec->rect().width();
1132         } else {
1133             posX = value_x->value();
1134         }
1135
1136         int posY;
1137         if (origin_y_top->isChecked()) {
1138             posY = m_frameHeight - value_y->value() - rec->rect().height();
1139         } else {
1140             posY = value_y->value();
1141         }
1142
1143         rec->setPos(posX, posY);
1144
1145     } else if (i->type() == IMAGEITEM) {
1146         int posX;
1147         if (origin_x_left->isChecked()) {
1148             // Use the sceneBoundingRect because this also regards transformations like zoom
1149             posX = m_frameWidth - value_x->value() - i->sceneBoundingRect().width();
1150         } else {
1151             posX = value_x->value();
1152         }
1153
1154         int posY;
1155         if (origin_y_top->isChecked()) {
1156             posY = m_frameHeight - value_y->value() - i->sceneBoundingRect().height();
1157         } else {
1158             posY = value_y->value();
1159         }
1160
1161         i->setPos(posX, posY);
1162
1163     }
1164
1165 }
1166
1167 void TitleWidget::updateTextOriginX()
1168 {
1169     if (origin_x_left->isChecked()) {
1170         origin_x_left->setText(i18n("\u2212X"));
1171     } else {
1172         origin_x_left->setText(i18n("+X"));
1173     }
1174 }
1175
1176 void TitleWidget::slotOriginXClicked()
1177 {
1178     // Update the text displayed on the button.
1179     updateTextOriginX();
1180
1181     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1182     if (l.size() >= 1) {
1183         updateCoordinates(l.at(0));
1184
1185         // Remember x axis setting
1186         l.at(0)->setData(TitleDocument::OriginXLeft, origin_x_left->isChecked() ?
1187                          TitleDocument::AxisInverted : TitleDocument::AxisDefault);
1188     }
1189     graphicsView->setFocus();
1190 }
1191
1192 void TitleWidget::updateTextOriginY()
1193 {
1194     if (origin_y_top->isChecked()) {
1195         origin_y_top->setText(i18n("\u2212Y"));
1196     } else {
1197         origin_y_top->setText(i18n("+Y"));
1198     }
1199 }
1200
1201 void TitleWidget::slotOriginYClicked()
1202 {
1203     // Update the text displayed on the button.
1204     updateTextOriginY();
1205
1206     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1207     if (l.size() >= 1) {
1208         updateCoordinates(l.at(0));
1209
1210         l.at(0)->setData(TitleDocument::OriginYTop, origin_y_top->isChecked() ?
1211                          TitleDocument::AxisInverted : TitleDocument::AxisDefault);
1212
1213     }
1214     graphicsView->setFocus();
1215 }
1216
1217 void TitleWidget::updateAxisButtons(QGraphicsItem *i)
1218 {
1219     int xAxis = i->data(TitleDocument::OriginXLeft).toInt();
1220     int yAxis = i->data(TitleDocument::OriginYTop).toInt();
1221     origin_x_left->blockSignals(true);
1222     origin_y_top->blockSignals(true);
1223
1224     if (xAxis == TitleDocument::AxisInverted) {
1225         origin_x_left->setChecked(true);
1226     } else {
1227         origin_x_left->setChecked(false);
1228     }
1229     updateTextOriginX();
1230
1231     if (yAxis == TitleDocument::AxisInverted) {
1232         origin_y_top->setChecked(true);
1233     } else {
1234         origin_y_top->setChecked(false);
1235     }
1236     updateTextOriginY();
1237
1238     origin_x_left->blockSignals(false);
1239     origin_y_top->blockSignals(false);
1240 }
1241
1242 void TitleWidget::slotChangeBackground()
1243 {
1244     QColor color = kcolorbutton->color();
1245     color.setAlpha(horizontalSlider->value());
1246     m_frameBorder->setBrush(QBrush(color));
1247 }
1248
1249 /**
1250  * Something (yeah) has changed in our QGraphicsScene.
1251  */
1252 void TitleWidget::slotChanged()
1253 {
1254     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1255     if (l.size() >= 1 && l.at(0)->type() == TEXTITEM) {
1256         textChanged(static_cast <QGraphicsTextItem *>(l.at(0)));
1257     }
1258 }
1259
1260 /**
1261  * If the user has set origin_x_left (everything also for y),
1262  * we need to look whether a text element has been selected. If yes,
1263  * we need to ensure that the right border of the text field
1264  * remains fixed also when some text has been entered.
1265  *
1266  * This is also known as right-justified, with the difference that
1267  * it is not valid for text but for its boundingRect. Text may still
1268  * be left-justified.
1269  */
1270 void TitleWidget::textChanged(QGraphicsTextItem *i)
1271 {
1272
1273     updateDimension(i);
1274
1275     if (origin_x_left->isChecked() || origin_y_top->isChecked()) {
1276
1277         if (!i->toPlainText().isEmpty()) {
1278             updatePosition(i);
1279         } else {
1280             /*
1281              * Don't do anything if the string is empty. If the position
1282              * would be updated here, a newly created text field would
1283              * be set to the position of the last selected text field.
1284              */
1285         }
1286     }
1287 }
1288
1289 void TitleWidget::slotInsertUnicode()
1290 {
1291     m_unicodeDialog->exec();
1292 }
1293
1294 void TitleWidget::slotInsertUnicodeString(QString text)
1295 {
1296     QList<QGraphicsItem *> l = graphicsView->scene()->selectedItems();
1297     if (l.size() > 0) {
1298         if (l.at(0)->type() == TEXTITEM) {
1299             QGraphicsTextItem *t = static_cast <QGraphicsTextItem *>(l.at(0));
1300             t->textCursor().insertText(text);
1301         }
1302     }
1303 }
1304
1305 void TitleWidget::slotUpdateText()
1306 {
1307     QFont font = font_family->currentFont();
1308     font.setPixelSize(font_size->value());
1309     font.setItalic(buttonItalic->isChecked());
1310     font.setUnderline(buttonUnder->isChecked());
1311     font.setWeight(font_weight_box->itemData(font_weight_box->currentIndex()).toInt());
1312     QColor color = fontColorButton->color();
1313     color.setAlpha(textAlpha->value());
1314
1315     QColor outlineColor=textOutlineColor->color();
1316     outlineColor.setAlpha(textOutlineAlpha->value());
1317     double outlineWidth=textOutline->value()/10.0;
1318     QGraphicsTextItem* item = NULL;
1319     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1320     if (l.size() == 1 && l.at(0)->type() == TEXTITEM) {
1321         item = static_cast <QGraphicsTextItem *>(l.at(0));
1322     }
1323     if (!item) return;
1324     //if (item->textCursor().selection ().isEmpty())
1325     QTextCursor cur = item->textCursor();
1326     QTextBlockFormat format = cur.blockFormat();
1327     if (buttonAlignLeft->isChecked() || buttonAlignCenter->isChecked() || buttonAlignRight->isChecked()) {
1328         item->setTextWidth(item->boundingRect().width());
1329         if (buttonAlignCenter->isChecked()) format.setAlignment(Qt::AlignHCenter);
1330         else if (buttonAlignRight->isChecked()) format.setAlignment(Qt::AlignRight);
1331         else if (buttonAlignLeft->isChecked()) format.setAlignment(Qt::AlignLeft);
1332     } else {
1333         format.setAlignment(Qt::AlignLeft);
1334         item->setTextWidth(-1);
1335     }
1336
1337     {
1338         item->setFont(font);
1339         if (outlineWidth>0.0){
1340                                         item->setData(101,outlineWidth);
1341                                         item->setData(102,outlineColor);
1342                                         QTextCursor cursor(item->document());
1343                                         cursor.select(QTextCursor::Document);
1344                                         QTextCharFormat format;
1345                                         format.setTextOutline( QPen(outlineColor,outlineWidth ));
1346                                         format.setForeground(QBrush(color));
1347                                         cursor.mergeCharFormat(format); 
1348         }else{
1349                 item->setDefaultTextColor(color);
1350         }
1351         cur.select(QTextCursor::Document);
1352         cur.setBlockFormat(format);
1353         item->setTextCursor(cur);
1354         cur.clearSelection();
1355         item->setTextCursor(cur);
1356
1357     }
1358 }
1359
1360 void TitleWidget::rectChanged()
1361 {
1362     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1363     if (l.size() == 1 && l.at(0)->type() == RECTITEM && !settingUp) {
1364         QGraphicsRectItem *rec = static_cast<QGraphicsRectItem *>(l.at(0));
1365         QColor f = rectFColor->color();
1366         f.setAlpha(rectFAlpha->value());
1367         QPen penf(f);
1368         penf.setWidth(rectLineWidth->value());
1369         rec->setPen(penf);
1370         QColor b = rectBColor->color();
1371         b.setAlpha(rectBAlpha->value());
1372         rec->setBrush(QBrush(b));
1373     }
1374 }
1375
1376 void TitleWidget::itemScaled(int val)
1377 {
1378     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1379     if (l.size() == 1) {
1380         Transform x = m_transformations.value(l.at(0));
1381         x.scalex = (double)val / 100.0;
1382         x.scaley = (double)val / 100.0;
1383         QTransform qtrans;
1384         qtrans.scale(x.scalex, x.scaley);
1385         qtrans.rotate(x.rotate);
1386         l[0]->setTransform(qtrans);
1387         m_transformations[l.at(0)] = x;
1388         updateDimension(l.at(0));
1389     }
1390 }
1391
1392 void TitleWidget::itemRotate(int val)
1393 {
1394     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1395     if (l.size() == 1) {
1396         Transform x = m_transformations[l.at(0)];
1397         x.rotate = (double)val;
1398         QTransform qtrans;
1399         qtrans.scale(x.scalex, x.scaley);
1400         qtrans.rotate(x.rotate);
1401         l[0]->setTransform(qtrans);
1402         m_transformations[l.at(0)] = x;
1403         updateDimension(l.at(0));
1404     }
1405 }
1406
1407 void TitleWidget::itemHCenter()
1408 {
1409     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1410     if (l.size() == 1) {
1411         QGraphicsItem *item = l.at(0);
1412         QRectF br = item->sceneBoundingRect();
1413         int width = (int)br.width();
1414         int newPos = (int)((m_frameWidth - width) / 2);
1415         newPos += item->pos().x() - br.left(); // Check item transformation
1416         item->setPos(newPos, item->pos().y());
1417         updateCoordinates(item);
1418     }
1419 }
1420
1421 void TitleWidget::itemVCenter()
1422 {
1423     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1424     if (l.size() == 1) {
1425         QGraphicsItem *item = l.at(0);
1426         QRectF br = item->sceneBoundingRect();
1427         int height = (int)br.height();
1428         int newPos = (int)((m_frameHeight - height) / 2);
1429         newPos += item->pos().y() - br.top(); // Check item transformation
1430         item->setPos(item->pos().x(), newPos);
1431         updateCoordinates(item);
1432     }
1433 }
1434
1435 void TitleWidget::itemTop()
1436 {
1437     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1438     if (l.size() == 1) {
1439         QGraphicsItem *item = l.at(0);
1440         QRectF br = item->sceneBoundingRect();
1441         double diff;
1442         if (br.top() > 0) diff = -br.top();
1443         else diff = -br.bottom();
1444         item->moveBy(0, diff);
1445         updateCoordinates(item);
1446     }
1447 }
1448
1449 void TitleWidget::itemBottom()
1450 {
1451     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1452     if (l.size() == 1) {
1453         QGraphicsItem *item = l.at(0);
1454         QRectF br = item->sceneBoundingRect();
1455         double diff;
1456         if (br.bottom() > m_frameHeight) diff = m_frameHeight - br.top();
1457         else diff = m_frameHeight - br.bottom();
1458         item->moveBy(0, diff);
1459         updateCoordinates(item);
1460     }
1461 }
1462
1463 void TitleWidget::itemLeft()
1464 {
1465     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1466     if (l.size() == 1) {
1467         QGraphicsItem *item = l.at(0);
1468         QRectF br = item->sceneBoundingRect();
1469         double diff;
1470         if (br.left() > 0) diff = -br.left();
1471         else diff = -br.right();
1472         item->moveBy(diff, 0);
1473         updateCoordinates(item);
1474     }
1475 }
1476
1477 void TitleWidget::itemRight()
1478 {
1479     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1480     if (l.size() == 1) {
1481         QGraphicsItem *item = l.at(0);
1482         QRectF br = item->sceneBoundingRect();
1483         double diff;
1484         if (br.right() < m_frameWidth) diff = m_frameWidth - br.right();
1485         else diff = m_frameWidth - br.left();
1486         item->moveBy(diff, 0);
1487         updateCoordinates(item);
1488     }
1489 }
1490
1491 void TitleWidget::setupViewports()
1492 {
1493     //double aspect_ratio = 4.0 / 3.0;//read from project
1494     //better zoom centered, but render uses only the created rect, so no problem to change the zoom function
1495     /*QRectF sp(0, 0, startViewportSize->value() * m_frameWidth / 100.0 , startViewportSize->value()* m_frameHeight / 100.0);
1496     QRectF ep(0, 0, endViewportSize->value() * m_frameWidth / 100.0, endViewportSize->value() * m_frameHeight / 100.0);
1497     // use a polygon thiat uses 16:9 and 4:3 rects forpreview the size in all aspect ratios ?
1498     QPolygonF spoly(sp);
1499     QPolygonF epoly(ep);
1500     spoly.translate(startViewportX->value(), startViewportY->value());
1501     epoly.translate(endViewportX->value(), endViewportY->value());
1502     m_startViewport->setPolygon(spoly);
1503     m_endViewport->setPolygon(epoly);
1504     if (! insertingValues) {
1505         m_startViewport->setData(0, startViewportX->value());
1506         m_startViewport->setData(1, startViewportY->value());
1507         m_startViewport->setData(2, startViewportSize->value());
1508
1509         m_endViewport->setData(0, endViewportX->value());
1510         m_endViewport->setData(1, endViewportY->value());
1511         m_endViewport->setData(2, endViewportSize->value());
1512     }*/
1513 }
1514
1515 void TitleWidget::loadTitle(KUrl url)
1516 {
1517     if (url.isEmpty()) url = KFileDialog::getOpenUrl(KUrl(m_projectTitlePath), "application/x-kdenlivetitle", this, i18n("Load Title"));
1518     if (!url.isEmpty()) {
1519         QList<QGraphicsItem *> items = m_scene->items();
1520         for (int i = 0; i < items.size(); i++) {
1521             if (items.at(i)->zValue() > -1000) delete items.at(i);
1522         }
1523         m_scene->clearTextSelection();
1524         QDomDocument doc;
1525         QString tmpfile;
1526
1527         if (KIO::NetAccess::download(url, tmpfile, 0)) {
1528             QFile file(tmpfile);
1529             if (file.open(QIODevice::ReadOnly)) {
1530                 doc.setContent(&file, false);
1531                 file.close();
1532             } else return;
1533             KIO::NetAccess::removeTempFile(tmpfile);
1534         }
1535         setXml(doc);
1536
1537         /*int out;
1538         m_count = m_titledocument.loadDocument(url, m_startViewport, m_endViewport, &out) + 1;
1539         adjustFrameSize();
1540         title_duration->setText(m_tc.getTimecode(GenTime(out, m_render->fps())));
1541         insertingValues = true;
1542         startViewportX->setValue(m_startViewport->data(0).toInt());
1543         startViewportY->setValue(m_startViewport->data(1).toInt());
1544         startViewportSize->setValue(m_startViewport->data(2).toInt());
1545         endViewportX->setValue(m_endViewport->data(0).toInt());
1546         endViewportY->setValue(m_endViewport->data(1).toInt());
1547         endViewportSize->setValue(m_endViewport->data(2).toInt());
1548
1549         insertingValues = false;
1550         slotSelectTool();
1551         slotAdjustZoom();*/
1552     }
1553 }
1554
1555 void TitleWidget::saveTitle(KUrl url)
1556 {
1557     if (anim_start->isChecked()) slotAnimStart(false);
1558     if (anim_end->isChecked()) slotAnimEnd(false);
1559     if (url.isEmpty()) {
1560         KFileDialog *fs = new KFileDialog(KUrl(m_projectTitlePath), "application/x-kdenlivetitle", this);
1561         fs->setOperationMode(KFileDialog::Saving);
1562         fs->setMode(KFile::File);
1563 #if KDE_IS_VERSION(4,2,0)
1564         fs->setConfirmOverwrite(true);
1565 #endif
1566         fs->setKeepLocation(true);
1567         fs->exec();
1568         url = fs->selectedUrl();
1569         delete fs;
1570     }
1571     if (!url.isEmpty()) {
1572         if (m_titledocument.saveDocument(url, m_startViewport, m_endViewport, m_tc.getFrameCount(title_duration->text())) == false)
1573             KMessageBox::error(this, i18n("Cannot write to file %1", url.path()));
1574     }
1575 }
1576
1577 QDomDocument TitleWidget::xml()
1578 {
1579     QDomDocument doc = m_titledocument.xml(m_startViewport, m_endViewport);
1580     doc.documentElement().setAttribute("out", m_tc.getFrameCount(title_duration->text()));
1581     return doc;
1582 }
1583
1584 int TitleWidget::duration() const
1585 {
1586     return m_tc.getFrameCount(title_duration->text());
1587 }
1588
1589 void TitleWidget::setXml(QDomDocument doc)
1590 {
1591     int out;
1592     m_count = m_titledocument.loadFromXml(doc, m_startViewport, m_endViewport, &out);
1593     adjustFrameSize();
1594     title_duration->setText(m_tc.getTimecode(GenTime(out, m_render->fps())));
1595     /*if (doc.documentElement().hasAttribute("out")) {
1596     GenTime duration = GenTime(doc.documentElement().attribute("out").toDouble() / 1000.0);
1597     title_duration->setText(m_tc.getTimecode(duration));
1598     }
1599     else title_duration->setText(m_tc.getTimecode(GenTime(5000)));*/
1600
1601     QDomElement e = doc.documentElement();
1602     m_transformations.clear();
1603     QList <QGraphicsItem *> items = graphicsView->scene()->items();
1604     const double PI = 4.0 * atan(1.0);
1605     for (int i = 0; i < items.count(); i++) {
1606         QTransform t = items.at(i)->transform();
1607         Transform x;
1608         x.scalex = t.m11();
1609         x.scaley = t.m22();
1610         x.rotate = 180. / PI * atan2(-t.m21(), t.m11());
1611         m_transformations[items.at(i)] = x;
1612     }
1613     // mbd: Update the GUI color selectors to match the stuff from the loaded document
1614     QColor background_color = m_titledocument.getBackgroundColor();
1615     horizontalSlider->blockSignals(true);
1616     kcolorbutton->blockSignals(true);
1617     horizontalSlider->setValue(background_color.alpha());
1618     background_color.setAlpha(255);
1619     kcolorbutton->setColor(background_color);
1620     horizontalSlider->blockSignals(false);
1621     kcolorbutton->blockSignals(false);
1622
1623     /*startViewportX->setValue(m_startViewport->data(0).toInt());
1624     startViewportY->setValue(m_startViewport->data(1).toInt());
1625     startViewportSize->setValue(m_startViewport->data(2).toInt());
1626     endViewportX->setValue(m_endViewport->data(0).toInt());
1627     endViewportY->setValue(m_endViewport->data(1).toInt());
1628     endViewportSize->setValue(m_endViewport->data(2).toInt());*/
1629
1630     QTimer::singleShot(200, this, SLOT(slotAdjustZoom()));
1631     slotSelectTool();
1632 }
1633
1634 /** \brief Connected to the accepted signal - calls writeChoices */
1635 void TitleWidget::slotAccepted()
1636 {
1637     if (anim_start->isChecked()) slotAnimStart(false);
1638     if (anim_end->isChecked()) slotAnimEnd(false);
1639     writeChoices();
1640 }
1641
1642 /** \brief Store the current choices of font, background and rect values */
1643 void TitleWidget::writeChoices()
1644 {
1645     // Get a pointer to a shared configuration instance, then get the TitleWidget group.
1646     KSharedConfigPtr config = KGlobal::config();
1647     KConfigGroup titleConfig(config, "TitleWidget");
1648     // Write the entries
1649     titleConfig.writeEntry("font_family", font_family->currentFont());
1650     //titleConfig.writeEntry("font_size", font_size->value());
1651     titleConfig.writeEntry("font_pixel_size", font_size->value());
1652     titleConfig.writeEntry("font_color", fontColorButton->color());
1653     titleConfig.writeEntry("font_alpha", textAlpha->value());
1654     titleConfig.writeEntry("font_weight", font_weight_box->itemData(font_weight_box->currentIndex()).toInt());
1655     titleConfig.writeEntry("font_italic", buttonItalic->isChecked());
1656     titleConfig.writeEntry("font_underlined", buttonUnder->isChecked());
1657
1658     titleConfig.writeEntry("rect_foreground_color", rectFColor->color());
1659     titleConfig.writeEntry("rect_foreground_alpha", rectFAlpha->value());
1660     titleConfig.writeEntry("rect_background_color", rectBColor->color());
1661     titleConfig.writeEntry("rect_background_alpha", rectBAlpha->value());
1662     titleConfig.writeEntry("rect_line_width", rectLineWidth->value());
1663
1664     titleConfig.writeEntry("background_color", kcolorbutton->color());
1665     titleConfig.writeEntry("background_alpha", horizontalSlider->value());
1666
1667     //! \todo Not sure if I should sync - it is probably safe to do it
1668     config->sync();
1669
1670 }
1671
1672 /** \brief Read the last stored choices into the dialog */
1673 void TitleWidget::readChoices()
1674 {
1675     // Get a pointer to a shared configuration instance, then get the TitleWidget group.
1676     KSharedConfigPtr config = KGlobal::config();
1677     KConfigGroup titleConfig(config, "TitleWidget");
1678     // read the entries
1679     font_family->setCurrentFont(titleConfig.readEntry("font_family", font_family->currentFont()));
1680     font_size->setValue(titleConfig.readEntry("font_pixel_size", font_size->value()));
1681     m_scene->slotUpdateFontSize(font_size->value());
1682     fontColorButton->setColor(titleConfig.readEntry("font_color", fontColorButton->color()));
1683     textAlpha->setValue(titleConfig.readEntry("font_alpha", textAlpha->value()));
1684     int weight;
1685     if (titleConfig.readEntry("font_bold", false)) weight = QFont::Bold;
1686     else weight = titleConfig.readEntry("font_weight", font_weight_box->itemData(font_weight_box->currentIndex()).toInt());
1687     setFontBoxWeight(weight);
1688     buttonItalic->setChecked(titleConfig.readEntry("font_italic", buttonItalic->isChecked()));
1689     buttonUnder->setChecked(titleConfig.readEntry("font_underlined", buttonUnder->isChecked()));
1690
1691     rectFColor->setColor(titleConfig.readEntry("rect_foreground_color", rectFColor->color()));
1692     rectFAlpha->setValue(titleConfig.readEntry("rect_foreground_alpha", rectFAlpha->value()));
1693     rectBColor->setColor(titleConfig.readEntry("rect_background_color", rectBColor->color()));
1694     rectBAlpha->setValue(titleConfig.readEntry("rect_background_alpha", rectBAlpha->value()));
1695     rectLineWidth->setValue(titleConfig.readEntry("rect_line_width", rectLineWidth->value()));
1696
1697     kcolorbutton->setColor(titleConfig.readEntry("background_color", kcolorbutton->color()));
1698     horizontalSlider->setValue(titleConfig.readEntry("background_alpha", horizontalSlider->value()));
1699 }
1700
1701 void TitleWidget::adjustFrameSize()
1702 {
1703     m_frameWidth = m_titledocument.frameWidth();
1704     m_frameHeight = m_titledocument.frameHeight();
1705     m_frameBorder->setRect(0, 0, m_frameWidth, m_frameHeight);
1706     displayBackgroundFrame();
1707 }
1708
1709 void TitleWidget::slotAnimStart(bool anim)
1710 {
1711     if (anim && anim_end->isChecked()) {
1712         anim_end->setChecked(false);
1713         m_endViewport->setZValue(-1000);
1714         m_endViewport->setBrush(QBrush());
1715     }
1716     slotSelectTool();
1717     QList<QGraphicsItem *> list = m_scene->items();
1718     for (int i = 0; i < list.count(); i++) {
1719         if (list.at(i)->zValue() > -1000) {
1720             list.at(i)->setFlag(QGraphicsItem::ItemIsMovable, !anim);
1721             list.at(i)->setFlag(QGraphicsItem::ItemIsSelectable, !anim);
1722         }
1723     }
1724     align_box->setEnabled(anim);
1725     itemzoom->setEnabled(!anim);
1726     itemrotate->setEnabled(!anim);
1727     frame_toolbar->setEnabled(!anim);
1728     toolbar_stack->setEnabled(!anim);
1729     if (anim) {
1730         keep_aspect->setChecked(!m_startViewport->data(0).isNull());
1731         m_startViewport->setZValue(1100);
1732         QColor col = m_startViewport->pen().color();
1733         col.setAlpha(100);
1734         m_startViewport->setBrush(col);
1735         m_startViewport->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
1736         m_startViewport->setSelected(true);
1737         selectionChanged();
1738         slotSelectTool();
1739         if (m_startViewport->childItems().isEmpty()) addAnimInfoText();
1740     } else {
1741         m_startViewport->setZValue(-1000);
1742         m_startViewport->setBrush(QBrush());
1743         m_startViewport->setFlags(0);
1744         if (!anim_end->isChecked()) deleteAnimInfoText();
1745     }
1746
1747 }
1748
1749 void TitleWidget::slotAnimEnd(bool anim)
1750 {
1751     if (anim && anim_start->isChecked()) {
1752         anim_start->setChecked(false);
1753         m_startViewport->setZValue(-1000);
1754         m_startViewport->setBrush(QBrush());
1755     }
1756     slotSelectTool();
1757     QList<QGraphicsItem *> list = m_scene->items();
1758     for (int i = 0; i < list.count(); i++) {
1759         if (list.at(i)->zValue() > -1000) {
1760             list.at(i)->setFlag(QGraphicsItem::ItemIsMovable, !anim);
1761             list.at(i)->setFlag(QGraphicsItem::ItemIsSelectable, !anim);
1762         }
1763     }
1764     align_box->setEnabled(anim);
1765     itemzoom->setEnabled(!anim);
1766     itemrotate->setEnabled(!anim);
1767     frame_toolbar->setEnabled(!anim);
1768     toolbar_stack->setEnabled(!anim);
1769     if (anim) {
1770         keep_aspect->setChecked(!m_endViewport->data(0).isNull());
1771         m_endViewport->setZValue(1100);
1772         QColor col = m_endViewport->pen().color();
1773         col.setAlpha(100);
1774         m_endViewport->setBrush(col);
1775         m_endViewport->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
1776         m_endViewport->setSelected(true);
1777         selectionChanged();
1778         slotSelectTool();
1779         if (m_endViewport->childItems().isEmpty()) addAnimInfoText();
1780     } else {
1781         m_endViewport->setZValue(-1000);
1782         m_endViewport->setBrush(QBrush());
1783         m_endViewport->setFlags(0);
1784         if (!anim_start->isChecked()) deleteAnimInfoText();
1785     }
1786 }
1787
1788 void TitleWidget::addAnimInfoText()
1789 {
1790     // add text to anim viewport
1791     QGraphicsTextItem *t = new QGraphicsTextItem(i18n("Start"), m_startViewport);
1792     QGraphicsTextItem *t2 = new QGraphicsTextItem(i18n("End"), m_endViewport);
1793     QFont font = t->font();
1794     font.setPixelSize(m_startViewport->rect().width() / 10);
1795     QColor col = m_startViewport->pen().color();
1796     col.setAlpha(255);
1797     t->setDefaultTextColor(col);
1798     t->setFont(font);
1799     font.setPixelSize(m_endViewport->rect().width() / 10);
1800     col = m_endViewport->pen().color();
1801     col.setAlpha(255);
1802     t2->setDefaultTextColor(col);
1803     t2->setFont(font);
1804 }
1805
1806 void TitleWidget::updateInfoText()
1807 {
1808     // update info text font
1809     if (!m_startViewport->childItems().isEmpty()) {
1810         QGraphicsTextItem *item = static_cast <QGraphicsTextItem *>(m_startViewport->childItems().at(0));
1811         if (item) {
1812             QFont font = item->font();
1813             font.setPixelSize(m_startViewport->rect().width() / 10);
1814             item->setFont(font);
1815         }
1816     }
1817     if (!m_endViewport->childItems().isEmpty()) {
1818         QGraphicsTextItem *item = static_cast <QGraphicsTextItem *>(m_endViewport->childItems().at(0));
1819         if (item) {
1820             QFont font = item->font();
1821             font.setPixelSize(m_endViewport->rect().width() / 10);
1822             item->setFont(font);
1823         }
1824     }
1825 }
1826
1827 void TitleWidget::deleteAnimInfoText()
1828 {
1829     // end animation editing, remove info text
1830     while (!m_startViewport->childItems().isEmpty()) {
1831         QGraphicsItem *item = m_startViewport->childItems().at(0);
1832         m_scene->removeItem(item);
1833         delete item;
1834     }
1835     while (!m_endViewport->childItems().isEmpty()) {
1836         QGraphicsItem *item = m_endViewport->childItems().at(0);
1837         m_scene->removeItem(item);
1838         delete item;
1839     }
1840 }
1841
1842
1843 void TitleWidget::slotKeepAspect(bool keep)
1844 {
1845     if (m_endViewport->zValue() == 1100) {
1846         m_endViewport->setData(0, keep == true ? m_frameWidth : QVariant());
1847         m_endViewport->setData(1, keep == true ? m_frameHeight : QVariant());
1848     } else {
1849         m_startViewport->setData(0, keep == true ? m_frameWidth : QVariant());
1850         m_startViewport->setData(1, keep == true ? m_frameHeight : QVariant());
1851     }
1852 }
1853
1854 void TitleWidget::slotResize50()
1855 {
1856     if (m_endViewport->zValue() == 1100) {
1857         m_endViewport->setRect(0, 0, m_frameWidth / 2, m_frameHeight / 2);
1858     } else m_startViewport->setRect(0, 0, m_frameWidth / 2, m_frameHeight / 2);
1859 }
1860
1861 void TitleWidget::slotResize100()
1862 {
1863     if (m_endViewport->zValue() == 1100) {
1864         m_endViewport->setRect(0, 0, m_frameWidth, m_frameHeight);
1865     } else m_startViewport->setRect(0, 0, m_frameWidth, m_frameHeight);
1866 }
1867
1868 void TitleWidget::slotResize200()
1869 {
1870     if (m_endViewport->zValue() == 1100) {
1871         m_endViewport->setRect(0, 0, m_frameWidth * 2, m_frameHeight * 2);
1872     } else m_startViewport->setRect(0, 0, m_frameWidth * 2, m_frameHeight * 2);
1873 }
1874
1875 void TitleWidget::slotAddEffect(int ix)
1876 {
1877     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1878     int effect = effect_list->itemData(ix).toInt();
1879     if (effect == NOEFFECT) {
1880         if (l.size() == 1) l[0]->setData(100, QVariant());
1881         effect_stack->setHidden(true);
1882         return;
1883     }
1884     effect_stack->setCurrentIndex(effect - 1);
1885     effect_stack->setHidden(false);
1886     if (effect == TYPEWRITEREFFECT) {
1887         if (l.size() == 1 && l.at(0)->type() == TEXTITEM) {
1888             QStringList effdata = QStringList() << "typewriter" << QString::number(typewriter_delay->value()) + ";" + QString::number(typewriter_start->value());
1889             l[0]->setData(100, effdata);
1890         }
1891     }
1892 #if QT_VERSION < 0x040600
1893     return;
1894 #else
1895     if (effect == BLUREFFECT) {
1896         // Blur effect
1897         if (l.size() == 1) {
1898             QGraphicsEffect *eff = new QGraphicsBlurEffect();
1899             l[0]->setGraphicsEffect(eff);
1900         }
1901     } else if (effect == SHADOWEFFECT) {
1902         if (l.size() == 1) {
1903             QGraphicsEffect *eff = new QGraphicsDropShadowEffect();
1904             l[0]->setGraphicsEffect(eff);
1905         }
1906     }
1907
1908 #endif
1909 }
1910
1911
1912 void TitleWidget::slotFontText(const QString& s)
1913 {
1914     const QFont f(s);
1915     if (f.exactMatch()) {
1916         // Font really exists (could also just be a «d» if the user
1917         // starts typing «dejavu» for example).
1918         font_family->setCurrentFont(f);
1919     }
1920     // Note: Typing dejavu serif does not recognize the font (takes sans)
1921     // in older Qt versions.
1922 }
1923
1924 void TitleWidget::slotEditTypewriter(int ix)
1925 {
1926     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1927     if (l.size() == 1) {
1928         QStringList effdata = QStringList() << "typewriter" << QString::number(typewriter_delay->value()) + ";" + QString::number(typewriter_start->value());
1929         l[0]->setData(100, effdata);
1930     }
1931 }
1932
1933 void TitleWidget::slotEditBlur(int ix)
1934 {
1935 #if QT_VERSION < 0x040600
1936     return;
1937 #else
1938     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1939     if (l.size() == 1) {
1940         QGraphicsEffect *eff = l[0]->graphicsEffect();
1941         QGraphicsBlurEffect *blur = static_cast <QGraphicsBlurEffect *>(eff);
1942         if (blur) blur->setBlurRadius(ix);
1943     }
1944 #endif
1945 }
1946
1947 void TitleWidget::slotEditShadow()
1948 {
1949 #if QT_VERSION < 0x040600
1950     return;
1951 #else
1952     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1953     if (l.size() == 1) {
1954         QGraphicsEffect *eff = l[0]->graphicsEffect();
1955         QGraphicsDropShadowEffect *shadow = static_cast <QGraphicsDropShadowEffect *>(eff);
1956         if (shadow) {
1957             shadow->setBlurRadius(shadow_radius->value());
1958             shadow->setOffset(shadow_x->value(), shadow_y->value());
1959         }
1960     }
1961 #endif
1962 }
1963
1964 qreal TitleWidget::zIndexBounds(bool maxBound)
1965 {
1966     qreal bound = maxBound ? -99 : 99;
1967     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1968     if (l.size() > 0) {
1969         QList<QGraphicsItem*> lItems = graphicsView->scene()->items(l[0]->sceneBoundingRect(), Qt::IntersectsItemShape);
1970         if (lItems.size() > 0) {
1971             int n = lItems.size();
1972             qreal z;
1973             if (maxBound) {
1974                 for (int i = 0; i < n; i++) {
1975                     z = lItems[i]->zValue();
1976                     if (z > bound && !lItems[i]->isSelected()) {
1977                         bound = z;
1978                     }
1979                 }
1980             } else {
1981                 // Get minimum z index.
1982                 for (int i = 0; i < n; i++) {
1983                     z = lItems[i]->zValue();
1984                     if (z < bound && !lItems[i]->isSelected() && z > -999) {
1985                         // There are items at the very bottom (background e.g.) with z-index < -1000.
1986                         bound = z;
1987                     }
1988                 }
1989             }
1990         }
1991     }
1992     return bound;
1993 }
1994
1995 void TitleWidget::slotZIndexUp()
1996 {
1997     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1998     if (l.size() >= 1) {
1999         qreal currentZ = l[0]->zValue();
2000         qreal max = zIndexBounds(true);
2001         if (currentZ <= max) {
2002             l[0]->setZValue(currentZ + 1);
2003             updateDimension(l[0]);
2004         }
2005     }
2006 }
2007
2008 void TitleWidget::slotZIndexTop()
2009 {
2010     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
2011     if (l.size() >= 1) {
2012         qreal currentZ = l[0]->zValue();
2013         qreal max = zIndexBounds(true);
2014         if (currentZ <= max) {
2015             l[0]->setZValue(max + 1);
2016             updateDimension(l[0]);
2017         }
2018     }
2019 }
2020
2021 void TitleWidget::slotZIndexDown()
2022 {
2023     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
2024     if (l.size() >= 1) {
2025         qreal currentZ = l[0]->zValue();
2026         qreal min = zIndexBounds(false);
2027         if (currentZ >= min) {
2028             l[0]->setZValue(currentZ - 1);
2029             updateDimension(l[0]);
2030         }
2031     }
2032 }
2033
2034 void TitleWidget::slotZIndexBottom()
2035 {
2036     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
2037     if (l.size() >= 1) {
2038         qreal currentZ = l[0]->zValue();
2039         qreal min = zIndexBounds(false);
2040         if (currentZ >= min) {
2041             l[0]->setZValue(min - 1);
2042             updateDimension(l[0]);
2043         }
2044     }
2045 }