annotate base/Selection.cpp @ 282:d9319859a4cf tip

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