comparison base/Selection.cpp @ 0:fc9323a41f5a

start base : Sonic Visualiser sv1-1.0rc1
author lbajardsilogic
date Fri, 11 May 2007 09:08:14 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:fc9323a41f5a
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 Sonic Visualiser
5 An audio file viewer and annotation editor.
6 Centre for Digital Music, Queen Mary, University of London.
7 This file copyright 2006 Chris Cannam.
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version. See the file
13 COPYING included with this distribution for more information.
14 */
15
16 #include "Selection.h"
17
18 Selection::Selection() :
19 m_startFrame(0),
20 m_endFrame(0)
21 {
22 }
23
24 Selection::Selection(size_t startFrame, size_t endFrame) :
25 m_startFrame(startFrame),
26 m_endFrame(endFrame)
27 {
28 if (m_startFrame > m_endFrame) {
29 size_t tmp = m_endFrame;
30 m_endFrame = m_startFrame;
31 m_startFrame = tmp;
32 }
33 }
34
35 Selection::Selection(const Selection &s) :
36 m_startFrame(s.m_startFrame),
37 m_endFrame(s.m_endFrame)
38 {
39 }
40
41 Selection &
42 Selection::operator=(const Selection &s)
43 {
44 if (this != &s) {
45 m_startFrame = s.m_startFrame;
46 m_endFrame = s.m_endFrame;
47 }
48 return *this;
49 }
50
51 Selection::~Selection()
52 {
53 }
54
55 bool
56 Selection::isEmpty() const
57 {
58 return m_startFrame == m_endFrame;
59 }
60
61 size_t
62 Selection::getStartFrame() const
63 {
64 return m_startFrame;
65 }
66
67 size_t
68 Selection::getEndFrame() const
69 {
70 return m_endFrame;
71 }
72
73 bool
74 Selection::contains(size_t frame) const
75 {
76 return (frame >= m_startFrame) && (frame < m_endFrame);
77 }
78
79 bool
80 Selection::operator<(const Selection &s) const
81 {
82 if (isEmpty()) {
83 if (s.isEmpty()) return false;
84 else return true;
85 } else {
86 if (s.isEmpty()) return false;
87 else return (m_startFrame < s.m_startFrame);
88 }
89 }
90
91 bool
92 Selection::operator==(const Selection &s) const
93 {
94 if (isEmpty()) return s.isEmpty();
95
96 return (m_startFrame == s.m_startFrame &&
97 m_endFrame == s.m_endFrame);
98 }
99
100
101 MultiSelection::MultiSelection()
102 {
103 }
104
105 MultiSelection::~MultiSelection()
106 {
107 }
108
109 const MultiSelection::SelectionList &
110 MultiSelection::getSelections() const
111 {
112 return m_selections;
113 }
114
115 void
116 MultiSelection::setSelection(const Selection &selection)
117 {
118 clearSelections();
119 addSelection(selection);
120 }
121
122 void
123 MultiSelection::addSelection(const Selection &selection)
124 {
125 m_selections.insert(selection);
126
127 // Cope with a sitation where the new selection overlaps one or
128 // more existing ones. This is a terribly inefficient way to do
129 // this, but that probably isn't significant in real life.
130
131 // It's essential for the correct operation of
132 // getContainingSelection that the selections do not overlap, so
133 // this is not just a frill.
134
135 for (SelectionList::iterator i = m_selections.begin();
136 i != m_selections.end(); ) {
137
138 SelectionList::iterator j = i;
139 if (++j == m_selections.end()) break;
140
141 if (i->getEndFrame() >= j->getStartFrame()) {
142 Selection merged(i->getStartFrame(),
143 std::max(i->getEndFrame(), j->getEndFrame()));
144 m_selections.erase(i);
145 m_selections.erase(j);
146 m_selections.insert(merged);
147 i = m_selections.begin();
148 } else {
149 ++i;
150 }
151 }
152 }
153
154 void
155 MultiSelection::removeSelection(const Selection &selection)
156 {
157 //!!! Likewise this needs to cope correctly with the situation
158 //where selection is not one of the original selection set but
159 //simply overlaps one of them (cutting down the original selection
160 //appropriately)
161
162 if (m_selections.find(selection) != m_selections.end()) {
163 m_selections.erase(selection);
164 }
165 }
166
167 void
168 MultiSelection::clearSelections()
169 {
170 if (!m_selections.empty()) {
171 m_selections.clear();
172 }
173 }
174
175 Selection
176 MultiSelection::getContainingSelection(size_t frame, bool defaultToFollowing) const
177 {
178 // This scales very badly with the number of selections, but it's
179 // more efficient for very small numbers of selections than a more
180 // scalable method, and I think that may be what we need
181
182 for (SelectionList::const_iterator i = m_selections.begin();
183 i != m_selections.end(); ++i) {
184
185 if (i->contains(frame)) return *i;
186
187 if (i->getStartFrame() > frame) {
188 if (defaultToFollowing) return *i;
189 else return Selection();
190 }
191 }
192
193 return Selection();
194 }
195
196 QString
197 MultiSelection::toXmlString(QString indent,
198 QString extraAttributes) const
199 {
200 QString s;
201 s += indent + QString("<selections %1>\n").arg(extraAttributes);
202 for (SelectionList::const_iterator i = m_selections.begin();
203 i != m_selections.end(); ++i) {
204 s += indent + QString(" <selection start=\"%1\" end=\"%2\"/>\n")
205 .arg(i->getStartFrame()).arg(i->getEndFrame());
206 }
207 s += indent + "</selections>\n";
208 return s;
209 }
210