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

Generated on Wed Feb 20 15:45:29 2008 for SonicVisualiser by  doxygen 1.5.1