18 #include "data/model/Model.h" 19 #include "base/RealTime.h" 20 #include "base/Profiler.h" 24 #include "data/model/TextModel.h" 27 #include <QMouseEvent> 28 #include <QInputDialog> 29 #include <QTextStream> 30 #include <QMessageBox> 39 m_originalPoint(0, 0.0, tr(
"Empty Label")),
40 m_editingPoint(0, 0.0, tr(
"Empty Label")),
80 int *min,
int *max,
int *deflt)
const 115 if (!
m_model)
return TextModel::PointList();
120 TextModel::PointList points(
m_model->getPoints(frame0, frame1));
122 TextModel::PointList rv;
123 QFontMetrics metrics = QFontMetrics(QFont());
125 for (TextModel::PointList::iterator i = points.begin();
126 i != points.end(); ++i) {
128 const TextModel::Point &p(*i);
133 QString label = p.label;
135 label = tr(
"<no text>");
138 QRect rect = metrics.boundingRect
139 (QRect(0, 0, 150, 200),
140 Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, label);
142 if (py + rect.height() > v->height()) {
143 if (rect.height() > v->height()) py = 0;
144 else py = v->height() - rect.height() - 1;
147 if (x >= px && x < px + rect.width() &&
148 y >= py && y < py + rect.height()) {
163 TextModel::PointList onPoints =
m_model->getPoints(a, b);
164 if (onPoints.empty())
return false;
166 float nearestDistance = -1;
168 for (TextModel::PointList::const_iterator i = onPoints.begin();
169 i != onPoints.end(); ++i) {
173 float distance = sqrtf(yd*yd + xd*xd);
175 if (nearestDistance == -1 || distance < nearestDistance) {
176 nearestDistance = distance;
193 if (points.empty()) {
195 return tr(
"In progress");
201 long useFrame = points.begin()->frame;
203 RealTime rt = RealTime::frame2RealTime(useFrame,
m_model->getSampleRate());
207 if (points.begin()->label ==
"") {
208 text = QString(tr(
"Time:\t%1\nHeight:\t%2\nLabel:\t%3"))
209 .arg(rt.toText(
true).c_str())
210 .arg(points.begin()->height)
211 .arg(points.begin()->label);
231 resolution =
m_model->getResolution();
232 TextModel::PointList points;
237 if (points.empty())
return false;
238 frame = points.begin()->frame;
242 points =
m_model->getPoints(frame, frame);
246 for (TextModel::PointList::const_iterator i = points.begin();
247 i != points.end(); ++i) {
251 if (i->frame > frame) {
259 if (i->frame <= frame) {
268 TextModel::PointList::const_iterator j = i;
271 if (j == points.end()) {
277 }
else if (j->frame >= frame) {
279 if (j->frame - frame < frame - i->frame) {
298 return h - int(height * h);
305 return float(h - y) / h;
313 int sampleRate =
m_model->getSampleRate();
314 if (!sampleRate)
return;
318 int x0 = rect.left(), x1 = rect.right();
322 TextModel::PointList points(
m_model->getPoints(frame0, frame1));
323 if (points.empty())
return;
328 brushColour.getHsv(&h, &s, &val);
329 brushColour.setHsv(h, s, 255, 100);
338 TextModel::Point illuminatePoint(0);
339 bool shouldIlluminate =
false;
346 int boxMaxWidth = 150;
347 int boxMaxHeight = 200;
350 paint.setClipRect(rect.x(), 0, rect.width() + boxMaxWidth, v->height());
352 for (TextModel::PointList::const_iterator i = points.begin();
353 i != points.end(); ++i) {
355 const TextModel::Point &p(*i);
360 if (!shouldIlluminate ||
362 TextModel::Point::Comparator()(illuminatePoint, p) ||
363 TextModel::Point::Comparator()(p, illuminatePoint)) {
364 paint.setPen(penColour);
365 paint.setBrush(brushColour);
367 paint.setBrush(penColour);
371 QString label = p.label;
373 label = tr(
"<no text>");
376 QRect boxRect =
paint.fontMetrics().boundingRect
377 (QRect(0, 0, boxMaxWidth, boxMaxHeight),
378 Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, label);
380 QRect textRect = QRect(3, 2, boxRect.width(), boxRect.height());
381 boxRect = QRect(0, 0, boxRect.width() + 6, boxRect.height() + 2);
383 if (y + boxRect.height() > v->height()) {
384 if (boxRect.height() > v->height()) y = 0;
385 else y = v->height() - boxRect.height() - 1;
388 boxRect = QRect(x, y, boxRect.width(), boxRect.height());
389 textRect = QRect(x + 3, y + 2, textRect.width(), textRect.height());
394 paint.setRenderHint(QPainter::Antialiasing,
false);
395 paint.drawRect(boxRect);
397 paint.setRenderHint(QPainter::Antialiasing,
true);
398 paint.drawText(textRect,
399 Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap,
410 paint.setRenderHint(QPainter::Antialiasing,
false);
419 SVDEBUG <<
"TextLayer::drawStart: no model" << endl;
424 if (frame < 0) frame = 0;
425 frame = frame /
m_model->getResolution() *
m_model->getResolution();
447 if (frame < 0) frame = 0;
448 frame = frame /
m_model->getResolution() *
m_model->getResolution();
465 QString label = QInputDialog::getText(v, tr(
"Enter label"),
466 tr(
"Please enter a new label:"),
467 QLineEdit::Normal,
"", &ok);
470 TextModel::RelabelCommand *command =
509 TextModel::Point p(0);
557 if (frame < 0) frame = 0;
558 frame = (frame /
m_model->getResolution()) *
m_model->getResolution();
584 newName = tr(
"Move Label");
586 newName = tr(
"Move Label Horizontally");
589 newName = tr(
"Move Label Vertically");
605 TextModel::Point text(0);
608 QString label = text.label;
611 label = QInputDialog::getText(v, tr(
"Enter label"),
612 tr(
"Please enter a new label:"),
613 QLineEdit::Normal, label, &ok);
614 if (ok && label != text.label) {
615 TextModel::RelabelCommand *command =
616 new TextModel::RelabelCommand(
m_model, text, label);
628 TextModel::EditCommand *command =
629 new TextModel::EditCommand(
m_model, tr(
"Drag Selection"));
631 TextModel::PointList points =
632 m_model->getPoints(s.getStartFrame(), s.getEndFrame());
634 for (TextModel::PointList::iterator i = points.begin();
635 i != points.end(); ++i) {
637 if (s.contains(i->frame)) {
638 TextModel::Point newPoint(*i);
639 newPoint.frame = i->frame + newStartFrame - s.getStartFrame();
640 command->deletePoint(*i);
641 command->addPoint(newPoint);
653 TextModel::EditCommand *command =
654 new TextModel::EditCommand(
m_model, tr(
"Resize Selection"));
656 TextModel::PointList points =
657 m_model->getPoints(s.getStartFrame(), s.getEndFrame());
660 double(newSize.getEndFrame() - newSize.getStartFrame()) /
661 double(s.getEndFrame() - s.getStartFrame());
663 for (TextModel::PointList::iterator i = points.begin();
664 i != points.end(); ++i) {
666 if (s.contains(i->frame)) {
668 double target = i->frame;
669 target = newSize.getStartFrame() +
670 double(target - s.getStartFrame()) * ratio;
672 TextModel::Point newPoint(*i);
673 newPoint.frame = lrint(target);
674 command->deletePoint(*i);
675 command->addPoint(newPoint);
687 TextModel::EditCommand *command =
688 new TextModel::EditCommand(
m_model, tr(
"Delete Selection"));
690 TextModel::PointList points =
691 m_model->getPoints(s.getStartFrame(), s.getEndFrame());
693 for (TextModel::PointList::iterator i = points.begin();
694 i != points.end(); ++i) {
695 if (s.contains(i->frame)) command->deletePoint(*i);
706 TextModel::PointList points =
707 m_model->getPoints(s.getStartFrame(), s.getEndFrame());
709 for (TextModel::PointList::iterator i = points.begin();
710 i != points.end(); ++i) {
711 if (s.contains(i->frame)) {
712 Clipboard::Point point(i->frame, i->height, i->label);
724 const Clipboard::PointList &points = from.getPoints();
726 bool realign =
false;
730 QMessageBox::StandardButton button =
731 QMessageBox::question(v, tr(
"Re-align pasted items?"),
732 tr(
"The items 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?"),
733 QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
736 if (button == QMessageBox::Cancel) {
740 if (button == QMessageBox::Yes) {
745 TextModel::EditCommand *command =
746 new TextModel::EditCommand(
m_model, tr(
"Paste"));
748 float valueMin = 0.0, valueMax = 1.0;
749 for (Clipboard::PointList::const_iterator i = points.begin();
750 i != points.end(); ++i) {
751 if (i->haveValue()) {
752 if (i->getValue() < valueMin) valueMin = i->getValue();
753 if (i->getValue() > valueMax) valueMax = i->getValue();
756 if (valueMax < valueMin + 1.0) valueMax = valueMin + 1.0;
758 for (Clipboard::PointList::const_iterator i = points.begin();
759 i != points.end(); ++i) {
761 if (!i->haveFrame())
continue;
766 frame = i->getFrame();
770 if (i->haveReferenceFrame()) {
771 frame = i->getReferenceFrame();
774 frame = i->getFrame();
778 TextModel::Point newPoint(frame);
780 if (i->haveValue()) {
781 newPoint.height = (i->getValue() - valueMin) / (valueMax - valueMin);
783 newPoint.height = 0.5;
786 if (i->haveLabel()) {
787 newPoint.label = i->getLabel();
788 }
else if (i->haveValue()) {
789 newPoint.label = QString(
"%1").arg(i->getValue());
791 newPoint.label = tr(
"New Point");
794 command->addPoint(newPoint);
806 (QString(darkbg ?
"Bright Orange" :
"Orange"));
811 QString indent, QString extraAttributes)
const virtual void drawStart(View *v, QMouseEvent *)
int getFrameForX(int x) const
Return the closest frame to the given pixel x-coordinate.
virtual void paint(View *v, QPainter &paint, QRect rect) const
Paint the given rectangle of this layer onto the given view using the given painter,...
virtual void deleteSelection(Selection s)
TextModel::Point m_editingPoint
virtual void drawEnd(View *v, QMouseEvent *)
TextModel::Point m_originalPoint
bool getPointToDrag(View *v, int x, int y, TextModel::Point &) const
virtual bool snapToFeatureFrame(View *, int &, int &resolution, SnapType) const
Adjust the given frame to snap to the nearest feature, if possible.
void connectSignals(const Model *)
virtual QColor getForeground() const
void setProperties(const QXmlAttributes &attributes)
Set the particular properties of a layer (those specific to the subclass) from a set of XML attribute...
void setModel(TextModel *model)
virtual void toXml(QTextStream &stream, QString indent="", QString extraAttributes="") const
Convert the layer's data (though not those of the model it refers to) into XML for file output.
void addCommand(Command *command)
Add a command to the command history.
virtual bool getValueExtents(float &min, float &max, bool &logarithmic, QString &unit) const
Return the minimum and maximum values for the y axis of the model in this layer, as well as whether t...
virtual QString getPropertyValueLabel(const PropertyName &, int value) const
virtual bool shouldIlluminateLocalFeatures(const Layer *, QPoint &) const
void finish(TextModel::EditCommand *command)
virtual void eraseStart(View *v, QMouseEvent *)
virtual PropertyList getProperties() const
virtual void eraseDrag(View *v, QMouseEvent *)
virtual QColor getBaseQColor() const
virtual void editStart(View *v, QMouseEvent *)
virtual void editDrag(View *v, QMouseEvent *)
int getColourIndex(QString name) const
TextModel::PointList getLocalPoints(View *v, int x, int y) const
virtual void setProperty(const PropertyName &, int value)
virtual QString getPropertyLabel(const PropertyName &) const
virtual bool snapToFeatureFrame(View *v, int &frame, int &resolution, SnapType snap) const
!! too much overlap with TimeValueLayer/TimeInstantLayer
virtual int getPropertyRangeAndValue(const PropertyName &, int *min, int *max, int *deflt) const
virtual void editEnd(View *v, QMouseEvent *)
virtual void setProperties(const QXmlAttributes &attributes)
Set the particular properties of a layer (those specific to the subclass) from a set of XML attribute...
virtual int getPropertyRangeAndValue(const PropertyName &, int *min, int *max, int *deflt) const
static CommandHistory * getInstance()
bool clipboardHasDifferentAlignment(View *v, const Clipboard &clip) const
virtual void copy(View *v, Selection s, Clipboard &to)
int getYForHeight(View *v, float height) const
virtual PropertyType getPropertyType(const PropertyName &) const
virtual bool editOpen(View *, QMouseEvent *)
Open an editor on the item under the mouse (e.g.
virtual int getDefaultColourHint(bool dark, bool &impose)
virtual void eraseEnd(View *v, QMouseEvent *)
virtual int alignFromReference(View *v, int frame) const
virtual int alignToReference(View *v, int frame) const
virtual void drawDrag(View *v, QMouseEvent *)
View is the base class of widgets that display one or more overlaid views of data against a horizonta...
virtual void moveSelection(Selection s, int newStartFrame)
virtual bool isLayerScrollable(const View *v) const
This should return true if the layer can safely be scrolled automatically by a given view (simply cop...
float getHeightForY(View *v, int y) const
virtual void resizeSelection(Selection s, Selection newSize)
virtual QString getPropertyValueLabel(const PropertyName &, int value) const
virtual void toXml(QTextStream &stream, QString indent="", QString extraAttributes="") const
Convert the layer's data (though not those of the model it refers to) into XML for file output.
virtual PropertyList getProperties() const
TextModel::EditCommand * m_editingCommand
virtual QString getFeatureDescription(View *v, QPoint &) const
virtual QColor getBackground() const
virtual QString getPropertyLabel(const PropertyName &) const
virtual PropertyType getPropertyType(const PropertyName &) const
int getXForFrame(int frame) const
Return the pixel x-coordinate corresponding to a given sample frame (which may be negative).
static ColourDatabase * getInstance()
virtual void setProperty(const PropertyName &, int value)
virtual bool paste(View *v, const Clipboard &from, int frameOffset, bool interactive)
Paste from the given clipboard onto the layer at the given frame offset.