~ubuntu-branches/ubuntu/saucy/merkaartor/saucy

« back to all changes in this revision

Viewing changes to src/Interaction/MoveTrackPointInteraction.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Bernd Zeimetz
  • Date: 2009-09-13 00:52:12 UTC
  • mto: (1.2.7 upstream) (0.1.3 upstream) (3.1.7 sid)
  • mto: This revision was merged to the branch mainline in revision 10.
  • Revision ID: james.westby@ubuntu.com-20090913005212-pjecal8zxm07x0fj
ImportĀ upstreamĀ versionĀ 0.14+svnfixes~20090912

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "Interaction/MoveTrackPointInteraction.h"
 
2
 
 
3
#include "MapView.h"
 
4
#include "Command/DocumentCommands.h"
 
5
#include "Command/RoadCommands.h"
 
6
#include "Command/TrackPointCommands.h"
 
7
#include "Maps/Coord.h"
 
8
#include "Maps/MapDocument.h"
 
9
#include "Maps/Projection.h"
 
10
#include "Maps/TrackPoint.h"
 
11
#include "Utils/LineF.h"
 
12
#include "Utils/MDiscardableDialog.h"
 
13
 
 
14
#include <QtGui/QCursor>
 
15
#include <QtGui/QMouseEvent>
 
16
#include <QtGui/QPixmap>
 
17
#include <QMessageBox>
 
18
 
 
19
#include <QList>
 
20
 
 
21
MoveTrackPointInteraction::MoveTrackPointInteraction(MapView* aView)
 
22
: FeatureSnapInteraction(aView), StartDragPosition(0,0)
 
23
{
 
24
}
 
25
 
 
26
MoveTrackPointInteraction::~MoveTrackPointInteraction(void)
 
27
{
 
28
}
 
29
 
 
30
QString MoveTrackPointInteraction::toHtml()
 
31
{
 
32
        QString help;
 
33
        help = (MainWindow::tr("LEFT-CLICK to select;LEFT-DRAG to move"));
 
34
 
 
35
        QStringList helpList = help.split(";");
 
36
 
 
37
        QString desc;
 
38
        desc = QString("<big><b>%1</b></big>").arg(MainWindow::tr("Move node Interaction"));
 
39
 
 
40
        QString S =
 
41
        "<html><head/><body>"
 
42
        "<small><i>" + QString(metaObject()->className()) + "</i></small><br/>"
 
43
        + desc;
 
44
        S += "<hr/>";
 
45
        S += "<ul style=\"margin-left: 0px; padding-left: 0px;\">";
 
46
        for (int i=0; i<helpList.size(); ++i) {
 
47
                S+= "<li>" + helpList[i] + "</li>";
 
48
        }
 
49
        S += "</ul>";
 
50
        S += "</body></html>";
 
51
 
 
52
        return S;
 
53
}
 
54
 
 
55
#ifndef Q_OS_SYMBIAN
 
56
QCursor MoveTrackPointInteraction::cursor() const
 
57
{
 
58
        QPixmap pm(":/Icons/move.xpm");
 
59
        return QCursor(pm);
 
60
}
 
61
#endif
 
62
 
 
63
 
 
64
void MoveTrackPointInteraction::snapMousePressEvent(QMouseEvent * event, MapFeature* aLast)
 
65
{
 
66
        QList<MapFeature*> sel;
 
67
        if (view()->isSelectionLocked()) {
 
68
                if (view()->properties()->selection(0))
 
69
                        sel.append(view()->properties()->selection(0));
 
70
                else
 
71
                        sel.append(aLast);
 
72
        } else {
 
73
                if (aLast)
 
74
                        sel.append(aLast);
 
75
        }
 
76
        clearNoSnap();
 
77
        Moving.clear();
 
78
        OriginalPosition.clear();
 
79
        StartDragPosition = XY_TO_COORD(event->pos());
 
80
        for (int j=0; j<sel.size(); j++) {
 
81
                if (TrackPoint* Pt = dynamic_cast<TrackPoint*>(sel[j]))
 
82
                {
 
83
                        Moving.push_back(Pt);
 
84
                        if (sel.size() == 1)
 
85
                                StartDragPosition = Pt->position();
 
86
                }
 
87
                else if (Road* R = dynamic_cast<Road*>(sel[j])) {
 
88
                        for (int i=0; i<R->size(); ++i)
 
89
                                if (std::find(Moving.begin(),Moving.end(),R->get(i)) == Moving.end())
 
90
                                        Moving.push_back(R->getNode(i));
 
91
                        addToNoSnap(R);
 
92
                }
 
93
        }
 
94
        for (int i=0; i<Moving.size(); ++i)
 
95
        {
 
96
                OriginalPosition.push_back(Moving[i]->position());
 
97
                addToNoSnap(Moving[i]);
 
98
        }
 
99
}
 
100
 
 
101
void MoveTrackPointInteraction::snapMouseReleaseEvent(QMouseEvent * event, MapFeature* Closer)
 
102
{
 
103
        if (Moving.size() && !panning())
 
104
        {
 
105
                CommandList* theList;
 
106
                if (Moving.size() > 1)
 
107
                        theList = new CommandList(MainWindow::tr("Move Nodes").arg(Moving[0]->id()), Moving[0]);
 
108
                else
 
109
                        theList = new CommandList(MainWindow::tr("Move Node %1").arg(Moving[0]->id()), Moving[0]);
 
110
                Coord Diff(calculateNewPosition(event,Closer, theList)-StartDragPosition);
 
111
                for (int i=0; i<Moving.size(); ++i)
 
112
                {
 
113
                        Moving[i]->setPosition(OriginalPosition[i]);
 
114
                        if (Moving[i]->layer()->isTrack())
 
115
                                theList->add(new MoveTrackPointCommand(Moving[i],OriginalPosition[i]+Diff, Moving[i]->layer()));
 
116
                        else
 
117
                                theList->add(new MoveTrackPointCommand(Moving[i],OriginalPosition[i]+Diff, document()->getDirtyOrOriginLayer(Moving[i]->layer())));
 
118
                }
 
119
                
 
120
                // If moving a single node (not a track node), see if it got dropped onto another node
 
121
                if (Moving.size() == 1 && !Moving[0]->layer()->isTrack())
 
122
                {
 
123
                        Coord newPos = OriginalPosition[0] + Diff;
 
124
                        QList<TrackPoint*> samePosPts;
 
125
                        for (VisibleFeatureIterator it(document()); !it.isEnd(); ++it)
 
126
                        {
 
127
                                TrackPoint* visPt = CAST_NODE(it.get());
 
128
                                if (visPt && visPt->layer()->classType() != MapLayer::TrackMapLayerType)
 
129
                                {
 
130
                                        if (visPt == Moving[0])
 
131
                                                continue;
 
132
 
 
133
                                        if (visPt->position() == newPos)
 
134
                                        {
 
135
                                                samePosPts.push_back(visPt);
 
136
                                        }
 
137
                                }
 
138
                        }
 
139
                        // Ensure the node being moved is at the end of the list.
 
140
                        // (This is not the node that all nodes will be merged into,
 
141
                        // they are always merged into a node that already was at that position.)
 
142
                        samePosPts.push_back(Moving[0]);
 
143
 
 
144
                        if (samePosPts.size() > 1)   // Ignore the node we're moving, see if there are more
 
145
                        {
 
146
                                MDiscardableMessage dlg(view(),
 
147
                                        MainWindow::tr("Nodes at the same position found."),
 
148
                                        MainWindow::tr("Do you want to merge all nodes at the drop position?"));
 
149
                                if (dlg.check() == QDialog::Accepted)
 
150
                                {
 
151
                                        // Merge all nodes from the same position
 
152
 
 
153
                                        // from MainWindow::on_nodeMergeAction_triggered()
 
154
                                        // Merge all nodes into the first node that has been found (not the node being moved)
 
155
                                        MapFeature* F = samePosPts[0];
 
156
                                        // Change the command description to reflect the merge
 
157
                                        theList->setDescription(MainWindow::tr("Merge Nodes into %1").arg(F->id()));
 
158
                                        theList->setFeature(F);
 
159
                                        
 
160
                                        // from mergeNodes(theDocument, theList, theProperties);
 
161
                                        QList<MapFeature*> alt;
 
162
                                        TrackPoint* merged = samePosPts[0];
 
163
                                        alt.push_back(merged);
 
164
                                        for (int i = 1; i < samePosPts.size(); ++i) {
 
165
                                                MapFeature::mergeTags(document(), theList, merged, samePosPts[i]);
 
166
                                                theList->add(new RemoveFeatureCommand(document(), samePosPts[i], alt));
 
167
                                        }
 
168
                                        
 
169
                                        view()->properties()->setSelection(F);
 
170
                                }
 
171
                        }
 
172
                }
 
173
                
 
174
                document()->addHistory(theList);
 
175
                view()->invalidate(true, false);
 
176
        }
 
177
        Moving.clear();
 
178
        OriginalPosition.clear();
 
179
        clearNoSnap();
 
180
}
 
181
 
 
182
void MoveTrackPointInteraction::snapMouseMoveEvent(QMouseEvent* event, MapFeature* Closer)
 
183
{
 
184
        if (Moving.size() && !panning())
 
185
        {
 
186
                Coord Diff = calculateNewPosition(event,Closer,NULL)-StartDragPosition;
 
187
                for (int i=0; i<Moving.size(); ++i)
 
188
                        Moving[i]->setPosition(OriginalPosition[i]+Diff);
 
189
                view()->invalidate(true, false);
 
190
        }
 
191
}
 
192
 
 
193
Coord MoveTrackPointInteraction::calculateNewPosition(QMouseEvent *event, MapFeature *aLast, CommandList* theList)
 
194
{
 
195
        Coord TargetC = XY_TO_COORD(event->pos());
 
196
        if (TrackPoint* Pt = dynamic_cast<TrackPoint*>(aLast))
 
197
                return Pt->position();
 
198
        else if (Road* R = dynamic_cast<Road*>(aLast))
 
199
        {
 
200
                QPoint Target(TargetC.lat(),TargetC.lon());
 
201
                LineF L1(R->getNode(0)->position(),R->getNode(1)->position());
 
202
                double Dist = L1.capDistance(TargetC);
 
203
                QPoint BestTarget = L1.project(Target).toPoint();
 
204
                int BestIdx = 1;
 
205
                for (int i=2; i<R->size(); ++i)
 
206
                {
 
207
                        LineF L2(R->getNode(i-1)->position(),R->getNode(i)->position());
 
208
                        double Dist2 = L2.capDistance(TargetC);
 
209
                        if (Dist2 < Dist)
 
210
                        {
 
211
                                Dist = Dist2;
 
212
                                BestTarget = L2.project(Target).toPoint();
 
213
                                BestIdx = i;
 
214
                        }
 
215
                }
 
216
                if (theList && (Moving.size() == 1))
 
217
                        theList->add(new
 
218
                                RoadAddTrackPointCommand(R,Moving[0],BestIdx,document()->getDirtyOrOriginLayer(R->layer())));
 
219
                return Coord(BestTarget.x(),BestTarget.y());
 
220
        }
 
221
        return TargetC;
 
222
}