svgui  1.9
TimeInstantLayer.cpp
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     This file copyright 2006 Chris Cannam.
00008     
00009     This program is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU General Public License as
00011     published by the Free Software Foundation; either version 2 of the
00012     License, or (at your option) any later version.  See the file
00013     COPYING included with this distribution for more information.
00014 */
00015 
00016 #include "TimeInstantLayer.h"
00017 
00018 #include "data/model/Model.h"
00019 #include "base/RealTime.h"
00020 #include "view/View.h"
00021 #include "base/Profiler.h"
00022 #include "base/Clipboard.h"
00023 #include "ColourDatabase.h"
00024 
00025 #include "data/model/SparseOneDimensionalModel.h"
00026 
00027 #include "widgets/ItemEditDialog.h"
00028 #include "widgets/ListInputDialog.h"
00029 
00030 #include <QPainter>
00031 #include <QMouseEvent>
00032 #include <QTextStream>
00033 #include <QMessageBox>
00034 
00035 #include <iostream>
00036 #include <cmath>
00037 
00038 //#define DEBUG_TIME_INSTANT_LAYER 1
00039 
00040 TimeInstantLayer::TimeInstantLayer() :
00041     SingleColourLayer(),
00042     m_model(0),
00043     m_editing(false),
00044     m_editingPoint(0, tr("New Point")),
00045     m_editingCommand(0),
00046     m_plotStyle(PlotInstants)
00047 {
00048 }
00049 
00050 TimeInstantLayer::~TimeInstantLayer()
00051 {
00052 }
00053 
00054 void
00055 TimeInstantLayer::setModel(SparseOneDimensionalModel *model)
00056 {
00057     if (m_model == model) return;
00058     m_model = model;
00059 
00060     connectSignals(m_model);
00061 
00062 #ifdef DEBUG_TIME_INSTANT_LAYER
00063     cerr << "TimeInstantLayer::setModel(" << model << ")" << endl;
00064 #endif
00065 
00066     if (m_model && m_model->getRDFTypeURI().endsWith("Segment")) {
00067         setPlotStyle(PlotSegmentation);
00068     }
00069 
00070     emit modelReplaced();
00071 }
00072 
00073 Layer::PropertyList
00074 TimeInstantLayer::getProperties() const
00075 {
00076     PropertyList list = SingleColourLayer::getProperties();
00077     list.push_back("Plot Type");
00078     return list;
00079 }
00080 
00081 QString
00082 TimeInstantLayer::getPropertyLabel(const PropertyName &name) const
00083 {
00084     if (name == "Plot Type") return tr("Plot Type");
00085     return SingleColourLayer::getPropertyLabel(name);
00086 }
00087 
00088 Layer::PropertyType
00089 TimeInstantLayer::getPropertyType(const PropertyName &name) const
00090 {
00091     if (name == "Plot Type") return ValueProperty;
00092     return SingleColourLayer::getPropertyType(name);
00093 }
00094 
00095 int
00096 TimeInstantLayer::getPropertyRangeAndValue(const PropertyName &name,
00097                                            int *min, int *max, int *deflt) const
00098 {
00099     int val = 0;
00100 
00101     if (name == "Plot Type") {
00102         
00103         if (min) *min = 0;
00104         if (max) *max = 1;
00105         if (deflt) *deflt = 0;
00106         
00107         val = int(m_plotStyle);
00108 
00109     } else {
00110         
00111         val = SingleColourLayer::getPropertyRangeAndValue(name, min, max, deflt);
00112     }
00113 
00114     return val;
00115 }
00116 
00117 QString
00118 TimeInstantLayer::getPropertyValueLabel(const PropertyName &name,
00119                                         int value) const
00120 {
00121     if (name == "Plot Type") {
00122         switch (value) {
00123         default:
00124         case 0: return tr("Instants");
00125         case 1: return tr("Segmentation");
00126         }
00127     }
00128     return SingleColourLayer::getPropertyValueLabel(name, value);
00129 }
00130 
00131 void
00132 TimeInstantLayer::setProperty(const PropertyName &name, int value)
00133 {
00134     if (name == "Plot Type") {
00135         setPlotStyle(PlotStyle(value));
00136     } else {
00137         SingleColourLayer::setProperty(name, value);
00138     }
00139 }
00140 
00141 void
00142 TimeInstantLayer::setPlotStyle(PlotStyle style)
00143 {
00144     if (m_plotStyle == style) return;
00145     m_plotStyle = style;
00146     emit layerParametersChanged();
00147 }
00148 
00149 bool
00150 TimeInstantLayer::isLayerScrollable(const View *v) const
00151 {
00152     QPoint discard;
00153     return !v->shouldIlluminateLocalFeatures(this, discard);
00154 }
00155 
00156 SparseOneDimensionalModel::PointList
00157 TimeInstantLayer::getLocalPoints(View *v, int x) const
00158 {
00159     // Return a set of points that all have the same frame number, the
00160     // nearest to the given x coordinate, and that are within a
00161     // certain fuzz distance of that x coordinate.
00162 
00163     if (!m_model) return SparseOneDimensionalModel::PointList();
00164 
00165     long frame = v->getFrameForX(x);
00166 
00167     SparseOneDimensionalModel::PointList onPoints =
00168         m_model->getPoints(frame);
00169 
00170     if (!onPoints.empty()) {
00171         return onPoints;
00172     }
00173 
00174     SparseOneDimensionalModel::PointList prevPoints =
00175         m_model->getPreviousPoints(frame);
00176     SparseOneDimensionalModel::PointList nextPoints =
00177         m_model->getNextPoints(frame);
00178 
00179     SparseOneDimensionalModel::PointList usePoints = prevPoints;
00180 
00181     if (prevPoints.empty()) {
00182         usePoints = nextPoints;
00183     } else if (long(prevPoints.begin()->frame) < v->getStartFrame() &&
00184                !(nextPoints.begin()->frame > v->getEndFrame())) {
00185         usePoints = nextPoints;
00186     } else if (nextPoints.begin()->frame - frame <
00187                frame - prevPoints.begin()->frame) {
00188         usePoints = nextPoints;
00189     }
00190 
00191     if (!usePoints.empty()) {
00192         int fuzz = 2;
00193         int px = v->getXForFrame(usePoints.begin()->frame);
00194         if ((px > x && px - x > fuzz) ||
00195             (px < x && x - px > fuzz + 1)) {
00196             usePoints.clear();
00197         }
00198     }
00199 
00200     return usePoints;
00201 }
00202 
00203 QString
00204 TimeInstantLayer::getLabelPreceding(int frame) const
00205 {
00206     if (!m_model) return "";
00207     SparseOneDimensionalModel::PointList points = m_model->getPreviousPoints(frame);
00208     for (SparseOneDimensionalModel::PointList::const_iterator i = points.begin();
00209          i != points.end(); ++i) {
00210         if (i->label != "") return i->label;
00211     }
00212     return "";
00213 }
00214 
00215 QString
00216 TimeInstantLayer::getFeatureDescription(View *v, QPoint &pos) const
00217 {
00218     int x = pos.x();
00219 
00220     if (!m_model || !m_model->getSampleRate()) return "";
00221 
00222     SparseOneDimensionalModel::PointList points = getLocalPoints(v, x);
00223 
00224     if (points.empty()) {
00225         if (!m_model->isReady()) {
00226             return tr("In progress");
00227         } else {
00228             return tr("No local points");
00229         }
00230     }
00231 
00232     long useFrame = points.begin()->frame;
00233 
00234     RealTime rt = RealTime::frame2RealTime(useFrame, m_model->getSampleRate());
00235     
00236     QString text;
00237 
00238     if (points.begin()->label == "") {
00239         text = QString(tr("Time:\t%1\nNo label"))
00240             .arg(rt.toText(true).c_str());
00241     } else {
00242         text = QString(tr("Time:\t%1\nLabel:\t%2"))
00243             .arg(rt.toText(true).c_str())
00244             .arg(points.begin()->label);
00245     }
00246 
00247     pos = QPoint(v->getXForFrame(useFrame), pos.y());
00248     return text;
00249 }
00250 
00251 bool
00252 TimeInstantLayer::snapToFeatureFrame(View *v, int &frame,
00253                                      int &resolution,
00254                                      SnapType snap) const
00255 {
00256     if (!m_model) {
00257         return Layer::snapToFeatureFrame(v, frame, resolution, snap);
00258     }
00259 
00260     resolution = m_model->getResolution();
00261     SparseOneDimensionalModel::PointList points;
00262 
00263     if (snap == SnapNeighbouring) {
00264         
00265         points = getLocalPoints(v, v->getXForFrame(frame));
00266         if (points.empty()) return false;
00267         frame = points.begin()->frame;
00268         return true;
00269     }    
00270 
00271     points = m_model->getPoints(frame, frame);
00272     int snapped = frame;
00273     bool found = false;
00274 
00275     for (SparseOneDimensionalModel::PointList::const_iterator i = points.begin();
00276          i != points.end(); ++i) {
00277 
00278         if (snap == SnapRight) {
00279 
00280             if (i->frame >= frame) {
00281                 snapped = i->frame;
00282                 found = true;
00283                 break;
00284             }
00285 
00286         } else if (snap == SnapLeft) {
00287 
00288             if (i->frame <= frame) {
00289                 snapped = i->frame;
00290                 found = true; // don't break, as the next may be better
00291             } else {
00292                 break;
00293             }
00294 
00295         } else { // nearest
00296 
00297             SparseOneDimensionalModel::PointList::const_iterator j = i;
00298             ++j;
00299 
00300             if (j == points.end()) {
00301 
00302                 snapped = i->frame;
00303                 found = true;
00304                 break;
00305 
00306             } else if (j->frame >= frame) {
00307 
00308                 if (j->frame - frame < frame - i->frame) {
00309                     snapped = j->frame;
00310                 } else {
00311                     snapped = i->frame;
00312                 }
00313                 found = true;
00314                 break;
00315             }
00316         }
00317     }
00318 
00319     frame = snapped;
00320     return found;
00321 }
00322 
00323 void
00324 TimeInstantLayer::paint(View *v, QPainter &paint, QRect rect) const
00325 {
00326     if (!m_model || !m_model->isOK()) return;
00327 
00328 //    Profiler profiler("TimeInstantLayer::paint", true);
00329 
00330     int x0 = rect.left(), x1 = rect.right();
00331 
00332     long frame0 = v->getFrameForX(x0);
00333     long frame1 = v->getFrameForX(x1);
00334 
00335     SparseOneDimensionalModel::PointList points(m_model->getPoints
00336                                                 (frame0, frame1));
00337 
00338     bool odd = false;
00339     if (m_plotStyle == PlotSegmentation && !points.empty()) {
00340         int index = m_model->getIndexOf(*points.begin());
00341         odd = ((index % 2) == 1);
00342     }
00343 
00344     paint.setPen(getBaseQColor());
00345 
00346     QColor brushColour(getBaseQColor());
00347     brushColour.setAlpha(100);
00348     paint.setBrush(brushColour);
00349 
00350     QColor oddBrushColour(brushColour);
00351     if (m_plotStyle == PlotSegmentation) {
00352         if (getBaseQColor() == Qt::black) {
00353             oddBrushColour = Qt::gray;
00354         } else if (getBaseQColor() == Qt::darkRed) {
00355             oddBrushColour = Qt::red;
00356         } else if (getBaseQColor() == Qt::darkBlue) {
00357             oddBrushColour = Qt::blue;
00358         } else if (getBaseQColor() == Qt::darkGreen) {
00359             oddBrushColour = Qt::green;
00360         } else {
00361             oddBrushColour = oddBrushColour.light(150);
00362         }
00363         oddBrushColour.setAlpha(100);
00364     }
00365 
00366 //    SVDEBUG << "TimeInstantLayer::paint: resolution is "
00367 //            << m_model->getResolution() << " frames" << endl;
00368 
00369     QPoint localPos;
00370     long illuminateFrame = -1;
00371 
00372     if (v->shouldIlluminateLocalFeatures(this, localPos)) {
00373         SparseOneDimensionalModel::PointList localPoints =
00374             getLocalPoints(v, localPos.x());
00375         if (!localPoints.empty()) illuminateFrame = localPoints.begin()->frame;
00376     }
00377         
00378     int prevX = -1;
00379     int textY = v->getTextLabelHeight(this, paint);
00380     
00381     for (SparseOneDimensionalModel::PointList::const_iterator i = points.begin();
00382          i != points.end(); ++i) {
00383 
00384         const SparseOneDimensionalModel::Point &p(*i);
00385         SparseOneDimensionalModel::PointList::const_iterator j = i;
00386         ++j;
00387 
00388         int x = v->getXForFrame(p.frame);
00389         if (x == prevX && m_plotStyle == PlotInstants &&
00390             p.frame != illuminateFrame) continue;
00391 
00392         int iw = v->getXForFrame(p.frame + m_model->getResolution()) - x;
00393         if (iw < 2) {
00394             if (iw < 1) {
00395                 iw = 2;
00396                 if (j != points.end()) {
00397                     int nx = v->getXForFrame(j->frame);
00398                     if (nx < x + 3) iw = 1;
00399                 }
00400             } else {
00401                 iw = 2;
00402             }
00403         }
00404                 
00405         if (p.frame == illuminateFrame) {
00406             paint.setPen(getForegroundQColor(v));
00407         } else {
00408             paint.setPen(brushColour);
00409         }
00410 
00411         if (m_plotStyle == PlotInstants) {
00412             if (iw > 1) {
00413                 paint.drawRect(x, 0, iw - 1, v->height() - 1);
00414             } else {
00415                 paint.drawLine(x, 0, x, v->height() - 1);
00416             }
00417         } else {
00418 
00419             if (odd) paint.setBrush(oddBrushColour);
00420             else paint.setBrush(brushColour);
00421             
00422             int nx;
00423             
00424             if (j != points.end()) {
00425                 const SparseOneDimensionalModel::Point &q(*j);
00426                 nx = v->getXForFrame(q.frame);
00427             } else {
00428                 nx = v->getXForFrame(m_model->getEndFrame());
00429             }
00430 
00431             if (nx >= x) {
00432                 
00433                 if (illuminateFrame != p.frame &&
00434                     (nx < x + 5 || x >= v->width() - 1)) {
00435                     paint.setPen(Qt::NoPen);
00436                 }
00437 
00438                 paint.drawRect(x, -1, nx - x, v->height() + 1);
00439             }
00440 
00441             odd = !odd;
00442         }
00443 
00444         paint.setPen(getBaseQColor());
00445         
00446         if (p.label != "") {
00447 
00448             // only draw if there's enough room from here to the next point
00449 
00450             int lw = paint.fontMetrics().width(p.label);
00451             bool good = true;
00452 
00453             if (j != points.end()) {
00454                 int nx = v->getXForFrame(j->frame);
00455                 if (nx >= x && nx - x - iw - 3 <= lw) good = false;
00456             }
00457 
00458             if (good) {
00459                 v->drawVisibleText(paint, x + iw + 2, textY, p.label, View::OutlinedText);
00460 //              paint.drawText(x + iw + 2, textY, p.label);
00461             }
00462         }
00463 
00464         prevX = x;
00465     }
00466 }
00467 
00468 void
00469 TimeInstantLayer::drawStart(View *v, QMouseEvent *e)
00470 {
00471 #ifdef DEBUG_TIME_INSTANT_LAYER
00472     cerr << "TimeInstantLayer::drawStart(" << e->x() << ")" << endl;
00473 #endif
00474 
00475     if (!m_model) return;
00476 
00477     long frame = v->getFrameForX(e->x());
00478     if (frame < 0) frame = 0;
00479     frame = frame / m_model->getResolution() * m_model->getResolution();
00480 
00481     m_editingPoint = SparseOneDimensionalModel::Point(frame, tr("New Point"));
00482 
00483     if (m_editingCommand) finish(m_editingCommand);
00484     m_editingCommand = new SparseOneDimensionalModel::EditCommand(m_model,
00485                                                                   tr("Draw Point"));
00486     m_editingCommand->addPoint(m_editingPoint);
00487 
00488     m_editing = true;
00489 }
00490 
00491 void
00492 TimeInstantLayer::drawDrag(View *v, QMouseEvent *e)
00493 {
00494 #ifdef DEBUG_TIME_INSTANT_LAYER
00495     cerr << "TimeInstantLayer::drawDrag(" << e->x() << ")" << endl;
00496 #endif
00497 
00498     if (!m_model || !m_editing) return;
00499 
00500     long frame = v->getFrameForX(e->x());
00501     if (frame < 0) frame = 0;
00502     frame = frame / m_model->getResolution() * m_model->getResolution();
00503     m_editingCommand->deletePoint(m_editingPoint);
00504     m_editingPoint.frame = frame;
00505     m_editingCommand->addPoint(m_editingPoint);
00506 }
00507 
00508 void
00509 TimeInstantLayer::drawEnd(View *, QMouseEvent *)
00510 {
00511 #ifdef DEBUG_TIME_INSTANT_LAYER
00512     cerr << "TimeInstantLayer::drawEnd(" << e->x() << ")" << endl;
00513 #endif
00514     if (!m_model || !m_editing) return;
00515     QString newName = tr("Add Point at %1 s")
00516         .arg(RealTime::frame2RealTime(m_editingPoint.frame,
00517                                       m_model->getSampleRate())
00518              .toText(false).c_str());
00519     m_editingCommand->setName(newName);
00520     finish(m_editingCommand);
00521     m_editingCommand = 0;
00522     m_editing = false;
00523 }
00524 
00525 void
00526 TimeInstantLayer::eraseStart(View *v, QMouseEvent *e)
00527 {
00528     if (!m_model) return;
00529 
00530     SparseOneDimensionalModel::PointList points = getLocalPoints(v, e->x());
00531     if (points.empty()) return;
00532 
00533     m_editingPoint = *points.begin();
00534 
00535     if (m_editingCommand) {
00536         finish(m_editingCommand);
00537         m_editingCommand = 0;
00538     }
00539 
00540     m_editing = true;
00541 }
00542 
00543 void
00544 TimeInstantLayer::eraseDrag(View *, QMouseEvent *)
00545 {
00546 }
00547 
00548 void
00549 TimeInstantLayer::eraseEnd(View *v, QMouseEvent *e)
00550 {
00551     if (!m_model || !m_editing) return;
00552 
00553     m_editing = false;
00554 
00555     SparseOneDimensionalModel::PointList points = getLocalPoints(v, e->x());
00556     if (points.empty()) return;
00557     if (points.begin()->frame != m_editingPoint.frame) return;
00558 
00559     m_editingCommand = new SparseOneDimensionalModel::EditCommand
00560         (m_model, tr("Erase Point"));
00561 
00562     m_editingCommand->deletePoint(m_editingPoint);
00563 
00564     finish(m_editingCommand);
00565     m_editingCommand = 0;
00566     m_editing = false;
00567 }
00568 
00569 void
00570 TimeInstantLayer::editStart(View *v, QMouseEvent *e)
00571 {
00572 #ifdef DEBUG_TIME_INSTANT_LAYER
00573     cerr << "TimeInstantLayer::editStart(" << e->x() << ")" << endl;
00574 #endif
00575 
00576     if (!m_model) return;
00577 
00578     SparseOneDimensionalModel::PointList points = getLocalPoints(v, e->x());
00579     if (points.empty()) return;
00580 
00581     m_editingPoint = *points.begin();
00582 
00583     if (m_editingCommand) {
00584         finish(m_editingCommand);
00585         m_editingCommand = 0;
00586     }
00587 
00588     m_editing = true;
00589 }
00590 
00591 void
00592 TimeInstantLayer::editDrag(View *v, QMouseEvent *e)
00593 {
00594 #ifdef DEBUG_TIME_INSTANT_LAYER
00595     cerr << "TimeInstantLayer::editDrag(" << e->x() << ")" << endl;
00596 #endif
00597 
00598     if (!m_model || !m_editing) return;
00599 
00600     long frame = v->getFrameForX(e->x());
00601     if (frame < 0) frame = 0;
00602     frame = frame / m_model->getResolution() * m_model->getResolution();
00603 
00604     if (!m_editingCommand) {
00605         m_editingCommand = new SparseOneDimensionalModel::EditCommand(m_model,
00606                                                                       tr("Drag Point"));
00607     }
00608 
00609     m_editingCommand->deletePoint(m_editingPoint);
00610     m_editingPoint.frame = frame;
00611     m_editingCommand->addPoint(m_editingPoint);
00612 }
00613 
00614 void
00615 TimeInstantLayer::editEnd(View *, QMouseEvent *)
00616 {
00617 #ifdef DEBUG_TIME_INSTANT_LAYER
00618     cerr << "TimeInstantLayer::editEnd(" << e->x() << ")" << endl;
00619 #endif
00620     if (!m_model || !m_editing) return;
00621     if (m_editingCommand) {
00622         QString newName = tr("Move Point to %1 s")
00623             .arg(RealTime::frame2RealTime(m_editingPoint.frame,
00624                                           m_model->getSampleRate())
00625                  .toText(false).c_str());
00626         m_editingCommand->setName(newName);
00627         finish(m_editingCommand);
00628     }
00629     m_editingCommand = 0;
00630     m_editing = false;
00631 }
00632 
00633 bool
00634 TimeInstantLayer::editOpen(View *v, QMouseEvent *e)
00635 {
00636     if (!m_model) return false;
00637 
00638     SparseOneDimensionalModel::PointList points = getLocalPoints(v, e->x());
00639     if (points.empty()) return false;
00640 
00641     SparseOneDimensionalModel::Point point = *points.begin();
00642 
00643     ItemEditDialog *dialog = new ItemEditDialog
00644         (m_model->getSampleRate(),
00645          ItemEditDialog::ShowTime |
00646          ItemEditDialog::ShowText);
00647 
00648     dialog->setFrameTime(point.frame);
00649     dialog->setText(point.label);
00650 
00651     if (dialog->exec() == QDialog::Accepted) {
00652 
00653         SparseOneDimensionalModel::Point newPoint = point;
00654         newPoint.frame = dialog->getFrameTime();
00655         newPoint.label = dialog->getText();
00656         
00657         SparseOneDimensionalModel::EditCommand *command =
00658             new SparseOneDimensionalModel::EditCommand(m_model, tr("Edit Point"));
00659         command->deletePoint(point);
00660         command->addPoint(newPoint);
00661         finish(command);
00662     }
00663 
00664     delete dialog;
00665     return true;
00666 }
00667 
00668 void
00669 TimeInstantLayer::moveSelection(Selection s, int newStartFrame)
00670 {
00671     if (!m_model) return;
00672 
00673     SparseOneDimensionalModel::EditCommand *command =
00674         new SparseOneDimensionalModel::EditCommand(m_model,
00675                                                    tr("Drag Selection"));
00676 
00677     SparseOneDimensionalModel::PointList points =
00678         m_model->getPoints(s.getStartFrame(), s.getEndFrame());
00679 
00680     for (SparseOneDimensionalModel::PointList::iterator i = points.begin();
00681          i != points.end(); ++i) {
00682 
00683         if (s.contains(i->frame)) {
00684             SparseOneDimensionalModel::Point newPoint(*i);
00685             newPoint.frame = i->frame + newStartFrame - s.getStartFrame();
00686             command->deletePoint(*i);
00687             command->addPoint(newPoint);
00688         }
00689     }
00690 
00691     finish(command);
00692 }
00693 
00694 void
00695 TimeInstantLayer::resizeSelection(Selection s, Selection newSize)
00696 {
00697     if (!m_model) return;
00698 
00699     SparseOneDimensionalModel::EditCommand *command =
00700         new SparseOneDimensionalModel::EditCommand(m_model,
00701                                                    tr("Resize Selection"));
00702 
00703     SparseOneDimensionalModel::PointList points =
00704         m_model->getPoints(s.getStartFrame(), s.getEndFrame());
00705 
00706     double ratio =
00707         double(newSize.getEndFrame() - newSize.getStartFrame()) /
00708         double(s.getEndFrame() - s.getStartFrame());
00709 
00710     for (SparseOneDimensionalModel::PointList::iterator i = points.begin();
00711          i != points.end(); ++i) {
00712 
00713         if (s.contains(i->frame)) {
00714 
00715             double target = i->frame;
00716             target = newSize.getStartFrame() + 
00717                 double(target - s.getStartFrame()) * ratio;
00718 
00719             SparseOneDimensionalModel::Point newPoint(*i);
00720             newPoint.frame = lrint(target);
00721             command->deletePoint(*i);
00722             command->addPoint(newPoint);
00723         }
00724     }
00725 
00726     finish(command);
00727 }
00728 
00729 void
00730 TimeInstantLayer::deleteSelection(Selection s)
00731 {
00732     if (!m_model) return;
00733 
00734     SparseOneDimensionalModel::EditCommand *command =
00735         new SparseOneDimensionalModel::EditCommand(m_model,
00736                                                    tr("Delete Selection"));
00737 
00738     SparseOneDimensionalModel::PointList points =
00739         m_model->getPoints(s.getStartFrame(), s.getEndFrame());
00740 
00741     for (SparseOneDimensionalModel::PointList::iterator i = points.begin();
00742          i != points.end(); ++i) {
00743         if (s.contains(i->frame)) command->deletePoint(*i);
00744     }
00745 
00746     finish(command);
00747 }
00748 
00749 void
00750 TimeInstantLayer::copy(View *v, Selection s, Clipboard &to)
00751 {
00752     if (!m_model) return;
00753 
00754     SparseOneDimensionalModel::PointList points =
00755         m_model->getPoints(s.getStartFrame(), s.getEndFrame());
00756 
00757     for (SparseOneDimensionalModel::PointList::iterator i = points.begin();
00758          i != points.end(); ++i) {
00759         if (s.contains(i->frame)) {
00760             Clipboard::Point point(i->frame, i->label);
00761             point.setReferenceFrame(alignToReference(v, i->frame));
00762             to.addPoint(point);
00763         }
00764     }
00765 }
00766 
00767 bool
00768 TimeInstantLayer::paste(View *v, const Clipboard &from, int frameOffset, bool)
00769 {
00770     if (!m_model) return false;
00771 
00772     const Clipboard::PointList &points = from.getPoints();
00773 
00774     bool realign = false;
00775 
00776     if (clipboardHasDifferentAlignment(v, from)) {
00777 
00778         QMessageBox::StandardButton button =
00779             QMessageBox::question(v, tr("Re-align pasted instants?"),
00780                                   tr("The instants you are pasting came from a layer with different source material from this one.  Do you want to re-align them in time, to match the source material for this layer?"),
00781                                   QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
00782                                   QMessageBox::Yes);
00783 
00784         if (button == QMessageBox::Cancel) {
00785             return false;
00786         }
00787 
00788         if (button == QMessageBox::Yes) {
00789             realign = true;
00790         }
00791     }
00792 
00793     SparseOneDimensionalModel::EditCommand *command =
00794         new SparseOneDimensionalModel::EditCommand(m_model, tr("Paste"));
00795 
00796     for (Clipboard::PointList::const_iterator i = points.begin();
00797          i != points.end(); ++i) {
00798         
00799         if (!i->haveFrame()) continue;
00800 
00801         int frame = 0;
00802 
00803         if (!realign) {
00804             
00805             frame = i->getFrame();
00806 
00807         } else {
00808 
00809             if (i->haveReferenceFrame()) {
00810                 frame = i->getReferenceFrame();
00811                 frame = alignFromReference(v, frame);
00812             } else {
00813                 frame = i->getFrame();
00814             }
00815         }
00816 
00817         if (frameOffset > 0) frame += frameOffset;
00818         else if (frameOffset < 0) {
00819             if (frame > -frameOffset) frame += frameOffset;
00820             else frame = 0;
00821         }
00822 
00823         SparseOneDimensionalModel::Point newPoint(frame);
00824         if (i->haveLabel()) {
00825             newPoint.label = i->getLabel();
00826         } else if (i->haveValue()) {
00827             newPoint.label = QString("%1").arg(i->getValue());
00828         }
00829         
00830         command->addPoint(newPoint);
00831     }
00832 
00833     finish(command);
00834     return true;
00835 }
00836 
00837 int
00838 TimeInstantLayer::getDefaultColourHint(bool darkbg, bool &impose)
00839 {
00840     impose = false;
00841     return ColourDatabase::getInstance()->getColourIndex
00842         (QString(darkbg ? "Bright Purple" : "Purple"));
00843 }
00844 
00845 void
00846 TimeInstantLayer::toXml(QTextStream &stream,
00847                         QString indent, QString extraAttributes) const
00848 {
00849     SingleColourLayer::toXml(stream, indent,
00850                              extraAttributes +
00851                              QString(" plotStyle=\"%1\"")
00852                              .arg(m_plotStyle));
00853 }
00854 
00855 void
00856 TimeInstantLayer::setProperties(const QXmlAttributes &attributes)
00857 {
00858     SingleColourLayer::setProperties(attributes);
00859 
00860     bool ok;
00861     PlotStyle style = (PlotStyle)
00862         attributes.value("plotStyle").toInt(&ok);
00863     if (ok) setPlotStyle(style);
00864 }
00865