]> git.sesse.net Git - kdenlive/blob - src/titlewidget.cpp
Various fixes to improve general stability in Qt 4.5.2
[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
30 #include <QDomDocument>
31 #include <QGraphicsItem>
32 #include <QGraphicsSvgItem>
33 #include <QTimer>
34 #include <QToolBar>
35 #include <QMenu>
36 #include <QSignalMapper>
37 #include <QTextBlockFormat>
38 #include <QTextCursor>
39
40 int settingUp = false;
41
42 const int IMAGEITEM = 7;
43 const int RECTITEM = 3;
44 const int TEXTITEM = 8;
45 static bool insertingValues = false;
46
47 TitleWidget::TitleWidget(KUrl url, Timecode tc, QString projectTitlePath, Render *render, QWidget *parent) :
48         QDialog(parent),
49         Ui::TitleWidget_UI(),
50         m_startViewport(NULL),
51         m_endViewport(NULL),
52         m_render(render),
53         m_count(0),
54         m_unicodeDialog(new UnicodeDialog(UnicodeDialog::InputHex)),
55         m_projectTitlePath(projectTitlePath),
56         m_tc(tc)
57 {
58     setupUi(this);
59     setFont(KGlobalSettings::toolBarFont());
60     //toolBox->setFont(KGlobalSettings::toolBarFont());
61     frame_properties->setEnabled(false);
62     rect_properties->setFixedHeight(frame_properties->height() + 4);
63     no_properties->setFixedHeight(frame_properties->height() + 4);
64     image_properties->setFixedHeight(frame_properties->height() + 4);
65     text_properties->setFixedHeight(frame_properties->height() + 4);
66     frame_properties->setFixedHeight(frame_toolbar->height());
67     m_frameWidth = render->renderWidth();
68     m_frameHeight = render->renderHeight();
69     showToolbars(TITLE_NONE);
70
71     //TODO: get default title duration instead of hardcoded one
72     title_duration->setText(m_tc.getTimecode(GenTime(5000 / 1000.0)));
73
74     connect(kcolorbutton, SIGNAL(clicked()), this, SLOT(slotChangeBackground())) ;
75     connect(horizontalSlider, SIGNAL(valueChanged(int)), this, SLOT(slotChangeBackground())) ;
76
77     connect(fontColorButton, SIGNAL(clicked()), this, SLOT(slotUpdateText())) ;
78     connect(font_family, SIGNAL(currentFontChanged(const QFont &)), this, SLOT(slotUpdateText())) ;
79     connect(font_size, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateText())) ;
80     connect(textAlpha, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateText()));
81     connect(font_weight_box, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdateText()));
82
83     connect(rectFAlpha, SIGNAL(valueChanged(int)), this, SLOT(rectChanged()));
84     connect(rectBAlpha, SIGNAL(valueChanged(int)), this, SLOT(rectChanged()));
85     connect(rectFColor, SIGNAL(clicked()), this, SLOT(rectChanged()));
86     connect(rectBColor, SIGNAL(clicked()), this, SLOT(rectChanged()));
87     connect(rectLineWidth, SIGNAL(valueChanged(int)), this, SLOT(rectChanged()));
88
89     connect(startViewportX, SIGNAL(valueChanged(int)), this, SLOT(setupViewports()));
90     connect(startViewportY, SIGNAL(valueChanged(int)), this, SLOT(setupViewports()));
91     connect(startViewportSize, SIGNAL(valueChanged(int)), this, SLOT(setupViewports()));
92     connect(endViewportX, SIGNAL(valueChanged(int)), this, SLOT(setupViewports()));
93     connect(endViewportY, SIGNAL(valueChanged(int)), this, SLOT(setupViewports()));
94     connect(endViewportSize, SIGNAL(valueChanged(int)), this, SLOT(setupViewports()));
95
96     connect(zValue, SIGNAL(valueChanged(int)), this, SLOT(zIndexChanged(int)));
97     connect(itemzoom, SIGNAL(valueChanged(int)), this, SLOT(itemScaled(int)));
98     connect(itemrotate, SIGNAL(valueChanged(int)), this, SLOT(itemRotate(int)));
99     connect(itemhcenter, SIGNAL(clicked()), this, SLOT(itemHCenter()));
100     connect(itemvcenter, SIGNAL(clicked()), this, SLOT(itemVCenter()));
101
102     connect(origin_x_left, SIGNAL(clicked()), this, SLOT(slotOriginXClicked()));
103     connect(origin_y_top, SIGNAL(clicked()), this, SLOT(slotOriginYClicked()));
104
105     m_signalMapper = new QSignalMapper(this);
106     m_signalMapper->setMapping(value_w, ValueWidth);
107     m_signalMapper->setMapping(value_h, ValueHeight);
108     connect(value_w, SIGNAL(valueChanged(int)), m_signalMapper, SLOT(map()));
109     connect(value_h, SIGNAL(valueChanged(int)), m_signalMapper, SLOT(map()));
110     connect(m_signalMapper, SIGNAL(mapped(int)), this, SLOT(slotValueChanged(int)));
111
112     connect(value_x, SIGNAL(valueChanged(int)), this, SLOT(slotAdjustSelectedItem()));
113     connect(value_y, SIGNAL(valueChanged(int)), this, SLOT(slotAdjustSelectedItem()));
114     connect(value_w, SIGNAL(valueChanged(int)), this, SLOT(slotAdjustSelectedItem()));
115     connect(value_h, SIGNAL(valueChanged(int)), this, SLOT(slotAdjustSelectedItem()));
116     connect(buttonFitZoom, SIGNAL(clicked()), this, SLOT(slotAdjustZoom()));
117     connect(buttonRealSize, SIGNAL(clicked()), this, SLOT(slotZoomOneToOne()));
118     connect(buttonItalic, SIGNAL(clicked()), this, SLOT(slotUpdateText()));
119     connect(buttonUnder, SIGNAL(clicked()), this, SLOT(slotUpdateText()));
120     connect(buttonAlignLeft, SIGNAL(clicked()), this, SLOT(slotUpdateText()));
121     connect(buttonAlignRight, SIGNAL(clicked()), this, SLOT(slotUpdateText()));
122     connect(buttonAlignCenter, SIGNAL(clicked()), this, SLOT(slotUpdateText()));
123     connect(buttonAlignNone, SIGNAL(clicked()), this, SLOT(slotUpdateText()));
124     //connect(buttonInsertUnicode, SIGNAL(clicked()), this, SLOT(slotInsertUnicode()));
125     connect(displayBg, SIGNAL(stateChanged(int)), this, SLOT(displayBackgroundFrame()));
126
127     connect(m_unicodeDialog, SIGNAL(charSelected(QString)), this, SLOT(slotInsertUnicodeString(QString)));
128
129     // mbd
130     connect(this, SIGNAL(accepted()), this, SLOT(slotAccepted()));
131
132     font_weight_box->blockSignals(true);
133     font_weight_box->addItem(i18nc("Font style", "Light"), QFont::Light);
134     font_weight_box->addItem(i18nc("Font style", "Normal"), QFont::Normal);
135     font_weight_box->addItem(i18nc("Font style", "Demi-Bold"), QFont::DemiBold);
136     font_weight_box->addItem(i18nc("Font style", "Bold"), QFont::Bold);
137     font_weight_box->addItem(i18nc("Font style", "Black"), QFont::Black);
138     font_weight_box->setToolTip(i18n("Font weight"));
139     font_weight_box->setCurrentIndex(1);
140     font_weight_box->blockSignals(false);
141
142     buttonFitZoom->setIcon(KIcon("zoom-fit-best"));
143     buttonRealSize->setIcon(KIcon("zoom-original"));
144     buttonItalic->setIcon(KIcon("format-text-italic"));
145     buttonUnder->setIcon(KIcon("format-text-underline"));
146     buttonAlignCenter->setIcon(KIcon("format-justify-center"));
147     buttonAlignLeft->setIcon(KIcon("format-justify-left"));
148     buttonAlignRight->setIcon(KIcon("format-justify-right"));
149     buttonAlignNone->setIcon(KIcon("kdenlive-align-none"));
150
151     buttonAlignNone->setToolTip(i18n("No alignment"));
152     buttonAlignRight->setToolTip(i18n("Align right"));
153     buttonAlignLeft->setToolTip(i18n("Align left"));
154     buttonAlignCenter->setToolTip(i18n("Align center"));
155
156     m_unicodeAction = new QAction(KIcon("kdenlive-insert-unicode"), QString(), this);
157     m_unicodeAction->setShortcut(Qt::SHIFT + Qt::CTRL + Qt::Key_U);
158     m_unicodeAction->setToolTip(i18n("Insert Unicode character") + ' ' + m_unicodeAction->shortcut().toString());
159     connect(m_unicodeAction, SIGNAL(triggered()), this, SLOT(slotInsertUnicode()));
160     buttonInsertUnicode->setDefaultAction(m_unicodeAction);
161
162     origin_x_left->setToolTip(i18n("Invert x axis and change 0 point"));
163     origin_y_top->setToolTip(i18n("Invert y axis and change 0 point"));
164     rectBColor->setToolTip(i18n("Select fill color"));
165     rectFColor->setToolTip(i18n("Select border color"));
166     rectBAlpha->setToolTip(i18n("Fill transparency"));
167     rectFAlpha->setToolTip(i18n("Border transparency"));
168     zoom_slider->setToolTip(i18n("Zoom"));
169     buttonRealSize->setToolTip(i18n("Original size (1:1)"));
170     buttonFitZoom->setToolTip(i18n("Fit zoom"));
171     kcolorbutton->setToolTip(i18n("Select background color"));
172     horizontalSlider->setToolTip(i18n("Background Transparency"));
173
174     itemhcenter->setIcon(KIcon("kdenlive-align-hor"));
175     itemhcenter->setToolTip(i18n("Align item horizontally"));
176     itemvcenter->setIcon(KIcon("kdenlive-align-vert"));
177     itemvcenter->setToolTip(i18n("Align item vertically"));
178
179     QHBoxLayout *layout = new QHBoxLayout;
180     frame_toolbar->setLayout(layout);
181     layout->setContentsMargins(2, 2, 2, 2);
182     QToolBar *m_toolbar = new QToolBar("titleToolBar", this);
183
184     m_buttonCursor = m_toolbar->addAction(KIcon("transform-move"), QString());
185     m_buttonCursor->setCheckable(true);
186     m_buttonCursor->setShortcut(Qt::ALT + Qt::Key_S);
187     m_buttonCursor->setToolTip(i18n("Selection Tool") + ' ' + m_buttonCursor->shortcut().toString());
188     connect(m_buttonCursor, SIGNAL(triggered()), this, SLOT(slotSelectTool()));
189
190     m_buttonText = m_toolbar->addAction(KIcon("insert-text"), QString());
191     m_buttonText->setCheckable(true);
192     m_buttonText->setShortcut(Qt::ALT + Qt::Key_T);
193     m_buttonText->setToolTip(i18n("Add Text") + ' ' + m_buttonText->shortcut().toString());
194     connect(m_buttonText, SIGNAL(triggered()), this, SLOT(slotTextTool()));
195
196     m_buttonRect = m_toolbar->addAction(KIcon("kdenlive-insert-rect"), QString());
197     m_buttonRect->setCheckable(true);
198     m_buttonRect->setShortcut(Qt::ALT + Qt::Key_R);
199     m_buttonRect->setToolTip(i18n("Add Rectangle") + ' ' + m_buttonRect->shortcut().toString());
200     connect(m_buttonRect, SIGNAL(triggered()), this, SLOT(slotRectTool()));
201
202     m_buttonImage = m_toolbar->addAction(KIcon("insert-image"), QString());
203     m_buttonImage->setCheckable(false);
204     m_buttonImage->setShortcut(Qt::ALT + Qt::Key_I);
205     m_buttonImage->setToolTip(i18n("Add Image") + ' ' + m_buttonImage->shortcut().toString());
206     connect(m_buttonImage, SIGNAL(triggered()), this, SLOT(slotImageTool()));
207
208     m_toolbar->addSeparator();
209
210     m_buttonLoad = m_toolbar->addAction(KIcon("document-open"), i18n("Open Document"));
211     m_buttonLoad->setCheckable(false);
212     m_buttonLoad->setShortcut(Qt::CTRL + Qt::Key_O);
213     connect(m_buttonLoad, SIGNAL(triggered()), this, SLOT(loadTitle()));
214
215     m_buttonSave = m_toolbar->addAction(KIcon("document-save-as"), i18n("Save As"));
216     m_buttonSave->setCheckable(false);
217     m_buttonSave->setShortcut(Qt::CTRL + Qt::Key_S);
218     connect(m_buttonSave, SIGNAL(triggered()), this, SLOT(saveTitle()));
219
220     layout->addWidget(m_toolbar);
221
222     // initialize graphic scene
223     m_scene = new GraphicsSceneRectMove(this);
224     graphicsView->setScene(m_scene);
225     m_titledocument.setScene(m_scene, m_frameWidth, m_frameHeight);
226     connect(m_scene, SIGNAL(changed(QList<QRectF>)), this, SLOT(slotChanged()));
227
228     // a gradient background
229     /*QRadialGradient *gradient = new QRadialGradient(0, 0, 10);
230     gradient->setSpread(QGradient::ReflectSpread);
231     scene->setBackgroundBrush(*gradient);*/
232
233     m_frameImage = new QGraphicsPixmapItem();
234     QTransform qtrans;
235     qtrans.scale(2.0, 2.0);
236     m_frameImage->setTransform(qtrans);
237     m_frameImage->setZValue(-1200);
238     m_frameImage->setFlags(QGraphicsItem::ItemClipsToShape);
239     displayBackgroundFrame();
240     graphicsView->scene()->addItem(m_frameImage);
241
242     connect(m_scene, SIGNAL(selectionChanged()), this , SLOT(selectionChanged()));
243     connect(m_scene, SIGNAL(itemMoved()), this , SLOT(selectionChanged()));
244     connect(m_scene, SIGNAL(sceneZoom(bool)), this , SLOT(slotZoom(bool)));
245     connect(m_scene, SIGNAL(actionFinished()), this , SLOT(slotSelectTool()));
246     //connect(m_scene, SIGNAL(actionFinished()), this , SLOT(selectionChanged()));
247     connect(m_scene, SIGNAL(newRect(QGraphicsRectItem *)), this , SLOT(slotNewRect(QGraphicsRectItem *)));
248     connect(m_scene, SIGNAL(newText(QGraphicsTextItem *)), this , SLOT(slotNewText(QGraphicsTextItem *)));
249     connect(zoom_slider, SIGNAL(valueChanged(int)), this , SLOT(slotUpdateZoom(int)));
250
251     QPen framepen(Qt::DotLine);
252     framepen.setColor(Qt::red);
253
254     m_frameBorder = new QGraphicsRectItem(QRectF(0, 0, m_frameWidth, m_frameHeight));
255     m_frameBorder->setPen(framepen);
256     m_frameBorder->setZValue(-1100);
257     m_frameBorder->setBrush(Qt::transparent);
258     m_frameBorder->setFlags(QGraphicsItem::ItemClipsToShape);
259     graphicsView->scene()->addItem(m_frameBorder);
260
261     // mbd: load saved settings
262     readChoices();
263
264     initViewports();
265     graphicsView->show();
266     //graphicsView->setRenderHint(QPainter::Antialiasing);
267     graphicsView->setInteractive(true);
268     //graphicsView->resize(400, 300);
269     kDebug() << "// TITLE WIDGWT: " << graphicsView->viewport()->width() << "x" << graphicsView->viewport()->height();
270     //toolBox->setItemEnabled(2, false);
271     if (!url.isEmpty()) loadTitle(url);
272     else {
273         slotTextTool();
274         QTimer::singleShot(200, this, SLOT(slotAdjustZoom()));
275     }
276 }
277
278 TitleWidget::~TitleWidget()
279 {
280     delete m_buttonRect;
281     delete m_buttonText;
282     delete m_buttonImage;
283     delete m_buttonCursor;
284     delete m_buttonSave;
285     delete m_buttonLoad;
286     delete m_unicodeAction;
287
288     delete m_unicodeDialog;
289     delete m_frameBorder;
290     delete m_frameImage;
291     delete m_startViewport;
292     delete m_endViewport;
293     delete m_scene;
294     delete m_signalMapper;
295 }
296
297 //static
298 QStringList TitleWidget::getFreeTitleInfo(const KUrl &projectUrl, bool isClone)
299 {
300     QStringList result;
301     QString titlePath = projectUrl.path(KUrl::AddTrailingSlash) + "titles/";
302     KStandardDirs::makeDir(titlePath);
303     titlePath.append((isClone == false) ? "title" : "clone");
304     int counter = 0;
305     QString path;
306     while (path.isEmpty() || QFile::exists(path)) {
307         counter++;
308         path = titlePath + QString::number(counter).rightJustified(3, '0', false) + ".png";
309     }
310     result.append(((isClone == false) ? i18n("Title") : i18n("Clone")) + ' ' + QString::number(counter).rightJustified(3, '0', false));
311     result.append(path);
312     return result;
313 }
314
315 QString TitleWidget::getTitleResourceFromName(const KUrl &projectUrl, const QString &titleName)
316 {
317     QStringList result;
318     QString titlePath = projectUrl.path(KUrl::AddTrailingSlash) + "titles/";
319     KStandardDirs::makeDir(titlePath);
320     return titlePath + titleName + ".png";
321 }
322
323 //virtual
324 void TitleWidget::resizeEvent(QResizeEvent * /*event*/)
325 {
326     //slotAdjustZoom();
327 }
328
329 void TitleWidget::slotTextTool()
330 {
331     m_scene->setTool(TITLE_TEXT);
332     showToolbars(TITLE_TEXT);
333     checkButton(TITLE_TEXT);
334 }
335
336 void TitleWidget::slotRectTool()
337 {
338     m_scene->setTool(TITLE_RECTANGLE);
339     showToolbars(TITLE_RECTANGLE);
340     checkButton(TITLE_RECTANGLE);
341 }
342
343 void TitleWidget::slotSelectTool()
344 {
345     m_scene->setTool(TITLE_SELECT);
346
347     // Find out which toolbars need to be shown, depending on selected item
348     TITLETOOL t = TITLE_SELECT;
349     QList<QGraphicsItem *> l = graphicsView->scene()->selectedItems();
350     if (l.size() > 0) {
351         switch (l.at(0)->type()) {
352         case TEXTITEM:
353             t = TITLE_TEXT;
354             break;
355         case RECTITEM:
356             t = TITLE_RECTANGLE;
357             break;
358         case IMAGEITEM:
359             t = TITLE_IMAGE;
360             break;
361         }
362     }
363     enableToolbars(t);
364     showToolbars(t);
365
366     if (l.size() > 0) {
367         updateCoordinates(l.at(0));
368         updateDimension(l.at(0));
369         updateRotZoom(l.at(0));
370     }
371
372     checkButton(TITLE_SELECT);
373 }
374
375 void TitleWidget::slotImageTool()
376 {
377     KUrl url = KFileDialog::getOpenUrl(KUrl(), "*.svg *.png *.jpg *.jpeg *.gif *.raw", this, i18n("Load Image"));
378     if (!url.isEmpty()) {
379         if (url.path().endsWith(".svg")) {
380             QGraphicsSvgItem *svg = new QGraphicsSvgItem(url.toLocalFile());
381             svg->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
382             svg->setZValue(m_count++);
383             svg->setData(Qt::UserRole, url.path());
384             graphicsView->scene()->addItem(svg);
385         } else {
386             QPixmap pix(url.path());
387             QGraphicsPixmapItem *image = new QGraphicsPixmapItem(pix);
388             image->setShapeMode(QGraphicsPixmapItem::BoundingRectShape);
389             image->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
390             image->setData(Qt::UserRole, url.path());
391             image->setZValue(m_count++);
392             graphicsView->scene()->addItem(image);
393         }
394     }
395     m_scene->setTool(TITLE_SELECT);
396     showToolbars(TITLE_SELECT);
397     checkButton(TITLE_NONE);
398 }
399
400 void TitleWidget::showToolbars(TITLETOOL toolType)
401 {
402     switch (toolType) {
403     case TITLE_TEXT:
404         rect_properties->setHidden(true);
405         image_properties->setHidden(true);
406         no_properties->setHidden(true);
407         text_properties->setHidden(false);
408         break;
409     case TITLE_RECTANGLE:
410         image_properties->setHidden(true);
411         no_properties->setHidden(true);
412         text_properties->setHidden(true);
413         rect_properties->setHidden(false);
414         break;
415     case TITLE_IMAGE:
416         no_properties->setHidden(true);
417         text_properties->setHidden(true);
418         rect_properties->setHidden(true);
419         image_properties->setHidden(false);
420         break;
421     default:
422         text_properties->setHidden(true);
423         rect_properties->setHidden(true);
424         image_properties->setHidden(true);
425         no_properties->setHidden(false);
426         break;
427     }
428 }
429
430 void TitleWidget::enableToolbars(TITLETOOL toolType)
431 {
432     // TITLETOOL is defined in graphicsscenerectmove.h
433     bool bFrame = false;
434     bool bText = false;
435     bool bRect = false;
436     bool bImage = false;
437     bool bValue_w = false;
438     bool bValue_h = false;
439
440     switch (toolType) {
441     case TITLE_SELECT:
442         break;
443     case TITLE_TEXT:
444         bFrame = true;
445         bText = true;
446         break;
447     case TITLE_RECTANGLE:
448         bFrame = true;
449         bRect = true;
450         bValue_w = true;
451         bValue_h = true;
452         break;
453     case TITLE_IMAGE:
454         bFrame = true;
455         bValue_w = true;
456         bValue_h = true;
457         bImage = true;
458         break;
459     default:
460         break;
461     }
462     frame_properties->setEnabled(bFrame);
463     text_properties->setEnabled(bText);
464     rect_properties->setEnabled(bRect);
465     image_properties->setEnabled(bImage);
466     value_w->setEnabled(bValue_w);
467     value_h->setEnabled(bValue_h);
468 }
469
470 void TitleWidget::checkButton(TITLETOOL toolType)
471 {
472     bool bSelect = false;
473     bool bText = false;
474     bool bRect = false;
475     bool bImage = false;
476
477     switch (toolType) {
478     case TITLE_SELECT:
479         bSelect = true;
480         break;
481     case TITLE_TEXT:
482         bText = true;
483         break;
484     case TITLE_RECTANGLE:
485         bRect = true;
486         break;
487     case TITLE_IMAGE:
488         bImage = true;
489         break;
490     case TITLE_NONE:
491         break;
492     }
493
494     m_buttonCursor->setChecked(bSelect);
495     m_buttonText->setChecked(bText);
496     m_buttonRect->setChecked(bRect);
497     m_buttonImage->setChecked(bImage);
498 }
499
500 void TitleWidget::displayBackgroundFrame()
501 {
502     if (!displayBg->isChecked()) {
503         QPixmap bg(m_frameWidth / 2, m_frameHeight / 2);
504         QPixmap pattern(20, 20);
505         pattern.fill();
506         QColor bgcolor(210, 210, 210);
507         QPainter p;
508         p.begin(&pattern);
509         p.fillRect(QRect(0, 0, 10, 10), bgcolor);
510         p.fillRect(QRect(10, 10, 20, 20), bgcolor);
511         p.end();
512         QBrush br(pattern);
513
514         p.begin(&bg);
515         p.fillRect(bg.rect(), br);
516         p.end();
517         m_frameImage->setPixmap(bg);
518     } else {
519         m_frameImage->setPixmap(m_render->extractFrame((int) m_render->seekPosition().frames(m_render->fps()), m_frameWidth / 2, m_frameHeight / 2));
520     }
521 }
522
523 void TitleWidget::initViewports()
524 {
525     m_startViewport = new QGraphicsPolygonItem(QPolygonF(QRectF(0, 0, 0, 0)));
526     m_endViewport = new QGraphicsPolygonItem(QPolygonF(QRectF(0, 0, 0, 0)));
527
528     QPen startpen(Qt::DotLine);
529     QPen endpen(Qt::DashDotLine);
530     startpen.setColor(QColor(100, 200, 100, 140));
531     endpen.setColor(QColor(200, 100, 100, 140));
532
533     m_startViewport->setPen(startpen);
534     m_endViewport->setPen(endpen);
535
536     startViewportSize->setValue(100);
537     endViewportSize->setValue(100);
538
539     m_startViewport->setZValue(-1000);
540     m_endViewport->setZValue(-1000);
541
542     m_startViewport->setFlags(/*QGraphicsItem::ItemIsMovable|*/QGraphicsItem::ItemIsSelectable);
543     m_endViewport->setFlags(/*QGraphicsItem::ItemIsMovable|*/QGraphicsItem::ItemIsSelectable);
544
545     graphicsView->scene()->addItem(m_startViewport);
546     graphicsView->scene()->addItem(m_endViewport);
547 }
548
549 void TitleWidget::slotUpdateZoom(int pos)
550 {
551     m_scene->setZoom((double) pos / 100);
552     zoom_label->setText(QString::number(pos) + '%');
553 }
554
555 void TitleWidget::slotZoom(bool up)
556 {
557     int pos = zoom_slider->value();
558     if (up) pos++;
559     else pos--;
560     zoom_slider->setValue(pos);
561 }
562
563 void TitleWidget::slotAdjustZoom()
564 {
565     /*double scalex = graphicsView->width() / (double)(m_frameWidth * 1.2);
566     double scaley = graphicsView->height() / (double)(m_frameHeight * 1.2);
567     if (scalex > scaley) scalex = scaley;
568     int zoompos = (int)(scalex * 7 + 0.5);*/
569     graphicsView->fitInView(m_frameBorder, Qt::KeepAspectRatio);
570     int zoompos = graphicsView->matrix().m11() * 100;
571     zoom_slider->setValue(zoompos);
572     graphicsView->centerOn(m_frameBorder);
573 }
574
575 void TitleWidget::slotZoomOneToOne()
576 {
577     zoom_slider->setValue(100);
578     graphicsView->centerOn(m_frameBorder);
579 }
580
581 void TitleWidget::slotNewRect(QGraphicsRectItem * rect)
582 {
583     updateAxisButtons(rect); // back to default
584
585     QColor f = rectFColor->color();
586     f.setAlpha(rectFAlpha->value());
587     QPen penf(f);
588     penf.setWidth(rectLineWidth->value());
589     rect->setPen(penf);
590     QColor b = rectBColor->color();
591     b.setAlpha(rectBAlpha->value());
592     rect->setBrush(QBrush(b));
593     rect->setZValue(m_count++);
594     //setCurrentItem(rect);
595     //graphicsView->setFocus();
596 }
597
598 void TitleWidget::slotNewText(QGraphicsTextItem *tt)
599 {
600     updateAxisButtons(tt); // back to default
601
602     QFont font = font_family->currentFont();
603     font.setPixelSize(font_size->value());
604     // mbd: issue 551:
605     font.setWeight(font_weight_box->itemData(font_weight_box->currentIndex()).toInt());
606     font.setItalic(buttonItalic->isChecked());
607     font.setUnderline(buttonUnder->isChecked());
608
609     tt->setFont(font);
610     QColor color = fontColorButton->color();
611     color.setAlpha(textAlpha->value());
612     tt->setDefaultTextColor(color);
613     tt->setZValue(m_count++);
614     setCurrentItem(tt);
615 }
616
617 void TitleWidget::setFontBoxWeight(int weight)
618 {
619     int index = font_weight_box->findData(weight);
620     if (index < 0) {
621         index = font_weight_box->findData(QFont::Normal);
622     }
623     font_weight_box->setCurrentIndex(index);
624 }
625
626 void TitleWidget::setCurrentItem(QGraphicsItem *item)
627 {
628     m_scene->setSelectedItem(item);
629 }
630
631 void TitleWidget::zIndexChanged(int v)
632 {
633     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
634     if (l.size() >= 1) {
635         l[0]->setZValue(v);
636     }
637 }
638
639 void TitleWidget::selectionChanged()
640 {
641     if (m_scene->tool() != TITLE_SELECT) return;
642     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
643     //toolBox->setItemEnabled(2, false);
644     //toolBox->setItemEnabled(3, false);
645     value_x->blockSignals(true);
646     value_y->blockSignals(true);
647     value_w->blockSignals(true);
648     value_h->blockSignals(true);
649     itemzoom->blockSignals(true);
650     itemrotate->blockSignals(true);
651     if (l.size() == 0) {
652         bool blockX = !origin_x_left->signalsBlocked();
653         bool blockY = !origin_y_top->signalsBlocked();
654         if (blockX) origin_x_left->blockSignals(true);
655         if (blockY) origin_y_top->blockSignals(true);
656         origin_x_left->setChecked(false);
657         origin_y_top->setChecked(false);
658         updateTextOriginX();
659         updateTextOriginY();
660         enableToolbars(TITLE_NONE);
661         if (blockX) origin_x_left->blockSignals(false);
662         if (blockY) origin_y_top->blockSignals(false);
663     } else if (l.size() == 1) {
664         if (l.at(0)->type() == TEXTITEM) {
665             showToolbars(TITLE_TEXT);
666             QGraphicsTextItem* i = static_cast <QGraphicsTextItem *>(l.at(0));
667             //if (l[0]->hasFocus())
668             toolBox->setCurrentIndex(0);
669             //toolBox->setItemEnabled(2, true);
670             font_size->blockSignals(true);
671             font_family->blockSignals(true);
672             font_weight_box->blockSignals(true);
673             buttonItalic->blockSignals(true);
674             buttonUnder->blockSignals(true);
675             fontColorButton->blockSignals(true);
676             textAlpha->blockSignals(true);
677             buttonAlignLeft->blockSignals(true);
678             buttonAlignRight->blockSignals(true);
679             buttonAlignNone->blockSignals(true);
680             buttonAlignCenter->blockSignals(true);
681
682             QFont font = i->font();
683             font_family->setCurrentFont(font);
684             font_size->setValue(font.pixelSize());
685             buttonItalic->setChecked(font.italic());
686             buttonUnder->setChecked(font.underline());
687             setFontBoxWeight(font.weight());
688
689             QColor color = i->defaultTextColor();
690             fontColorButton->setColor(color);
691             textAlpha->setValue(color.alpha());
692
693             QTextCursor cur = i->textCursor();
694             QTextBlockFormat format = cur.blockFormat();
695             if (i->textWidth() == -1) buttonAlignNone->setChecked(true);
696             else if (format.alignment() == Qt::AlignHCenter) buttonAlignCenter->setChecked(true);
697             else if (format.alignment() == Qt::AlignRight) buttonAlignRight->setChecked(true);
698             else if (format.alignment() == Qt::AlignLeft) buttonAlignLeft->setChecked(true);
699
700             font_size->blockSignals(false);
701             font_family->blockSignals(false);
702             font_weight_box->blockSignals(false);
703             buttonItalic->blockSignals(false);
704             buttonUnder->blockSignals(false);
705             fontColorButton->blockSignals(false);
706             textAlpha->blockSignals(false);
707             buttonAlignLeft->blockSignals(false);
708             buttonAlignRight->blockSignals(false);
709             buttonAlignNone->blockSignals(false);
710             buttonAlignCenter->blockSignals(false);
711
712             updateAxisButtons(i);
713             updateCoordinates(i);
714             updateDimension(i);
715             enableToolbars(TITLE_TEXT);
716
717         } else if ((l.at(0))->type() == RECTITEM) {
718             showToolbars(TITLE_RECTANGLE);
719             settingUp = true;
720             QGraphicsRectItem *rec = static_cast <QGraphicsRectItem *>(l.at(0));
721             toolBox->setCurrentIndex(0);
722             //toolBox->setItemEnabled(3, true);
723             rectFAlpha->setValue(rec->pen().color().alpha());
724             rectBAlpha->setValue(rec->brush().color().alpha());
725             //kDebug() << rec->brush().color().alpha();
726             QColor fcol = rec->pen().color();
727             QColor bcol = rec->brush().color();
728             //fcol.setAlpha(255);
729             //bcol.setAlpha(255);
730             rectFColor->setColor(fcol);
731             rectBColor->setColor(bcol);
732             settingUp = false;
733             rectLineWidth->setValue(rec->pen().width());
734
735             updateAxisButtons(l.at(0));
736             updateCoordinates(rec);
737             updateDimension(rec);
738             enableToolbars(TITLE_RECTANGLE);
739
740         } else if (l.at(0)->type() == IMAGEITEM) {
741             showToolbars(TITLE_IMAGE);
742
743             updateCoordinates(l.at(0));
744             updateDimension(l.at(0));
745
746             enableToolbars(TITLE_IMAGE);
747
748         } else {
749             //toolBox->setCurrentIndex(0);
750             showToolbars(TITLE_NONE);
751             enableToolbars(TITLE_NONE);
752             /*frame_properties->setEnabled(false);
753             text_properties->setEnabled(false);
754             rect_properties->setEnabled(false);*/
755         }
756         zValue->setValue((int)l.at(0)->zValue());
757         itemzoom->setValue((int)(m_transformations.value(l.at(0)).scalex * 100.0 + 0.5));
758         itemrotate->setValue((int)(m_transformations.value(l.at(0)).rotate));
759         value_x->blockSignals(false);
760         value_y->blockSignals(false);
761         value_w->blockSignals(false);
762         value_h->blockSignals(false);
763         itemzoom->blockSignals(false);
764         itemrotate->blockSignals(false);
765     }
766 }
767
768 void TitleWidget::slotValueChanged(int type)
769 {
770     QList<QGraphicsItem *> l = graphicsView->scene()->selectedItems();
771     if (l.size() > 0 && l.at(0)->type() == IMAGEITEM) {
772
773         int val = 0;
774         switch (type) {
775         case ValueWidth:
776             val = value_w->value();
777             break;
778         case ValueHeight:
779             val = value_h->value();
780             break;
781         }
782
783         QGraphicsItem *i = l.at(0);
784         Transform t = m_transformations.value(i);
785
786         // Ratio width:height
787         double phi = (double) i->boundingRect().width() / i->boundingRect().height();
788         double alpha = (double) t.rotate / 180.0 * M_PI;
789
790         // New length
791         double length = val;
792
793         // Scaling factor
794         double scale = 1;
795
796         switch (type) {
797         case ValueWidth:
798             // Add 0.5 because otherwise incrementing by 1 might have no effect
799             length = val / (cos(alpha) + 1 / phi * sin(alpha)) + 0.5;
800             scale = length / i->boundingRect().width();
801             break;
802         case ValueHeight:
803             length = val / (phi * sin(alpha) + cos(alpha)) + 0.5;
804             scale = length / i->boundingRect().height();
805             break;
806         }
807
808         t.scalex = scale;
809         t.scaley = scale;
810         QTransform qtrans;
811         qtrans.scale(scale, scale);
812         qtrans.rotate(t.rotate);
813         i->setTransform(qtrans);
814         m_transformations[i] = t;
815
816         updateDimension(i);
817         updateRotZoom(i);
818     }
819 }
820
821 /** \brief Updates position/size of the selected item when a value
822  * of an item (coordinates, size) has changed */
823 void TitleWidget::slotAdjustSelectedItem()
824 {
825     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
826     if (l.size() >= 1) {
827         if (l.at(0)->type() == RECTITEM) {
828             //rect item
829             QGraphicsRectItem *rec = static_cast <QGraphicsRectItem *>(l.at(0));
830             updatePosition(rec);
831             rec->setRect(QRect(0, 0, value_w->value(), value_h->value()));
832         } else if (l.at(0)->type() == TEXTITEM) {
833             //text item
834             updatePosition(l.at(0));
835         } else if (l.at(0)->type() == IMAGEITEM) {
836             //image item
837             updatePosition(l.at(0));
838         }
839     }
840 }
841
842 /** \brief Updates width/height int the text fields, regarding transformation matrix */
843 void TitleWidget::updateDimension(QGraphicsItem *i)
844 {
845     value_w->blockSignals(true);
846     value_h->blockSignals(true);
847
848
849     if (i->type() == IMAGEITEM) {
850         // Get multipliers for rotation/scaling
851
852         /*Transform t = m_transformations.value(i);
853         QRectF r = i->boundingRect();
854         int width = (int) ( abs(r.width()*t.scalex * cos(t.rotate/180.0*M_PI))
855                     + abs(r.height()*t.scaley * sin(t.rotate/180.0*M_PI)) );
856         int height = (int) ( abs(r.height()*t.scaley * cos(t.rotate/180*M_PI))
857                     + abs(r.width()*t.scalex * sin(t.rotate/180*M_PI)) );*/
858
859         value_w->setValue(i->sceneBoundingRect().width());
860         value_h->setValue(i->sceneBoundingRect().height());
861     } else if (i->type() == RECTITEM) {
862         QGraphicsRectItem *r = static_cast <QGraphicsRectItem *>(i);
863         value_w->setValue((int) r->rect().width());
864         value_h->setValue((int) r->rect().height());
865     } else if (i->type() == TEXTITEM) {
866         QGraphicsTextItem *t = static_cast <QGraphicsTextItem *>(i);
867         value_w->setValue((int) t->boundingRect().width());
868         value_h->setValue((int) t->boundingRect().height());
869     }
870
871     value_w->blockSignals(false);
872     value_h->blockSignals(false);
873 }
874
875 /** \brief Updates the coordinates in the text fields from the item */
876 void TitleWidget::updateCoordinates(QGraphicsItem *i)
877 {
878     // Block signals emitted by this method
879     value_x->blockSignals(true);
880     value_y->blockSignals(true);
881
882     if (i->type() == TEXTITEM) {
883
884         QGraphicsTextItem *rec = static_cast <QGraphicsTextItem *>(i);
885
886         // Set the correct x coordinate value
887         if (origin_x_left->isChecked()) {
888             // Origin (0 point) is at m_frameWidth, coordinate axis is inverted
889             value_x->setValue((int)(m_frameWidth - rec->pos().x() - rec->boundingRect().width()));
890         } else {
891             // Origin is at 0 (default)
892             value_x->setValue((int) rec->pos().x());
893         }
894
895         // Same for y
896         if (origin_y_top->isChecked()) {
897             value_y->setValue((int)(m_frameHeight - rec->pos().y() - rec->boundingRect().height()));
898         } else {
899             value_y->setValue((int) rec->pos().y());
900         }
901
902     } else if (i->type() == RECTITEM) {
903
904         QGraphicsRectItem *rec = static_cast <QGraphicsRectItem *>(i);
905
906         if (origin_x_left->isChecked()) {
907             // Origin (0 point) is at m_frameWidth
908             value_x->setValue((int)(m_frameWidth - rec->pos().x() - rec->rect().width()));
909         } else {
910             // Origin is at 0 (default)
911             value_x->setValue((int) rec->pos().x());
912         }
913
914         if (origin_y_top->isChecked()) {
915             value_y->setValue((int)(m_frameHeight - rec->pos().y() - rec->rect().height()));
916         } else {
917             value_y->setValue((int) rec->pos().y());
918         }
919
920     } else if (i->type() == IMAGEITEM) {
921
922         if (origin_x_left->isChecked()) {
923             value_x->setValue((int)(m_frameWidth - i->pos().x() - i->sceneBoundingRect().width()));
924         } else {
925             value_x->setValue((int) i->pos().x());
926         }
927
928         if (origin_y_top->isChecked()) {
929             value_y->setValue((int)(m_frameHeight - i->pos().y() - i->sceneBoundingRect().height()));
930         } else {
931             value_y->setValue((int) i->pos().y());
932         }
933
934     }
935
936     // Stop blocking signals now
937     value_x->blockSignals(false);
938     value_y->blockSignals(false);
939 }
940
941 void TitleWidget::updateRotZoom(QGraphicsItem *i)
942 {
943     itemzoom->blockSignals(true);
944     itemrotate->blockSignals(false);
945
946     Transform t = m_transformations.value(i);
947     itemzoom->setValue((int)(t.scalex * 100.0 + 0.5));
948     itemrotate->setValue((int)(t.rotate));
949
950     itemzoom->blockSignals(false);
951     itemrotate->blockSignals(false);
952 }
953
954 /** \brief Updates the position of an item by reading coordinates from the text fields */
955 void TitleWidget::updatePosition(QGraphicsItem *i)
956 {
957     if (i->type() == TEXTITEM) {
958         QGraphicsTextItem *rec = static_cast <QGraphicsTextItem *>(i);
959
960         int posX;
961         if (origin_x_left->isChecked()) {
962             /* Origin of the x axis is at m_frameWidth,
963              * and distance from right border of the item to the right
964              * border of the frame is taken.
965              * See comment to slotOriginXClicked().
966              */
967             posX = m_frameWidth - value_x->value() - rec->boundingRect().width();
968         } else {
969             posX = value_x->value();
970         }
971
972         int posY;
973         if (origin_y_top->isChecked()) {
974             /* Same for y axis */
975             posY = m_frameHeight - value_y->value() - rec->boundingRect().height();
976         } else {
977             posY = value_y->value();
978         }
979
980         rec->setPos(posX, posY);
981
982     } else if (i->type() == RECTITEM) {
983
984         QGraphicsRectItem *rec = static_cast <QGraphicsRectItem *>(i);
985
986         int posX;
987         if (origin_x_left->isChecked()) {
988             posX = m_frameWidth - value_x->value() - rec->rect().width();
989         } else {
990             posX = value_x->value();
991         }
992
993         int posY;
994         if (origin_y_top->isChecked()) {
995             posY = m_frameHeight - value_y->value() - rec->rect().height();
996         } else {
997             posY = value_y->value();
998         }
999
1000         rec->setPos(posX, posY);
1001
1002     } else if (i->type() == IMAGEITEM) {
1003         int posX;
1004         if (origin_x_left->isChecked()) {
1005             // Use the sceneBoundingRect because this also regards transformations like zoom
1006             posX = m_frameWidth - value_x->value() - i->sceneBoundingRect().width();
1007         } else {
1008             posX = value_x->value();
1009         }
1010
1011         int posY;
1012         if (origin_y_top->isChecked()) {
1013             posY = m_frameHeight - value_y->value() - i->sceneBoundingRect().height();
1014         } else {
1015             posY = value_y->value();
1016         }
1017
1018         i->setPos(posX, posY);
1019
1020     }
1021
1022 }
1023
1024 void TitleWidget::updateTextOriginX()
1025 {
1026     if (origin_x_left->isChecked()) {
1027         origin_x_left->setText(i18n("\u2212X"));
1028     } else {
1029         origin_x_left->setText(i18n("+X"));
1030     }
1031 }
1032
1033 void TitleWidget::slotOriginXClicked()
1034 {
1035     // Update the text displayed on the button.
1036     updateTextOriginX();
1037
1038     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1039     if (l.size() >= 1) {
1040         updateCoordinates(l.at(0));
1041
1042         // Remember x axis setting
1043         l.at(0)->setData(TitleDocument::OriginXLeft, origin_x_left->isChecked() ?
1044                          TitleDocument::AxisInverted : TitleDocument::AxisDefault);
1045     }
1046     graphicsView->setFocus();
1047 }
1048
1049 void TitleWidget::updateTextOriginY()
1050 {
1051     if (origin_y_top->isChecked()) {
1052         origin_y_top->setText(i18n("\u2212Y"));
1053     } else {
1054         origin_y_top->setText(i18n("+Y"));
1055     }
1056 }
1057
1058 void TitleWidget::slotOriginYClicked()
1059 {
1060     // Update the text displayed on the button.
1061     updateTextOriginY();
1062
1063     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1064     if (l.size() >= 1) {
1065         updateCoordinates(l.at(0));
1066
1067         l.at(0)->setData(TitleDocument::OriginYTop, origin_y_top->isChecked() ?
1068                          TitleDocument::AxisInverted : TitleDocument::AxisDefault);
1069
1070     }
1071     graphicsView->setFocus();
1072 }
1073
1074 void TitleWidget::updateAxisButtons(QGraphicsItem *i)
1075 {
1076     int xAxis = i->data(TitleDocument::OriginXLeft).toInt();
1077     int yAxis = i->data(TitleDocument::OriginYTop).toInt();
1078     origin_x_left->blockSignals(true);
1079     origin_y_top->blockSignals(true);
1080
1081     if (xAxis == TitleDocument::AxisInverted) {
1082         origin_x_left->setChecked(true);
1083     } else {
1084         origin_x_left->setChecked(false);
1085     }
1086     updateTextOriginX();
1087
1088     if (yAxis == TitleDocument::AxisInverted) {
1089         origin_y_top->setChecked(true);
1090     } else {
1091         origin_y_top->setChecked(false);
1092     }
1093     updateTextOriginY();
1094
1095     origin_x_left->blockSignals(false);
1096     origin_y_top->blockSignals(false);
1097 }
1098
1099 void TitleWidget::slotChangeBackground()
1100 {
1101     QColor color = kcolorbutton->color();
1102     color.setAlpha(horizontalSlider->value());
1103     m_frameBorder->setBrush(QBrush(color));
1104 }
1105
1106 /**
1107  * Something (yeah) has changed in our QGraphicsScene.
1108  */
1109 void TitleWidget::slotChanged()
1110 {
1111     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1112     if (l.size() >= 1 && l.at(0)->type() == TEXTITEM) {
1113         textChanged(static_cast <QGraphicsTextItem *>(l.at(0)));
1114     }
1115 }
1116
1117 /**
1118  * If the user has set origin_x_left (everything also for y),
1119  * we need to look whether a text element has been selected. If yes,
1120  * we need to ensure that the right border of the text field
1121  * remains fixed also when some text has been entered.
1122  *
1123  * This is also known as right-justified, with the difference that
1124  * it is not valid for text but for its boundingRect. Text may still
1125  * be left-justified.
1126  */
1127 void TitleWidget::textChanged(QGraphicsTextItem *i)
1128 {
1129
1130     updateDimension(i);
1131
1132     if (origin_x_left->isChecked() || origin_y_top->isChecked()) {
1133
1134         if (!i->toPlainText().isEmpty()) {
1135             updatePosition(i);
1136         } else {
1137             /*
1138              * Don't do anything if the string is empty. If the position
1139              * would be updated here, a newly created text field would
1140              * be set to the position of the last selected text field.
1141              */
1142         }
1143     }
1144 }
1145
1146 void TitleWidget::slotInsertUnicode()
1147 {
1148     m_unicodeDialog->exec();
1149 }
1150
1151 void TitleWidget::slotInsertUnicodeString(QString text)
1152 {
1153     QList<QGraphicsItem *> l = graphicsView->scene()->selectedItems();
1154     if (l.size() > 0) {
1155         if (l.at(0)->type() == TEXTITEM) {
1156             QGraphicsTextItem *t = static_cast <QGraphicsTextItem *>(l.at(0));
1157             t->textCursor().insertText(text);
1158         }
1159     }
1160 }
1161
1162 void TitleWidget::slotUpdateText()
1163 {
1164     QFont font = font_family->currentFont();
1165     font.setPixelSize(font_size->value());
1166     font.setItalic(buttonItalic->isChecked());
1167     font.setUnderline(buttonUnder->isChecked());
1168     font.setWeight(font_weight_box->itemData(font_weight_box->currentIndex()).toInt());
1169     QColor color = fontColorButton->color();
1170     color.setAlpha(textAlpha->value());
1171
1172     QGraphicsTextItem* item = NULL;
1173     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1174     if (l.size() == 1 && l.at(0)->type() == TEXTITEM) {
1175         item = static_cast <QGraphicsTextItem *>(l.at(0));
1176     }
1177     if (!item) return;
1178     //if (item->textCursor().selection ().isEmpty())
1179     QTextCursor cur = item->textCursor();
1180     QTextBlockFormat format = cur.blockFormat();
1181     if (buttonAlignLeft->isChecked() || buttonAlignCenter->isChecked() || buttonAlignRight->isChecked()) {
1182         item->setTextWidth(item->boundingRect().width());
1183         if (buttonAlignCenter->isChecked()) format.setAlignment(Qt::AlignHCenter);
1184         else if (buttonAlignRight->isChecked()) format.setAlignment(Qt::AlignRight);
1185         else if (buttonAlignLeft->isChecked()) format.setAlignment(Qt::AlignLeft);
1186     } else {
1187         format.setAlignment(Qt::AlignLeft);
1188         item->setTextWidth(-1);
1189     }
1190
1191     {
1192         item->setFont(font);
1193         item->setDefaultTextColor(color);
1194         cur.select(QTextCursor::Document);
1195         cur.setBlockFormat(format);
1196         item->setTextCursor(cur);
1197         cur.clearSelection();
1198         item->setTextCursor(cur);
1199
1200     }
1201 }
1202
1203 void TitleWidget::rectChanged()
1204 {
1205     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1206     if (l.size() == 1 && l.at(0)->type() == RECTITEM && !settingUp) {
1207         QGraphicsRectItem *rec = static_cast<QGraphicsRectItem *>(l.at(0));
1208         QColor f = rectFColor->color();
1209         f.setAlpha(rectFAlpha->value());
1210         QPen penf(f);
1211         penf.setWidth(rectLineWidth->value());
1212         rec->setPen(penf);
1213         QColor b = rectBColor->color();
1214         b.setAlpha(rectBAlpha->value());
1215         rec->setBrush(QBrush(b));
1216     }
1217 }
1218
1219 void TitleWidget::itemScaled(int val)
1220 {
1221     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1222     if (l.size() == 1) {
1223         Transform x = m_transformations.value(l.at(0));
1224         x.scalex = (double)val / 100.0;
1225         x.scaley = (double)val / 100.0;
1226         QTransform qtrans;
1227         qtrans.scale(x.scalex, x.scaley);
1228         qtrans.rotate(x.rotate);
1229         l[0]->setTransform(qtrans);
1230         m_transformations[l.at(0)] = x;
1231         updateDimension(l.at(0));
1232     }
1233 }
1234
1235 void TitleWidget::itemRotate(int val)
1236 {
1237     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1238     if (l.size() == 1) {
1239         Transform x = m_transformations[l.at(0)];
1240         x.rotate = (double)val;
1241         QTransform qtrans;
1242         qtrans.scale(x.scalex, x.scaley);
1243         qtrans.rotate(x.rotate);
1244         l[0]->setTransform(qtrans);
1245         m_transformations[l.at(0)] = x;
1246         updateDimension(l.at(0));
1247     }
1248 }
1249
1250 void TitleWidget::itemHCenter()
1251 {
1252     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1253     if (l.size() == 1) {
1254         QGraphicsItem *item = l.at(0);
1255         QRectF br;
1256         br = item->sceneBoundingRect();
1257         int width = (int)br.width();
1258         int newPos = (int)((m_frameWidth - width) / 2);
1259         newPos += item->pos().x() - br.left(); // Check item transformation
1260         item->setPos(newPos, item->pos().y());
1261         updateCoordinates(item);
1262     }
1263 }
1264
1265 void TitleWidget::itemVCenter()
1266 {
1267     QList<QGraphicsItem*> l = graphicsView->scene()->selectedItems();
1268     if (l.size() == 1) {
1269         QGraphicsItem *item = l.at(0);
1270         QRectF br;
1271         br = item->sceneBoundingRect();
1272         int height = (int)br.height();
1273         int newPos = (int)((m_frameHeight - height) / 2);
1274         newPos += item->pos().y() - br.top(); // Check item transformation
1275         item->setPos(item->pos().x(), newPos);
1276         updateCoordinates(item);
1277     }
1278 }
1279
1280 void TitleWidget::setupViewports()
1281 {
1282     //double aspect_ratio = 4.0 / 3.0;//read from project
1283     //better zoom centered, but render uses only the created rect, so no problem to change the zoom function
1284     QRectF sp(0, 0, startViewportSize->value() * m_frameWidth / 100.0 , startViewportSize->value()* m_frameHeight / 100.0);
1285     QRectF ep(0, 0, endViewportSize->value() * m_frameWidth / 100.0, endViewportSize->value() * m_frameHeight / 100.0);
1286     // use a polygon thiat uses 16:9 and 4:3 rects forpreview the size in all aspect ratios ?
1287     QPolygonF spoly(sp);
1288     QPolygonF epoly(ep);
1289     spoly.translate(startViewportX->value(), startViewportY->value());
1290     epoly.translate(endViewportX->value(), endViewportY->value());
1291     m_startViewport->setPolygon(spoly);
1292     m_endViewport->setPolygon(epoly);
1293     if (! insertingValues) {
1294         m_startViewport->setData(0, startViewportX->value());
1295         m_startViewport->setData(1, startViewportY->value());
1296         m_startViewport->setData(2, startViewportSize->value());
1297
1298         m_endViewport->setData(0, endViewportX->value());
1299         m_endViewport->setData(1, endViewportY->value());
1300         m_endViewport->setData(2, endViewportSize->value());
1301     }
1302 }
1303
1304 void TitleWidget::loadTitle(KUrl url)
1305 {
1306     if (url.isEmpty()) url = KFileDialog::getOpenUrl(KUrl(m_projectTitlePath), "application/x-kdenlivetitle", this, i18n("Load Title"));
1307     if (!url.isEmpty()) {
1308         QList<QGraphicsItem *> items = m_scene->items();
1309         for (int i = 0; i < items.size(); i++) {
1310             if (items.at(i)->zValue() > -1000) delete items.at(i);
1311         }
1312         m_scene->clearTextSelection();
1313         QDomDocument doc;
1314         QString tmpfile;
1315
1316         if (KIO::NetAccess::download(url, tmpfile, 0)) {
1317             QFile file(tmpfile);
1318             if (file.open(QIODevice::ReadOnly)) {
1319                 doc.setContent(&file, false);
1320                 file.close();
1321             } else return;
1322             KIO::NetAccess::removeTempFile(tmpfile);
1323         }
1324         setXml(doc);
1325         /*int out;
1326         m_count = m_titledocument.loadDocument(url, m_startViewport, m_endViewport, &out) + 1;
1327         adjustFrameSize();
1328         title_duration->setText(m_tc.getTimecode(GenTime(out, m_render->fps())));
1329         insertingValues = true;
1330         startViewportX->setValue(m_startViewport->data(0).toInt());
1331         startViewportY->setValue(m_startViewport->data(1).toInt());
1332         startViewportSize->setValue(m_startViewport->data(2).toInt());
1333         endViewportX->setValue(m_endViewport->data(0).toInt());
1334         endViewportY->setValue(m_endViewport->data(1).toInt());
1335         endViewportSize->setValue(m_endViewport->data(2).toInt());
1336
1337         insertingValues = false;
1338         slotSelectTool();
1339         slotAdjustZoom();*/
1340     }
1341 }
1342
1343 void TitleWidget::saveTitle(KUrl url)
1344 {
1345     if (url.isEmpty()) url = KFileDialog::getSaveUrl(KUrl(m_projectTitlePath), "application/x-kdenlivetitle", this, i18n("Save Title"));
1346     if (!url.isEmpty()) {
1347         if (m_titledocument.saveDocument(url, m_startViewport, m_endViewport, m_tc.getFrameCount(title_duration->text())) == false)
1348             KMessageBox::error(this, i18n("Cannot write to file %1", url.path()));
1349     }
1350 }
1351
1352 QDomDocument TitleWidget::xml()
1353 {
1354     QDomDocument doc = m_titledocument.xml(m_startViewport, m_endViewport);
1355     doc.documentElement().setAttribute("out", m_tc.getFrameCount(title_duration->text()));
1356     if (cropImage->isChecked()) {
1357         doc.documentElement().setAttribute("crop", 1);
1358     }
1359     return doc;
1360 }
1361
1362 int TitleWidget::duration() const
1363 {
1364     return m_tc.getFrameCount(title_duration->text());
1365 }
1366
1367 void TitleWidget::setXml(QDomDocument doc)
1368 {
1369     int out;
1370     m_count = m_titledocument.loadFromXml(doc, m_startViewport, m_endViewport, &out);
1371     adjustFrameSize();
1372     title_duration->setText(m_tc.getTimecode(GenTime(out, m_render->fps())));
1373     /*if (doc.documentElement().hasAttribute("out")) {
1374     GenTime duration = GenTime(doc.documentElement().attribute("out").toDouble() / 1000.0);
1375     title_duration->setText(m_tc.getTimecode(duration));
1376     }
1377     else title_duration->setText(m_tc.getTimecode(GenTime(5000)));*/
1378
1379     QDomElement e = doc.documentElement();
1380     cropImage->setChecked(e.hasAttribute("crop"));
1381     m_transformations.clear();
1382     QList <QGraphicsItem *> items = graphicsView->scene()->items();
1383     const double PI = 4.0 * atan(1.0);
1384     for (int i = 0; i < items.count(); i++) {
1385         QTransform t = items.at(i)->transform();
1386         Transform x;
1387         x.scalex = t.m11();
1388         x.scaley = t.m22();
1389         x.rotate = 180. / PI * atan2(-t.m21(), t.m11());
1390         m_transformations[items.at(i)] = x;
1391     }
1392     // mbd: Update the GUI color selectors to match the stuff from the loaded document
1393     QColor background_color = m_titledocument.getBackgroundColor();
1394     horizontalSlider->blockSignals(true);
1395     kcolorbutton->blockSignals(true);
1396     horizontalSlider->setValue(background_color.alpha());
1397     background_color.setAlpha(255);
1398     kcolorbutton->setColor(background_color);
1399     horizontalSlider->blockSignals(false);
1400     kcolorbutton->blockSignals(false);
1401
1402     startViewportX->setValue(m_startViewport->data(0).toInt());
1403     startViewportY->setValue(m_startViewport->data(1).toInt());
1404     startViewportSize->setValue(m_startViewport->data(2).toInt());
1405     endViewportX->setValue(m_endViewport->data(0).toInt());
1406     endViewportY->setValue(m_endViewport->data(1).toInt());
1407     endViewportSize->setValue(m_endViewport->data(2).toInt());
1408
1409     QTimer::singleShot(200, this, SLOT(slotAdjustZoom()));
1410     slotSelectTool();
1411 }
1412
1413 const QRect TitleWidget::renderedRect()
1414 {
1415     int minX = 0;
1416     int minY = 0;
1417     int maxX = m_frameWidth;
1418     int maxY = m_frameHeight;
1419     if (!cropImage->isChecked()) {
1420         m_scene->removeItem(m_startViewport);
1421         m_scene->removeItem(m_endViewport);
1422         QRect boundingRect = m_scene->itemsBoundingRect().toRect();
1423         if (boundingRect.left() < 0) minX = boundingRect.left();
1424         if (boundingRect.top() < 0) minY = boundingRect.top();
1425         if (boundingRect.right() > maxX) maxX = boundingRect.right();
1426         if (boundingRect.bottom() > maxY) maxY = boundingRect.bottom();
1427         if (minX < 0) {
1428             maxX = maxX - minX;
1429         }
1430         if (minY < 0) {
1431             maxY = maxY - minY;
1432         }
1433     }
1434     QRect rect(minX, minY, maxX, maxY);
1435     return rect;
1436 }
1437
1438 QImage TitleWidget::renderedPixmap()
1439 {
1440     QRect rect = renderedRect();
1441     QImage pix(rect.width(), rect.height(), QImage::Format_ARGB32);
1442     pix.fill(Qt::transparent);
1443     QPainter painter(&pix);
1444     painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::HighQualityAntialiasing);
1445     m_scene->clearTextSelection();
1446     QPen framepen = m_frameBorder->pen();
1447     m_frameBorder->setPen(Qt::NoPen);
1448     m_startViewport->setVisible(false);
1449     m_endViewport->setVisible(false);
1450     m_frameImage->setVisible(false);
1451
1452     m_scene->render(&painter, QRectF(), rect); //QRectF(minX, minY, maxX - minX, maxY - minY));
1453     painter.end();
1454     m_frameBorder->setPen(framepen);
1455     m_startViewport->setVisible(true);
1456     m_endViewport->setVisible(true);
1457     m_frameImage->setVisible(true);
1458     return pix;
1459 }
1460
1461 /** \brief Connected to the accepted signal - calls writeChoices */
1462 void TitleWidget::slotAccepted()
1463 {
1464     writeChoices();
1465 }
1466
1467 /** \brief Store the current choices of font, background and rect values */
1468 void TitleWidget::writeChoices()
1469 {
1470     // Get a pointer to a shared configuration instance, then get the TitleWidget group.
1471     KSharedConfigPtr config = KGlobal::config();
1472     KConfigGroup titleConfig(config, "TitleWidget");
1473     // Write the entries
1474     titleConfig.writeEntry("font_family", font_family->currentFont());
1475     //titleConfig.writeEntry("font_size", font_size->value());
1476     titleConfig.writeEntry("font_pixel_size", font_size->value());
1477     titleConfig.writeEntry("font_color", fontColorButton->color());
1478     titleConfig.writeEntry("font_alpha", textAlpha->value());
1479     titleConfig.writeEntry("font_weight", font_weight_box->itemData(font_weight_box->currentIndex()).toInt());
1480     titleConfig.writeEntry("font_italic", buttonItalic->isChecked());
1481     titleConfig.writeEntry("font_underlined", buttonUnder->isChecked());
1482
1483     titleConfig.writeEntry("rect_foreground_color", rectFColor->color());
1484     titleConfig.writeEntry("rect_foreground_alpha", rectFAlpha->value());
1485     titleConfig.writeEntry("rect_background_color", rectBColor->color());
1486     titleConfig.writeEntry("rect_background_alpha", rectBAlpha->value());
1487     titleConfig.writeEntry("rect_line_width", rectLineWidth->value());
1488
1489     titleConfig.writeEntry("background_color", kcolorbutton->color());
1490     titleConfig.writeEntry("background_alpha", horizontalSlider->value());
1491
1492     titleConfig.writeEntry("crop_image", cropImage->isChecked());
1493
1494     //! \todo Not sure if I should sync - it is probably safe to do it
1495     config->sync();
1496
1497 }
1498
1499 /** \brief Read the last stored choices into the dialog */
1500 void TitleWidget::readChoices()
1501 {
1502     // Get a pointer to a shared configuration instance, then get the TitleWidget group.
1503     KSharedConfigPtr config = KGlobal::config();
1504     KConfigGroup titleConfig(config, "TitleWidget");
1505     // read the entries
1506     font_family->setCurrentFont(titleConfig.readEntry("font_family", font_family->currentFont()));
1507     font_size->setValue(titleConfig.readEntry("font_pixel_size", font_size->value()));
1508     fontColorButton->setColor(titleConfig.readEntry("font_color", fontColorButton->color()));
1509     textAlpha->setValue(titleConfig.readEntry("font_alpha", textAlpha->value()));
1510     int weight;
1511     if (titleConfig.readEntry("font_bold", false)) weight = QFont::Bold;
1512     else weight = titleConfig.readEntry("font_weight", font_weight_box->itemData(font_weight_box->currentIndex()).toInt());
1513     setFontBoxWeight(weight);
1514     buttonItalic->setChecked(titleConfig.readEntry("font_italic", buttonItalic->isChecked()));
1515     buttonUnder->setChecked(titleConfig.readEntry("font_underlined", buttonUnder->isChecked()));
1516
1517     rectFColor->setColor(titleConfig.readEntry("rect_foreground_color", rectFColor->color()));
1518     rectFAlpha->setValue(titleConfig.readEntry("rect_foreground_alpha", rectFAlpha->value()));
1519     rectBColor->setColor(titleConfig.readEntry("rect_background_color", rectBColor->color()));
1520     rectBAlpha->setValue(titleConfig.readEntry("rect_background_alpha", rectBAlpha->value()));
1521     rectLineWidth->setValue(titleConfig.readEntry("rect_line_width", rectLineWidth->value()));
1522
1523     kcolorbutton->setColor(titleConfig.readEntry("background_color", kcolorbutton->color()));
1524     horizontalSlider->setValue(titleConfig.readEntry("background_alpha", horizontalSlider->value()));
1525
1526     cropImage->setChecked(titleConfig.readEntry("crop_image", cropImage->isChecked()));
1527 }
1528
1529 void TitleWidget::adjustFrameSize()
1530 {
1531     m_frameWidth = m_titledocument.frameWidth();
1532     m_frameHeight = m_titledocument.frameHeight();
1533     m_frameBorder->setRect(0, 0, m_frameWidth, m_frameHeight);
1534     displayBackgroundFrame();
1535 }
1536
1537
1538
1539