]> git.sesse.net Git - kdenlive/commitdiff
double click a clip in timeline to edit position & duration, several clip move/resize...
authorJean-Baptiste Mardelle <jb@kdenlive.org>
Sat, 28 Jun 2008 20:35:16 +0000 (20:35 +0000)
committerJean-Baptiste Mardelle <jb@kdenlive.org>
Sat, 28 Jun 2008 20:35:16 +0000 (20:35 +0000)
svn path=/branches/KDE4/; revision=2289

src/CMakeLists.txt
src/clipdurationdialog.cpp [new file with mode: 0644]
src/clipdurationdialog.h [new file with mode: 0644]
src/clipitem.cpp
src/clipitem.h
src/customtrackview.cpp
src/widgets/clipdurationdialog_ui.ui [new file with mode: 0644]

index 70a13dcdae586d0025d5ebc2624545fc859bb57c..adf9d13879afba0814bddc3630a1f5f79728aa48 100644 (file)
@@ -50,6 +50,7 @@ kde4_add_ui_files(kdenlive_UI
   widgets/clipproperties_ui.ui
   widgets/markerdialog_ui.ui
   widgets/keyframedialog_ui.ui
+  widgets/clipdurationdialog_ui.ui
 )
  
 set(kdenlive_SRCS 
@@ -117,6 +118,7 @@ set(kdenlive_SRCS
   statusbarmessagelabel.cpp
   regiongrabber.cpp
   editkeyframecommand.cpp
+  clipdurationdialog.cpp
 )
 
 kde4_add_kcfg_files(kdenlive_SRCS GENERATE_MOC kdenlivesettings.kcfgc )
diff --git a/src/clipdurationdialog.cpp b/src/clipdurationdialog.cpp
new file mode 100644 (file)
index 0000000..5e05647
--- /dev/null
@@ -0,0 +1,115 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Jean-Baptiste Mardelle (jb@kdenlive.org)        *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
+ ***************************************************************************/
+
+
+#include <KDebug>
+
+#include "clipdurationdialog.h"
+#include "kdenlivesettings.h"
+
+ClipDurationDialog::ClipDurationDialog(AbstractClipItem *clip, Timecode tc, QWidget * parent): QDialog(parent), m_tc(tc), m_clip(clip) {
+    setFont(KGlobalSettings::toolBarFont());
+    m_fps = m_tc.fps();
+    m_view.setupUi(this);
+
+    if (clip->type() == TRANSITIONWIDGET) {
+        m_view.crop_up->hide();
+        m_view.crop_down->hide();
+        m_view.crop_position->hide();
+        m_view.crop_label->hide();
+    }
+
+    m_view.clip_position->setText(tc.getTimecode(m_clip->startPos(), m_fps));
+    m_view.crop_position->setText(tc.getTimecode(m_clip->cropStart(), m_fps));
+    m_view.clip_duration->setText(tc.getTimecode(m_clip->duration(), m_fps));
+    connect(m_view.position_up, SIGNAL(clicked()), this, SLOT(slotPosUp()));
+    connect(m_view.position_down, SIGNAL(clicked()), this, SLOT(slotPosDown()));
+    connect(m_view.crop_up, SIGNAL(clicked()), this, SLOT(slotCropUp()));
+    connect(m_view.crop_down, SIGNAL(clicked()), this, SLOT(slotCropDown()));
+    connect(m_view.duration_up, SIGNAL(clicked()), this, SLOT(slotDurUp()));
+    connect(m_view.duration_down, SIGNAL(clicked()), this, SLOT(slotDurDown()));
+
+    adjustSize();
+}
+
+ClipDurationDialog::~ClipDurationDialog() {
+}
+
+void ClipDurationDialog::slotPosUp() {
+    int position = m_tc.getFrameCount(m_view.clip_position->text(), m_fps);
+    //if (duration >= m_clip->duration().frames(m_fps)) return;
+    position ++;
+    m_view.clip_position->setText(m_tc.getTimecode(GenTime(position, m_fps), m_fps));
+}
+
+void ClipDurationDialog::slotPosDown() {
+    int position = m_tc.getFrameCount(m_view.clip_position->text(), m_fps);
+    //if (duration >= m_clip->duration().frames(m_fps)) return;
+    position --;
+    m_view.clip_position->setText(m_tc.getTimecode(GenTime(position, m_fps), m_fps));
+}
+
+void ClipDurationDialog::slotDurUp() {
+    int duration = m_tc.getFrameCount(m_view.clip_duration->text(), m_fps);
+    int crop = m_tc.getFrameCount(m_view.crop_position->text(), m_fps);
+    if (duration + crop > m_clip->maxDuration().frames(m_fps)) return;
+    duration ++;
+    m_view.clip_duration->setText(m_tc.getTimecode(GenTime(duration, m_fps), m_fps));
+}
+
+void ClipDurationDialog::slotDurDown() {
+    int duration = m_tc.getFrameCount(m_view.clip_duration->text(), m_fps);
+    if (duration <= 0) return;
+    duration --;
+    m_view.clip_duration->setText(m_tc.getTimecode(GenTime(duration, m_fps), m_fps));
+}
+
+void ClipDurationDialog::slotCropUp() {
+    int crop = m_tc.getFrameCount(m_view.crop_position->text(), m_fps);
+    int duration = m_tc.getFrameCount(m_view.clip_duration->text(), m_fps);
+    if (duration + crop > m_clip->maxDuration().frames(m_fps)) return;
+    crop ++;
+    m_view.crop_position->setText(m_tc.getTimecode(GenTime(crop, m_fps), m_fps));
+}
+
+void ClipDurationDialog::slotCropDown() {
+    int crop = m_tc.getFrameCount(m_view.crop_position->text(), m_fps);
+    if (crop <= 0) return;
+    crop --;
+    m_view.crop_position->setText(m_tc.getTimecode(GenTime(crop, m_fps), m_fps));
+}
+
+GenTime ClipDurationDialog::startPos() const {
+    int pos = m_tc.getFrameCount(m_view.clip_position->text(), m_fps);
+    return GenTime(pos, m_fps);
+}
+
+GenTime ClipDurationDialog::cropStart() const {
+    int pos = m_tc.getFrameCount(m_view.crop_position->text(), m_fps);
+    return GenTime(pos, m_fps);
+}
+
+GenTime ClipDurationDialog::duration() const {
+    int pos = m_tc.getFrameCount(m_view.clip_duration->text(), m_fps);
+    return GenTime(pos, m_fps);
+}
+
+#include "clipdurationdialog.moc"
+
+
diff --git a/src/clipdurationdialog.h b/src/clipdurationdialog.h
new file mode 100644 (file)
index 0000000..368e1f7
--- /dev/null
@@ -0,0 +1,59 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Jean-Baptiste Mardelle (jb@kdenlive.org)        *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
+ ***************************************************************************/
+
+
+#ifndef CLIPDURATIONDIALOG_H
+#define CLIPDURATIONDIALOG_H
+
+#include <QDialog>
+
+#include "abstractclipitem.h"
+#include "timecode.h"
+#include "ui_clipdurationdialog_ui.h"
+
+
+class ClipDurationDialog : public QDialog {
+    Q_OBJECT
+
+public:
+    ClipDurationDialog(AbstractClipItem *clip, Timecode tc, QWidget * parent = 0);
+    ~ClipDurationDialog();
+    GenTime startPos() const;
+    GenTime cropStart() const;
+    GenTime duration() const;
+
+private slots:
+    void slotPosUp();
+    void slotPosDown();
+    void slotDurUp();
+    void slotDurDown();
+    void slotCropUp();
+    void slotCropDown();
+
+private:
+    Ui::ClipDurationDialog_UI m_view;
+    AbstractClipItem *m_clip;
+    Timecode m_tc;
+    double m_fps;
+
+};
+
+
+#endif
+
index c502264b91bf8b06149df53640576d337bf1712e..2cadbe95f5e8ee85af0a7fef218384c2c6abd95d 100644 (file)
@@ -63,7 +63,7 @@ ClipItem::ClipItem(DocClipBase *clip, ItemInfo info, GenTime cropStart, double s
 
     setFlags(QGraphicsItem::ItemClipsToShape | QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
     setAcceptsHoverEvents(true);
-    connect(this , SIGNAL(prepareAudioThumb(double, QPainterPath, int, int)) , this, SLOT(slotPrepareAudioThumb(double, QPainterPath, int, int)));
+    connect(this , SIGNAL(prepareAudioThumb(double, QPainterPath, int, int, int)) , this, SLOT(slotPrepareAudioThumb(double, QPainterPath, int, int, int)));
 
     setBrush(QColor(141, 166, 215));
     if (m_clipType == VIDEO || m_clipType == AV || m_clipType == SLIDESHOW) {
@@ -373,15 +373,15 @@ void ClipItem::paint(QPainter *painter,
     }
 
     // draw audio thumbnails
-    if (KdenliveSettings::audiothumbnails() && ((m_clipType == AV && option->exposedRect.bottom() > br.height() / 2) || m_clipType == AUDIO) && audioThumbReady) {
+    if (KdenliveSettings::audiothumbnails() && ((m_clipType == AV && option->exposedRect.bottom() > (br.y() + br.height() / 2)) || m_clipType == AUDIO) && audioThumbReady) {
 
         QPainterPath path = m_clipType == AV ? roundRectPathLower : resultClipPath;
         if (m_clipType == AV) painter->fillPath(path, QBrush(QColor(200, 200, 200, 140)));
 
-        int channels = 2;
+        int channels = baseClip()->getProperty("channels").toInt();
         if (scale != framePixelWidth)
             audioThumbCachePic.clear();
-        emit prepareAudioThumb(scale, path, startpixel, endpixel + 200);//200 more for less missing parts before repaint after scrolling
+        emit prepareAudioThumb(scale, path, startpixel, endpixel + 200, channels);//200 more for less missing parts before repaint after scrolling
         int cropLeft = (int)((m_cropStart).frames(m_fps) * scale);
         for (int startCache = startpixel - startpixel % 100; startCache < endpixel + 300;startCache += 100) {
             if (audioThumbCachePic.contains(startCache) && !audioThumbCachePic[startCache].isNull())
@@ -591,11 +591,10 @@ QList <GenTime> ClipItem::snapMarkers() const {
     return snaps;
 }
 
-void ClipItem::slotPrepareAudioThumb(double pixelForOneFrame, QPainterPath path, int startpixel, int endpixel) {
-    int channels = 2;
+void ClipItem::slotPrepareAudioThumb(double pixelForOneFrame, QPainterPath path, int startpixel, int endpixel, int channels) {
 
     QRectF re = path.boundingRect();
-
+    //kDebug() << "// PREP AUDIO THMB FRMO : " << startpixel << ", to: " << endpixel;
     //if ( (!audioThumbWasDrawn || framePixelWidth!=pixelForOneFrame ) && !baseClip()->audioFrameChache.isEmpty()){
 
     for (int startCache = startpixel - startpixel % 100;startCache + 100 < endpixel ;startCache += 100) {
index 190c669b1749116df26e55c1bd21059605f7401a..892ab8dee321d0262259cd71fffc4523b876bef2 100644 (file)
@@ -140,13 +140,12 @@ private slots:
     void slotGetStartThumb();
     void slotGetEndThumb();
     void slotGotAudioData();
-    void slotPrepareAudioThumb(double, QPainterPath, int, int);
+    void slotPrepareAudioThumb(double pixelForOneFrame, QPainterPath path, int startpixel, int endpixel, int channels);
     void animate(qreal value);
 
 signals:
     void getThumb(int, int);
-    void prepareAudioThumb(double, QPainterPath, int, int);
-
+    void prepareAudioThumb(double, QPainterPath, int, int, int);
 };
 
 #endif
index 574c1cda89405d5db752b82d8296bab109acd454..da04d2fe4eb17b1497eae9c2a0b8cf8b794efbd8 100644 (file)
@@ -57,6 +57,7 @@
 #include "markerdialog.h"
 #include "mainwindow.h"
 #include "ui_keyframedialog_ui.h"
+#include "clipdurationdialog.h"
 
 
 //TODO:
@@ -589,6 +590,42 @@ void CustomTrackView::mouseDoubleClickEvent(QMouseEvent *event) {
             m_commandStack->push(command);
             updateEffect(m_tracksList.count() - item->track(), item->startPos(), item->selectedEffect());
         }
+    } else {
+        ClipDurationDialog d(m_dragItem, m_document->timecode(), this);
+        if (d.exec() == QDialog::Accepted) {
+            if (d.startPos() != m_dragItem->startPos()) {
+                if (m_dragItem->type() == AVWIDGET) {
+                    ItemInfo startInfo;
+                    startInfo.startPos = m_dragItem->startPos();
+                    startInfo.endPos = m_dragItem->endPos();
+                    startInfo.track = m_dragItem->track();
+                    ItemInfo endInfo;
+                    endInfo.startPos = d.startPos();
+                    endInfo.endPos = m_dragItem->endPos() + (endInfo.startPos - startInfo.startPos);
+                    endInfo.track = m_dragItem->track();
+                    MoveClipCommand *command = new MoveClipCommand(this, startInfo, endInfo, true);
+                    m_commandStack->push(command);
+                } else {
+                    //TODO: move transition
+                }
+            }
+            if (d.duration() != m_dragItem->duration()) {
+                if (m_dragItem->type() == AVWIDGET) {
+                    ItemInfo startInfo;
+                    startInfo.startPos = m_dragItem->startPos();
+                    startInfo.endPos = m_dragItem->endPos();
+                    startInfo.track = m_dragItem->track();
+                    ItemInfo endInfo;
+                    endInfo.startPos = startInfo.startPos;
+                    endInfo.endPos = endInfo.startPos + d.duration();
+                    endInfo.track = m_dragItem->track();
+                    ResizeClipCommand *command = new ResizeClipCommand(this, startInfo, endInfo, true);
+                    m_commandStack->push(command);
+                } else {
+                    //TODO: resize transition
+                }
+            }
+        }
     }
 }
 
@@ -1011,7 +1048,7 @@ void CustomTrackView::mouseReleaseEvent(QMouseEvent * event) {
                 // undo last move and emit error message
                 MoveClipCommand *command = new MoveClipCommand(this, info, m_dragItemInfo, true);
                 m_commandStack->push(command);
-                emit displayMessage(i18n("Cannot move clip to requested position"), ErrorMessage);
+                emit displayMessage(i18n("Cannot move clip to position %1seconds", QString::number(m_dragItemInfo.startPos.seconds(), 'g', 2)), ErrorMessage);
             }
         }
         if (m_dragItem->type() == TRANSITIONWIDGET && (m_dragItemInfo.startPos != info.startPos || m_dragItemInfo.track != info.track)) {
@@ -1233,7 +1270,7 @@ Transition *CustomTrackView::getTransitionItemAt(GenTime pos, int track) {
 void CustomTrackView::moveClip(const ItemInfo start, const ItemInfo end) {
     ClipItem *item = getClipItemAt((int) start.startPos.frames(m_document->fps()) + 1, start.track);
     if (!item) {
-        emit displayMessage(i18n("Cannot move clip at time: %1s on track %2", start.startPos.seconds(), start.track), ErrorMessage);
+        emit displayMessage(i18n("Cannot move clip at time: %1s on track %2", QString::number(start.startPos.seconds(), 'g', 2), start.track), ErrorMessage);
         kDebug() << "----------------  ERROR, CANNOT find clip to move at.. ";// << startPos.x() * m_scale * FRAME_SIZE + 1 << ", " << startPos.y() * m_tracksHeight + m_tracksHeight / 2;
         return;
     }
@@ -1244,7 +1281,7 @@ void CustomTrackView::moveClip(const ItemInfo start, const ItemInfo end) {
         item->moveTo((int) end.startPos.frames(m_document->fps()), m_scale, (int)((end.track - start.track) * m_tracksHeight), end.track);
     } else {
         // undo last move and emit error message
-        emit displayMessage(i18n("Cannot move clip to requested position"), ErrorMessage);
+        emit displayMessage(i18n("Cannot move clip to position %1seconds", QString::number(end.startPos.seconds(), 'g', 2)), ErrorMessage);
     }
 }
 
@@ -1274,11 +1311,11 @@ void CustomTrackView::moveTransition(const ItemInfo start, const ItemInfo end) {
 }
 
 void CustomTrackView::resizeClip(const ItemInfo start, const ItemInfo end) {
-    int offset;
+    int offset = 0;
     bool resizeClipStart = true;
     if (start.startPos == end.startPos) resizeClipStart = false;
-    if (resizeClipStart) offset = 1;
-    else offset = -1;
+    /*if (resizeClipStart) offset = 1;
+    else offset = -1;*/
     ClipItem *item = getClipItemAt((int)(start.startPos.frames(m_document->fps()) + offset), start.track);
     if (!item) {
         emit displayMessage(i18n("Cannot move clip at time: %1s on track %2", start.startPos.seconds(), start.track), ErrorMessage);
@@ -1290,8 +1327,8 @@ void CustomTrackView::resizeClip(const ItemInfo start, const ItemInfo end) {
         item->resizeStart((int) end.startPos.frames(m_document->fps()), m_scale);
         updateClipFade(item);
     } else {
-        m_document->renderer()->mltResizeClipEnd(m_tracksList.count() - item->track(), item->startPos(), item->cropStart(), item->cropStart() + end.startPos - item->startPos());
-        item->resizeEnd((int) end.startPos.frames(m_document->fps()), m_scale);
+        m_document->renderer()->mltResizeClipEnd(m_tracksList.count() - item->track(), item->startPos(), item->cropStart(), item->cropStart() + end.endPos - item->startPos());
+        item->resizeEnd((int) end.endPos.frames(m_document->fps()), m_scale);
         updateClipFade(item, true);
     }
     m_document->renderer()->doRefresh();
diff --git a/src/widgets/clipdurationdialog_ui.ui b/src/widgets/clipdurationdialog_ui.ui
new file mode 100644 (file)
index 0000000..577e832
--- /dev/null
@@ -0,0 +1,184 @@
+<ui version="4.0" >
+ <class>ClipDurationDialog_UI</class>
+ <widget class="QDialog" name="ClipDurationDialog_UI" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>226</width>
+    <height>149</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>Duration</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout" >
+   <item row="0" column="0" >
+    <widget class="QLabel" name="position_label" >
+     <property name="text" >
+      <string>Position</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="1" >
+    <layout class="QHBoxLayout" name="horizontalLayout" >
+     <item>
+      <widget class="KRestrictedLine" name="clip_position" >
+       <property name="inputMask" >
+        <string>99:99:99:99; </string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <layout class="QVBoxLayout" name="verticalLayout" >
+       <item>
+        <widget class="KArrowButton" name="position_up" />
+       </item>
+       <item>
+        <widget class="KArrowButton" name="position_down" >
+         <property name="arrowType" stdset="0" >
+          <number>2</number>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+    </layout>
+   </item>
+   <item row="1" column="0" >
+    <widget class="QLabel" name="crop_label" >
+     <property name="text" >
+      <string>Crop start</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="1" >
+    <layout class="QHBoxLayout" name="horizontalLayout_2" >
+     <item>
+      <widget class="KRestrictedLine" name="crop_position" >
+       <property name="inputMask" >
+        <string>99:99:99:99; </string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <layout class="QVBoxLayout" name="verticalLayout_2" >
+       <item>
+        <widget class="KArrowButton" name="crop_up" />
+       </item>
+       <item>
+        <widget class="KArrowButton" name="crop_down" >
+         <property name="arrowType" stdset="0" >
+          <number>2</number>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+    </layout>
+   </item>
+   <item row="2" column="0" >
+    <widget class="QLabel" name="duration_label" >
+     <property name="text" >
+      <string>Duration</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="1" >
+    <layout class="QHBoxLayout" name="horizontalLayout_3" >
+     <item>
+      <widget class="KRestrictedLine" name="clip_duration" >
+       <property name="inputMask" >
+        <string>99:99:99:99; </string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <layout class="QVBoxLayout" name="verticalLayout_3" >
+       <item>
+        <widget class="KArrowButton" name="duration_up" />
+       </item>
+       <item>
+        <widget class="KArrowButton" name="duration_down" >
+         <property name="arrowType" stdset="0" >
+          <number>2</number>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+    </layout>
+   </item>
+   <item row="3" column="0" colspan="2" >
+    <spacer name="verticalSpacer" >
+     <property name="orientation" >
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0" >
+      <size>
+       <width>218</width>
+       <height>2</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item row="4" column="0" colspan="2" >
+    <widget class="QDialogButtonBox" name="buttonBox" >
+     <property name="orientation" >
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons" >
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>KArrowButton</class>
+   <extends>QPushButton</extends>
+   <header>karrowbutton.h</header>
+  </customwidget>
+  <customwidget>
+   <class>KRestrictedLine</class>
+   <extends>KLineEdit</extends>
+   <header>krestrictedline.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>ClipDurationDialog_UI</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>ClipDurationDialog_UI</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>