Mercurial > hg > svcore
comparison data/model/SparseModel.h @ 1429:48e9f538e6e9
Untabify
author | Chris Cannam |
---|---|
date | Thu, 01 Mar 2018 18:02:22 +0000 |
parents | cbdd534f517a |
children | b40f67578976 |
comparison
equal
deleted
inserted
replaced
1428:87ae75da6527 | 1429:48e9f538e6e9 |
---|---|
43 class SparseModel : public Model, | 43 class SparseModel : public Model, |
44 public TabularModel | 44 public TabularModel |
45 { | 45 { |
46 public: | 46 public: |
47 SparseModel(sv_samplerate_t sampleRate, int resolution, | 47 SparseModel(sv_samplerate_t sampleRate, int resolution, |
48 bool notifyOnAdd = true); | 48 bool notifyOnAdd = true); |
49 virtual ~SparseModel() { } | 49 virtual ~SparseModel() { } |
50 | 50 |
51 virtual bool isOK() const { return true; } | 51 virtual bool isOK() const { return true; } |
52 virtual sv_frame_t getStartFrame() const; | 52 virtual sv_frame_t getStartFrame() const; |
53 virtual sv_frame_t getEndFrame() const; | 53 virtual sv_frame_t getEndFrame() const; |
69 // end of the final point. | 69 // end of the final point. |
70 virtual void extendEndFrame(sv_frame_t to) { m_extendTo = to; } | 70 virtual void extendEndFrame(sv_frame_t to) { m_extendTo = to; } |
71 | 71 |
72 typedef PointType Point; | 72 typedef PointType Point; |
73 typedef std::multiset<PointType, | 73 typedef std::multiset<PointType, |
74 typename PointType::OrderComparator> PointList; | 74 typename PointType::OrderComparator> PointList; |
75 typedef typename PointList::iterator PointListIterator; | 75 typedef typename PointList::iterator PointListIterator; |
76 typedef typename PointList::const_iterator PointListConstIterator; | 76 typedef typename PointList::const_iterator PointListConstIterator; |
77 | 77 |
78 /** | 78 /** |
79 * Return whether the model is empty or not. | 79 * Return whether the model is empty or not. |
194 * Command to add a point, with undo. | 194 * Command to add a point, with undo. |
195 */ | 195 */ |
196 class AddPointCommand : public Command | 196 class AddPointCommand : public Command |
197 { | 197 { |
198 public: | 198 public: |
199 AddPointCommand(SparseModel<PointType> *model, | 199 AddPointCommand(SparseModel<PointType> *model, |
200 const PointType &point, | 200 const PointType &point, |
201 QString name = "") : | 201 QString name = "") : |
202 m_model(model), m_point(point), m_name(name) { } | 202 m_model(model), m_point(point), m_name(name) { } |
203 | 203 |
204 virtual QString getName() const { | 204 virtual QString getName() const { |
205 return (m_name == "" ? tr("Add Point") : m_name); | 205 return (m_name == "" ? tr("Add Point") : m_name); |
206 } | 206 } |
207 | 207 |
208 virtual void execute() { m_model->addPoint(m_point); } | 208 virtual void execute() { m_model->addPoint(m_point); } |
209 virtual void unexecute() { m_model->deletePoint(m_point); } | 209 virtual void unexecute() { m_model->deletePoint(m_point); } |
210 | 210 |
211 const PointType &getPoint() const { return m_point; } | 211 const PointType &getPoint() const { return m_point; } |
212 | 212 |
213 private: | 213 private: |
214 SparseModel<PointType> *m_model; | 214 SparseModel<PointType> *m_model; |
215 PointType m_point; | 215 PointType m_point; |
216 QString m_name; | 216 QString m_name; |
217 }; | 217 }; |
218 | 218 |
219 | 219 |
220 /** | 220 /** |
221 * Command to remove a point, with undo. | 221 * Command to remove a point, with undo. |
222 */ | 222 */ |
223 class DeletePointCommand : public Command | 223 class DeletePointCommand : public Command |
224 { | 224 { |
225 public: | 225 public: |
226 DeletePointCommand(SparseModel<PointType> *model, | 226 DeletePointCommand(SparseModel<PointType> *model, |
227 const PointType &point) : | 227 const PointType &point) : |
228 m_model(model), m_point(point) { } | 228 m_model(model), m_point(point) { } |
229 | 229 |
230 virtual QString getName() const { return tr("Delete Point"); } | 230 virtual QString getName() const { return tr("Delete Point"); } |
231 | 231 |
232 virtual void execute() { m_model->deletePoint(m_point); } | 232 virtual void execute() { m_model->deletePoint(m_point); } |
233 virtual void unexecute() { m_model->addPoint(m_point); } | 233 virtual void unexecute() { m_model->addPoint(m_point); } |
234 | 234 |
235 const PointType &getPoint() const { return m_point; } | 235 const PointType &getPoint() const { return m_point; } |
236 | 236 |
237 private: | 237 private: |
238 SparseModel<PointType> *m_model; | 238 SparseModel<PointType> *m_model; |
239 PointType m_point; | 239 PointType m_point; |
240 }; | 240 }; |
241 | 241 |
242 | 242 |
243 /** | 243 /** |
244 * Command to add or remove a series of points, with undo. | 244 * Command to add or remove a series of points, with undo. |
245 * Consecutive add/remove pairs for the same point are collapsed. | 245 * Consecutive add/remove pairs for the same point are collapsed. |
246 */ | 246 */ |
247 class EditCommand : public MacroCommand | 247 class EditCommand : public MacroCommand |
248 { | 248 { |
249 public: | 249 public: |
250 EditCommand(SparseModel<PointType> *model, QString commandName); | 250 EditCommand(SparseModel<PointType> *model, QString commandName); |
251 | 251 |
252 virtual void addPoint(const PointType &point); | 252 virtual void addPoint(const PointType &point); |
253 virtual void deletePoint(const PointType &point); | 253 virtual void deletePoint(const PointType &point); |
254 | 254 |
255 /** | 255 /** |
256 * Stack an arbitrary other command in the same sequence. | 256 * Stack an arbitrary other command in the same sequence. |
257 */ | 257 */ |
258 virtual void addCommand(Command *command) { addCommand(command, true); } | 258 virtual void addCommand(Command *command) { addCommand(command, true); } |
259 | 259 |
260 /** | 260 /** |
261 * If any points have been added or deleted, return this | 261 * If any points have been added or deleted, return this |
262 * command (so the caller can add it to the command history). | 262 * command (so the caller can add it to the command history). |
263 * Otherwise delete the command and return NULL. | 263 * Otherwise delete the command and return NULL. |
264 */ | 264 */ |
265 virtual EditCommand *finish(); | 265 virtual EditCommand *finish(); |
266 | 266 |
267 protected: | 267 protected: |
268 virtual void addCommand(Command *command, bool executeFirst); | 268 virtual void addCommand(Command *command, bool executeFirst); |
269 | 269 |
270 SparseModel<PointType> *m_model; | 270 SparseModel<PointType> *m_model; |
271 }; | 271 }; |
272 | 272 |
273 | 273 |
274 /** | 274 /** |
275 * Command to relabel a point. | 275 * Command to relabel a point. |
276 */ | 276 */ |
277 class RelabelCommand : public Command | 277 class RelabelCommand : public Command |
278 { | 278 { |
279 public: | 279 public: |
280 RelabelCommand(SparseModel<PointType> *model, | 280 RelabelCommand(SparseModel<PointType> *model, |
281 const PointType &point, | 281 const PointType &point, |
282 QString newLabel) : | 282 QString newLabel) : |
283 m_model(model), m_oldPoint(point), m_newPoint(point) { | 283 m_model(model), m_oldPoint(point), m_newPoint(point) { |
284 m_newPoint.label = newLabel; | 284 m_newPoint.label = newLabel; |
285 } | 285 } |
286 | 286 |
287 virtual QString getName() const { return tr("Re-Label Point"); } | 287 virtual QString getName() const { return tr("Re-Label Point"); } |
288 | 288 |
289 virtual void execute() { | 289 virtual void execute() { |
290 m_model->deletePoint(m_oldPoint); | 290 m_model->deletePoint(m_oldPoint); |
291 m_model->addPoint(m_newPoint); | 291 m_model->addPoint(m_newPoint); |
292 std::swap(m_oldPoint, m_newPoint); | 292 std::swap(m_oldPoint, m_newPoint); |
293 } | 293 } |
294 | 294 |
295 virtual void unexecute() { execute(); } | 295 virtual void unexecute() { execute(); } |
296 | 296 |
297 private: | 297 private: |
298 SparseModel<PointType> *m_model; | 298 SparseModel<PointType> *m_model; |
299 PointType m_oldPoint; | 299 PointType m_oldPoint; |
300 PointType m_newPoint; | 300 PointType m_newPoint; |
301 }; | 301 }; |
302 | 302 |
303 /** | 303 /** |
304 * TabularModel methods. | 304 * TabularModel methods. |
305 */ | 305 */ |
556 SparseModel<PointType>::getStartFrame() const | 556 SparseModel<PointType>::getStartFrame() const |
557 { | 557 { |
558 QMutexLocker locker(&m_mutex); | 558 QMutexLocker locker(&m_mutex); |
559 sv_frame_t f = 0; | 559 sv_frame_t f = 0; |
560 if (!m_points.empty()) { | 560 if (!m_points.empty()) { |
561 f = m_points.begin()->frame; | 561 f = m_points.begin()->frame; |
562 } | 562 } |
563 return f; | 563 return f; |
564 } | 564 } |
565 | 565 |
566 template <typename PointType> | 566 template <typename PointType> |
568 SparseModel<PointType>::getEndFrame() const | 568 SparseModel<PointType>::getEndFrame() const |
569 { | 569 { |
570 QMutexLocker locker(&m_mutex); | 570 QMutexLocker locker(&m_mutex); |
571 sv_frame_t f = 0; | 571 sv_frame_t f = 0; |
572 if (!m_points.empty()) { | 572 if (!m_points.empty()) { |
573 PointListConstIterator i(m_points.end()); | 573 PointListConstIterator i(m_points.end()); |
574 f = (--i)->frame; | 574 f = (--i)->frame; |
575 } | 575 } |
576 if (m_extendTo > f) return m_extendTo; | 576 if (m_extendTo > f) return m_extendTo; |
577 else return f; | 577 else return f; |
578 } | 578 } |
579 | 579 |
616 if (endItr != m_points.end()) ++endItr; | 616 if (endItr != m_points.end()) ++endItr; |
617 | 617 |
618 PointList rv; | 618 PointList rv; |
619 | 619 |
620 for (PointListConstIterator i = startItr; i != endItr; ++i) { | 620 for (PointListConstIterator i = startItr; i != endItr; ++i) { |
621 rv.insert(*i); | 621 rv.insert(*i); |
622 } | 622 } |
623 | 623 |
624 return rv; | 624 return rv; |
625 } | 625 } |
626 | 626 |
632 getPointIterators(frame, startItr, endItr); | 632 getPointIterators(frame, startItr, endItr); |
633 | 633 |
634 PointList rv; | 634 PointList rv; |
635 | 635 |
636 for (PointListConstIterator i = startItr; i != endItr; ++i) { | 636 for (PointListConstIterator i = startItr; i != endItr; ++i) { |
637 rv.insert(*i); | 637 rv.insert(*i); |
638 } | 638 } |
639 | 639 |
640 return rv; | 640 return rv; |
641 } | 641 } |
642 | 642 |
702 if (i == m_points.begin()) return rv; | 702 if (i == m_points.begin()) return rv; |
703 | 703 |
704 --i; | 704 --i; |
705 sv_frame_t frame = i->frame; | 705 sv_frame_t frame = i->frame; |
706 while (i->frame == frame) { | 706 while (i->frame == frame) { |
707 rv.insert(*i); | 707 rv.insert(*i); |
708 if (i == m_points.begin()) break; | 708 if (i == m_points.begin()) break; |
709 --i; | 709 --i; |
710 } | 710 } |
711 | 711 |
712 return rv; | 712 return rv; |
713 } | 713 } |
714 | 714 |
724 PointListConstIterator i = m_points.upper_bound(lookupPoint); | 724 PointListConstIterator i = m_points.upper_bound(lookupPoint); |
725 if (i == m_points.end()) return rv; | 725 if (i == m_points.end()) return rv; |
726 | 726 |
727 sv_frame_t frame = i->frame; | 727 sv_frame_t frame = i->frame; |
728 while (i != m_points.end() && i->frame == frame) { | 728 while (i != m_points.end() && i->frame == frame) { |
729 rv.insert(*i); | 729 rv.insert(*i); |
730 ++i; | 730 ++i; |
731 } | 731 } |
732 | 732 |
733 return rv; | 733 return rv; |
734 } | 734 } |
735 | 735 |
736 template <typename PointType> | 736 template <typename PointType> |
737 void | 737 void |
738 SparseModel<PointType>::setResolution(int resolution) | 738 SparseModel<PointType>::setResolution(int resolution) |
739 { | 739 { |
740 { | 740 { |
741 QMutexLocker locker(&m_mutex); | 741 QMutexLocker locker(&m_mutex); |
742 m_resolution = resolution; | 742 m_resolution = resolution; |
743 m_rows.clear(); | 743 m_rows.clear(); |
744 } | 744 } |
745 emit modelChanged(); | 745 emit modelChanged(); |
746 } | 746 } |
747 | 747 |
748 template <typename PointType> | 748 template <typename PointType> |
749 void | 749 void |
750 SparseModel<PointType>::clear() | 750 SparseModel<PointType>::clear() |
751 { | 751 { |
752 { | 752 { |
753 QMutexLocker locker(&m_mutex); | 753 QMutexLocker locker(&m_mutex); |
754 m_points.clear(); | 754 m_points.clear(); |
755 m_pointCount = 0; | 755 m_pointCount = 0; |
756 m_rows.clear(); | 756 m_rows.clear(); |
757 } | 757 } |
758 emit modelChanged(); | 758 emit modelChanged(); |
759 } | 759 } |
774 // notifyOnAdd as an option rather than a necessity (the | 774 // notifyOnAdd as an option rather than a necessity (the |
775 // alternative is to notify on setCompletion). | 775 // alternative is to notify on setCompletion). |
776 | 776 |
777 if (m_notifyOnAdd) { | 777 if (m_notifyOnAdd) { |
778 m_rows.clear(); //!!! inefficient | 778 m_rows.clear(); //!!! inefficient |
779 emit modelChangedWithin(point.frame, point.frame + m_resolution); | 779 emit modelChangedWithin(point.frame, point.frame + m_resolution); |
780 } else { | 780 } else { |
781 if (m_sinceLastNotifyMin == -1 || | 781 if (m_sinceLastNotifyMin == -1 || |
782 point.frame < m_sinceLastNotifyMin) { | 782 point.frame < m_sinceLastNotifyMin) { |
783 m_sinceLastNotifyMin = point.frame; | 783 m_sinceLastNotifyMin = point.frame; |
784 } | 784 } |
785 if (m_sinceLastNotifyMax == -1 || | 785 if (m_sinceLastNotifyMax == -1 || |
786 point.frame > m_sinceLastNotifyMax) { | 786 point.frame > m_sinceLastNotifyMax) { |
787 m_sinceLastNotifyMax = point.frame; | 787 m_sinceLastNotifyMax = point.frame; |
788 } | 788 } |
789 } | 789 } |
790 } | 790 } |
791 | 791 |
792 template <typename PointType> | 792 template <typename PointType> |
793 bool | 793 bool |
820 if (i->frame > point.frame) break; | 820 if (i->frame > point.frame) break; |
821 if (!comparator(*i, point) && !comparator(point, *i)) { | 821 if (!comparator(*i, point) && !comparator(point, *i)) { |
822 m_points.erase(i); | 822 m_points.erase(i); |
823 m_pointCount--; | 823 m_pointCount--; |
824 break; | 824 break; |
825 } | 825 } |
826 ++i; | 826 ++i; |
827 } | 827 } |
828 | 828 |
829 // std::cout << "SparseOneDimensionalModel: emit modelChanged(" | 829 // std::cout << "SparseOneDimensionalModel: emit modelChanged(" |
830 // << point.frame << ")" << std::endl; | 830 // << point.frame << ")" << std::endl; |
831 m_rows.clear(); //!!! inefficient | 831 m_rows.clear(); //!!! inefficient |
832 emit modelChangedWithin(point.frame, point.frame + m_resolution); | 832 emit modelChangedWithin(point.frame, point.frame + m_resolution); |
833 } | 833 } |
834 | 834 |
835 template <typename PointType> | 835 template <typename PointType> |
839 // std::cerr << "SparseModel::setCompletion(" << completion << ")" << std::endl; | 839 // std::cerr << "SparseModel::setCompletion(" << completion << ")" << std::endl; |
840 | 840 |
841 QMutexLocker locker(&m_mutex); | 841 QMutexLocker locker(&m_mutex); |
842 | 842 |
843 if (m_completion != completion) { | 843 if (m_completion != completion) { |
844 m_completion = completion; | 844 m_completion = completion; |
845 | 845 |
846 if (completion == 100) { | 846 if (completion == 100) { |
847 | 847 |
848 if (!m_notifyOnAdd) { | 848 if (!m_notifyOnAdd) { |
849 emit completionChanged(); | 849 emit completionChanged(); |
850 } | 850 } |
851 | 851 |
852 m_notifyOnAdd = true; // henceforth | 852 m_notifyOnAdd = true; // henceforth |
853 m_rows.clear(); //!!! inefficient | 853 m_rows.clear(); //!!! inefficient |
854 emit modelChanged(); | 854 emit modelChanged(); |
855 | 855 |
856 } else if (!m_notifyOnAdd) { | 856 } else if (!m_notifyOnAdd) { |
857 | 857 |
858 if (update && | 858 if (update && |
859 m_sinceLastNotifyMin >= 0 && | 859 m_sinceLastNotifyMin >= 0 && |
860 m_sinceLastNotifyMax >= 0) { | 860 m_sinceLastNotifyMax >= 0) { |
861 m_rows.clear(); //!!! inefficient | 861 m_rows.clear(); //!!! inefficient |
862 emit modelChangedWithin(m_sinceLastNotifyMin, m_sinceLastNotifyMax); | 862 emit modelChangedWithin(m_sinceLastNotifyMin, m_sinceLastNotifyMax); |
863 m_sinceLastNotifyMin = m_sinceLastNotifyMax = -1; | 863 m_sinceLastNotifyMin = m_sinceLastNotifyMax = -1; |
864 } else { | 864 } else { |
865 emit completionChanged(); | 865 emit completionChanged(); |
866 } | 866 } |
867 } else { | 867 } else { |
868 emit completionChanged(); | 868 emit completionChanged(); |
869 } | 869 } |
870 } | 870 } |
871 } | 871 } |
872 | 872 |
873 template <typename PointType> | 873 template <typename PointType> |
874 void | 874 void |
880 // << extraAttributes.toStdString() << std::endl; | 880 // << extraAttributes.toStdString() << std::endl; |
881 | 881 |
882 QString type = getXmlOutputType(); | 882 QString type = getXmlOutputType(); |
883 | 883 |
884 Model::toXml | 884 Model::toXml |
885 (out, | 885 (out, |
886 indent, | 886 indent, |
887 QString("type=\"%1\" dimensions=\"%2\" resolution=\"%3\" notifyOnAdd=\"%4\" dataset=\"%5\" %6") | 887 QString("type=\"%1\" dimensions=\"%2\" resolution=\"%3\" notifyOnAdd=\"%4\" dataset=\"%5\" %6") |
888 .arg(type) | 888 .arg(type) |
889 .arg(PointType(0).getDimensions()) | 889 .arg(PointType(0).getDimensions()) |
890 .arg(m_resolution) | 890 .arg(m_resolution) |
891 .arg(m_notifyOnAdd ? "true" : "false") | 891 .arg(m_notifyOnAdd ? "true" : "false") |
892 .arg(getObjectExportId(&m_points)) | 892 .arg(getObjectExportId(&m_points)) |
893 .arg(extraAttributes)); | 893 .arg(extraAttributes)); |
894 | 894 |
895 out << indent; | 895 out << indent; |
896 out << QString("<dataset id=\"%1\" dimensions=\"%2\">\n") | 896 out << QString("<dataset id=\"%1\" dimensions=\"%2\">\n") |
897 .arg(getObjectExportId(&m_points)) | 897 .arg(getObjectExportId(&m_points)) |
898 .arg(PointType(0).getDimensions()); | 898 .arg(PointType(0).getDimensions()); |
899 | 899 |
900 for (PointListConstIterator i = m_points.begin(); i != m_points.end(); ++i) { | 900 for (PointListConstIterator i = m_points.begin(); i != m_points.end(); ++i) { |
901 i->toXml(out, indent + " "); | 901 i->toXml(out, indent + " "); |
902 } | 902 } |
903 | 903 |
940 } | 940 } |
941 | 941 |
942 template <typename PointType> | 942 template <typename PointType> |
943 void | 943 void |
944 SparseModel<PointType>::EditCommand::addCommand(Command *command, | 944 SparseModel<PointType>::EditCommand::addCommand(Command *command, |
945 bool executeFirst) | 945 bool executeFirst) |
946 { | 946 { |
947 if (executeFirst) command->execute(); | 947 if (executeFirst) command->execute(); |
948 | 948 |
949 if (!m_commands.empty()) { | 949 if (!m_commands.empty()) { |
950 DeletePointCommand *dpc = dynamic_cast<DeletePointCommand *>(command); | 950 DeletePointCommand *dpc = dynamic_cast<DeletePointCommand *>(command); |
951 if (dpc) { | 951 if (dpc) { |
952 AddPointCommand *apc = dynamic_cast<AddPointCommand *> | 952 AddPointCommand *apc = dynamic_cast<AddPointCommand *> |
953 (m_commands[m_commands.size() - 1]); | 953 (m_commands[m_commands.size() - 1]); |
954 typename PointType::Comparator comparator; | 954 typename PointType::Comparator comparator; |
955 if (apc) { | 955 if (apc) { |
956 if (!comparator(apc->getPoint(), dpc->getPoint()) && | 956 if (!comparator(apc->getPoint(), dpc->getPoint()) && |
957 !comparator(dpc->getPoint(), apc->getPoint())) { | 957 !comparator(dpc->getPoint(), apc->getPoint())) { |
958 deleteCommand(apc); | 958 deleteCommand(apc); |
959 return; | 959 return; |
960 } | 960 } |
961 } | 961 } |
962 } | 962 } |
963 } | 963 } |
964 | 964 |
965 MacroCommand::addCommand(command); | 965 MacroCommand::addCommand(command); |
966 } | 966 } |
967 | 967 |