diff options
| author | Stanislaw Halik <sthalik@misaki.pl> | 2014-10-12 00:30:13 +0200 | 
|---|---|---|
| committer | Stanislaw Halik <sthalik@misaki.pl> | 2014-10-12 00:30:13 +0200 | 
| commit | 88f985ca34275fc1cc014c5b8fa618ca95233db7 (patch) | |
| tree | fd1a2418d20a21f843b66b0cec0dc0a7aa503068 /qfunctionconfigurator | |
| parent | f50ef9ca768f676c38fb7f24c15d38e2f72126fb (diff) | |
spline editor needs discard changes on cancel
Diffstat (limited to 'qfunctionconfigurator')
| -rw-r--r-- | qfunctionconfigurator/functionconfig.cpp | 97 | ||||
| -rw-r--r-- | qfunctionconfigurator/functionconfig.h | 12 | ||||
| -rw-r--r-- | qfunctionconfigurator/qfunctionconfigurator.cpp | 71 | ||||
| -rw-r--r-- | qfunctionconfigurator/qfunctionconfigurator.h | 16 | 
4 files changed, 105 insertions, 91 deletions
diff --git a/qfunctionconfigurator/functionconfig.cpp b/qfunctionconfigurator/functionconfig.cpp index 4c52b6eb..0d37156e 100644 --- a/qfunctionconfigurator/functionconfig.cpp +++ b/qfunctionconfigurator/functionconfig.cpp @@ -24,7 +24,6 @@ void Map::setTrackingActive(bool blnActive)  Map::Map() :      _mutex(QMutex::Recursive), -    data(0),      activep(false),      max_x(0),      max_y(0) @@ -48,13 +47,13 @@ bool Map::getLastPoint(QPointF& point ) {  float Map::getValueInternal(int x) {      float sign = x < 0 ? -1 : 1; -    x = std::abs((double) x); +    x = std::abs(x);      float ret; -    int sz = data.size(); +    int sz = cur.data.size();      if (sz == 0)          ret = 0;      else -        ret = data[std::max(std::min(x, sz-1), 0)]; +        ret = cur.data[std::max(std::min(x, sz-1), 0)];      return ret * sign;  } @@ -72,91 +71,99 @@ static bool sortFn(const QPointF& one, const QPointF& two) {  }  void Map::reload() { -    if (input.size()) -            qStableSort(input.begin(), input.end(), sortFn); - -    if (input.size()) +    if (cur.input.size())      { +        auto& input = cur.input; +        auto& data = cur.data; +         +        qStableSort(input.begin(), input.end(), sortFn);          data = std::vector<float>(MEMOIZE_PRECISION * input[input.size() - 1].x()); - +                  const int sz = data.size(); - +                  for (int i = 0; i < sz; i++) -                data[i] = -1; - -                for (int k = 0; k < input[0].x() * MEMOIZE_PRECISION; k++) { +            data[i] = -1; +         +        for (int k = 0; k < input[0].x() * MEMOIZE_PRECISION; k++) {              if (k < sz)                  data[k] = input[0].y() * k / (input[0].x() * MEMOIZE_PRECISION);          } - -       for (int i = 0; i < sz; i++) { +         +        for (int i = 0; i < sz; i++) {              QPointF p0 = ensureInBounds(input, i - 1);              QPointF p1 = ensureInBounds(input, i);              QPointF p2 = ensureInBounds(input, i + 1);              QPointF p3 = ensureInBounds(input, i + 2); - +                          int end = std::min<int>(sz, p2.x() * MEMOIZE_PRECISION);              int start = p1.x() * MEMOIZE_PRECISION; - +                          for (int j = start; j < end; j++) {                  double t = (j - start) / (double) (end - start);                  double t2 = t*t;                  double t3 = t*t*t; - +                                  int x = .5 * ((2. * p1.x()) +                                (-p0.x() + p2.x()) * t +                                (2. * p0.x() - 5. * p1.x() + 4. * p2.x() - p3.x()) * t2 +                                (-p0.x() + 3. * p1.x() - 3. * p2.x() + p3.x()) * t3)                          * MEMOIZE_PRECISION; - +                                  float y = .5 * ((2. * p1.y()) + -                                 (-p0.y() + p2.y()) * t + -                                 (2. * p0.y() - 5. * p1.y() + 4. * p2.y() - p3.y()) * t2 + -                                 (-p0.y() + 3. * p1.y() - 3. * p2.y() + p3.y()) * t3); - +                                (-p0.y() + p2.y()) * t + +                                (2. * p0.y() - 5. * p1.y() + 4. * p2.y() - p3.y()) * t2 + +                                (-p0.y() + 3. * p1.y() - 3. * p2.y() + p3.y()) * t3); +                                  if (x >= 0 && x < sz)                      data[x] = y;              } -       } - -       float last = 0; -       for (int i = 0; i < sz; i++) -       { -           if (data[i] <= 0) -               data[i] = last; -           last = data[i]; -       } +        } +         +        float last = 0; +        for (int i = 0; i < sz; i++) +        { +            if (data[i] <= 0) +                data[i] = last; +            last = data[i]; +        }      } +    else +        cur.data.clear();  }  void Map::removePoint(int i) {      QMutexLocker foo(&_mutex); -    if (i >= 0 && i < input.size()) +    if (i >= 0 && i < cur.input.size())      { -        input.removeAt(i); +        cur.input.removeAt(i);          reload();      }  }  void Map::addPoint(QPointF pt) {      QMutexLocker foo(&_mutex); -        input.append(pt); +        cur.input.append(pt);          reload();  }  void Map::movePoint(int idx, QPointF pt) {      QMutexLocker foo(&_mutex); -    if (idx >= 0 && idx < input.size()) +    if (idx >= 0 && idx < cur.input.size())      { -        input[idx] = pt; +        cur.input[idx] = pt;          reload();      }  }  const QList<QPointF> Map::getPoints() {      QMutexLocker foo(&_mutex); -    // NB can't pass by reference -    return input; +    return cur.input; +} + +void Map::invalidate_unsaved_settings() +{ +    cur = saved; +    reload();  }  void Map::loadSettings(QSettings& settings, const QString& title) { @@ -180,19 +187,20 @@ void Map::loadSettings(QSettings& settings, const QString& title) {      }      settings.endGroup(); -    input = points; +    cur.input = points;      reload(); +    saved = cur;  }  void Map::saveSettings(QSettings& settings, const QString& title) {      QMutexLocker foo(&_mutex);      settings.beginGroup(QString("Curves-%1").arg(title)); -    int max = input.size(); +    int max = cur.input.size();      settings.setValue("point-count", max);      for (int i = 0; i < max; i++) { -        settings.setValue(QString("point-%1-x").arg(i), input[i].x()); -        settings.setValue(QString("point-%1-y").arg(i), input[i].y()); +        settings.setValue(QString("point-%1-x").arg(i), cur.input[i].x()); +        settings.setValue(QString("point-%1-y").arg(i), cur.input[i].y());      }      for (int i = max; true; i++) @@ -203,5 +211,8 @@ void Map::saveSettings(QSettings& settings, const QString& title) {          settings.remove(x);          settings.remove(QString("point-%1-y").arg(i));      } +     +    saved = cur; +              settings.endGroup();  } diff --git a/qfunctionconfigurator/functionconfig.h b/qfunctionconfigurator/functionconfig.h index 7d21fd63..e24f54cf 100644 --- a/qfunctionconfigurator/functionconfig.h +++ b/qfunctionconfigurator/functionconfig.h @@ -20,17 +20,22 @@  class OPENTRACK_EXPORT Map {  private: +    struct State { +        QList<QPointF> input; +        std::vector<float> data;         +    }; +          static constexpr long MEMOIZE_PRECISION = 25;      void reload();      float getValueInternal(int x);      MyMutex _mutex; -    QList<QPointF> input; -    std::vector<float> data;      QPointF last_input_value;      volatile bool activep;      int max_x;      int max_y; +     +    State cur, saved;  public:      int maxInput() const { return max_x; }      int maxOutput() const { return max_y; } @@ -46,7 +51,7 @@ public:      void removePoint(int i);      void removeAllPoints() {          QMutexLocker foo(&_mutex); -        input.clear(); +        cur.input.clear();          reload();      } @@ -62,6 +67,7 @@ public:      void saveSettings(QSettings& settings, const QString& title);      void loadSettings(QSettings& settings, const QString& title); +    void invalidate_unsaved_settings();      void setTrackingActive(bool blnActive);  }; diff --git a/qfunctionconfigurator/qfunctionconfigurator.cpp b/qfunctionconfigurator/qfunctionconfigurator.cpp index 57d1500a..b15f308e 100644 --- a/qfunctionconfigurator/qfunctionconfigurator.cpp +++ b/qfunctionconfigurator/qfunctionconfigurator.cpp @@ -10,20 +10,11 @@  #include "qfunctionconfigurator/qfunctionconfigurator.h"  #include <QPainter>  #include <QPaintEvent> -#include <QPainterPathStroker> -#include <QPainterPath> -#include <QBrush> -#include <QFileDialog>  #include <QPen> -#include <QMessageBox> -#include <QImage>  #include <QPixmap>  #include <QTimer> -#include <QtDebug>  #include <cmath> -#include <QTabWidget> -#include <QTabBar> -#include <QFontMetrics> +#include <algorithm>  static const int pointSize = 5; @@ -57,8 +48,7 @@ void QFunctionConfigurator::drawBackground()      QPainter painter(&_background);      painter.fillRect(rect(), QColor::fromRgb(204, 204, 204)); -    painter.setRenderHint(QPainter::Antialiasing); -     +      QColor bg_color(112, 154, 209);      painter.fillRect(pixel_bounds, bg_color); @@ -140,8 +130,6 @@ void QFunctionConfigurator::drawFunction()      _function = QPixmap(_background);      QPainter painter(&_function); - -    painter.save();      painter.setRenderHint(QPainter::Antialiasing, true);      QList<QPointF> points = _config->getPoints(); @@ -164,13 +152,11 @@ void QFunctionConfigurator::drawFunction()          drawLine(&painter, prev, cur, pen);          prev = cur;      } -    painter.restore();  }  void QFunctionConfigurator::paintEvent(QPaintEvent *e)  {      QPainter p(this); -    p.setRenderHint(QPainter::Antialiasing);      if (_background.isNull())          drawBackground(); @@ -179,6 +165,7 @@ void QFunctionConfigurator::paintEvent(QPaintEvent *e)          _draw_function = false;          drawFunction();      } +          p.drawPixmap(e->rect(), _function);      if (_config) { @@ -246,10 +233,9 @@ void QFunctionConfigurator::mousePressEvent(QMouseEvent *e)          moving_control_point_idx = -1;          if (_config) {              for (int i = 0; i < points.size(); i++) { -                if ( point_within_pixel(points[i], e->pos() ) ) { +                if (point_within_pixel(points[i], e->pos())) {                      bTouchingPoint = true;                      moving_control_point_idx = i; -                    timer.restart();                      break;                  }              } @@ -263,7 +249,7 @@ void QFunctionConfigurator::mousePressEvent(QMouseEvent *e)          if (_config) {              int found_pt = -1;              for (int i = 0; i < points.size(); i++) { -                if ( point_within_pixel(points[i], e->pos() ) ) { +                if (point_within_pixel(points[i], e->pos())) {                      found_pt = i;                      break;                  } @@ -284,21 +270,31 @@ void QFunctionConfigurator::mouseMoveEvent(QMouseEvent *e)      if (!_config)          return; -    static constexpr int min_refresh_delay = 25; +    static constexpr int min_refresh_delay = 12;      if (timer.isValid() && timer.elapsed() < min_refresh_delay)          return; -    static constexpr int refresh_delay = 50; +    static constexpr int refresh_delay = 17;      QList<QPointF> points = _config->getPoints(); -    if (moving_control_point_idx >= 0 && moving_control_point_idx < points.size()) { +    if (moving_control_point_idx != -1 && moving_control_point_idx < points.size()) {          setCursor(Qt::ClosedHandCursor); - -        if (timer.isValid() && timer.elapsed() > refresh_delay) +         +        bool overlap = false; +         +        QPointF new_pt = pixel_coord_to_point(e->pos()); +         +        if (moving_control_point_idx + 1 < points.size()) +            overlap |= new_pt.x() > points[moving_control_point_idx+1].x(); +        if (moving_control_point_idx != 0) +            overlap |= new_pt.x() < points[moving_control_point_idx-1].x(); +         +        if (overlap) +            moving_control_point_idx = -1; +        else if (timer.isValid() && timer.elapsed() > refresh_delay)          {              timer.restart(); -            QPointF new_pt = pixel_coord_to_point(e->pos());              points[moving_control_point_idx] = new_pt;              _config->movePoint(moving_control_point_idx, new_pt);              _draw_function = true; @@ -326,11 +322,9 @@ void QFunctionConfigurator::mouseReleaseEvent(QMouseEvent *e)  {      if (!_config)          return; -     -    QList<QPointF> points = _config->getPoints();      if (e->button() == Qt::LeftButton) { -        timer.invalidate(); +        QList<QPointF> points = _config->getPoints();          if (moving_control_point_idx >= 0 && moving_control_point_idx < points.size()) {              if (_config) {                  _config->movePoint(moving_control_point_idx, pixel_coord_to_point(e->pos())); @@ -338,10 +332,27 @@ void QFunctionConfigurator::mouseReleaseEvent(QMouseEvent *e)          }          setCursor(Qt::ArrowCursor);          moving_control_point_idx = -1; +         +        _draw_function = true; +        update();      } +} +void QFunctionConfigurator::update_range() +{ +    if (!_config) +        return; +     +    const double w = width(), h = height(); +    const double mwl = 40, mhl = 20; +    const double mwr = 15, mhr = 35; +     +    pixel_bounds = QRectF(mwl, mhl, (w - mwl - mwr), (h - mhl - mhr)); +    c = QPointF(pixel_bounds.width() / _config->maxInput(), pixel_bounds.height() / _config->maxOutput());      _draw_function = true; -    update(); +     +    _background = QPixmap(); +    _function = QPixmap();  }  bool QFunctionConfigurator::point_within_pixel(const QPointF &pt, const QPointF &pixel) @@ -382,5 +393,5 @@ QPointF QFunctionConfigurator::point_to_pixel(const QPointF& point)  void QFunctionConfigurator::resizeEvent(QResizeEvent *)  {      update_range(); -    repaint(); +    update();  } diff --git a/qfunctionconfigurator/qfunctionconfigurator.h b/qfunctionconfigurator/qfunctionconfigurator.h index e35d0bc3..25d8f8bc 100644 --- a/qfunctionconfigurator/qfunctionconfigurator.h +++ b/qfunctionconfigurator/qfunctionconfigurator.h @@ -46,21 +46,7 @@ private:  protected:  	virtual void resizeEvent(QResizeEvent *);  private: -    void update_range() { -        if (!_config) -            return; -         -        const double w = width(), h = height(); -        const double mwl = 40, mhl = 20; -        const double mwr = 15, mhr = 35; -         -        pixel_bounds = QRectF(mwl, mhl, (w - mwl - mwr), (h - mhl - mhr)); -        c = QPointF(pixel_bounds.width() / _config->maxInput(), pixel_bounds.height() / _config->maxOutput()); -        _draw_function = true; -         -        _background = QPixmap(); -        _function = QPixmap(); -    } +    void update_range();      QPointF pixel_coord_to_point (const QPointF& point);      QPointF point_to_pixel (const QPointF& point);  | 
