Changeset View
Standalone View
kmplot/view.cpp
Show First 20 Lines • Show All 81 Lines • ▼ Show 20 Line(s) | |||||
82 | 82 | | |||
83 | //BEGIN class View | 83 | //BEGIN class View | ||
84 | View * View::m_self = 0; | 84 | View * View::m_self = 0; | ||
85 | 85 | | |||
86 | View::View( bool readOnly, QMenu * functionPopup, QWidget* parent ) | 86 | View::View( bool readOnly, QMenu * functionPopup, QWidget* parent ) | ||
87 | : QWidget( parent ), | 87 | : QWidget( parent ), | ||
88 | buffer( width(), height() ), | 88 | buffer( width(), height() ), | ||
89 | m_popupMenu( functionPopup ), | 89 | m_popupMenu( functionPopup ), | ||
90 | m_readonly( readOnly ) | 90 | m_readonly( readOnly ), | ||
91 | m_AccumulatedDelta(0), | ||||
92 | m_viewportAnimation( new QPropertyAnimation( this, "viewport" ) ) | ||||
91 | { | 93 | { | ||
92 | assert( !m_self ); // this class should only be constructed once | 94 | assert( !m_self ); // this class should only be constructed once | ||
93 | m_self = this; | 95 | m_self = this; | ||
94 | setAttribute( Qt::WA_StaticContents ); | 96 | setAttribute( Qt::WA_StaticContents ); | ||
95 | 97 | | |||
96 | m_haveRoot = false; | 98 | m_haveRoot = false; | ||
97 | m_xmin = m_xmax = m_ymin = m_ymax = 0.0; | 99 | m_xmin = m_xmax = m_ymin = m_ymax = 0.0; | ||
98 | m_printHeaderTable = false; | 100 | m_printHeaderTable = false; | ||
▲ Show 20 Lines • Show All 2868 Lines • ▼ Show 20 Line(s) | 2960 | { | |||
2967 | bool upperOk = ((!plot->usecustomxmax) || (plot->usecustomxmax && m_crosshairPosition.x()<plot->dmax.value())); | 2969 | bool upperOk = ((!plot->usecustomxmax) || (plot->usecustomxmax && m_crosshairPosition.x()<plot->dmax.value())); | ||
2968 | 2970 | | |||
2969 | return lowerOk && upperOk; | 2971 | return lowerOk && upperOk; | ||
2970 | } | 2972 | } | ||
2971 | 2973 | | |||
2972 | 2974 | | |||
2973 | void View::mousePressEvent(QMouseEvent *e) | 2975 | void View::mousePressEvent(QMouseEvent *e) | ||
2974 | { | 2976 | { | ||
2977 | m_AccumulatedDelta = 0; | ||||
2975 | m_mousePressTimer->start(); | 2978 | m_mousePressTimer->start(); | ||
2976 | 2979 | | |||
2977 | // In general, we want to update the view | 2980 | // In general, we want to update the view | ||
2978 | update(); | 2981 | update(); | ||
2979 | 2982 | | |||
2980 | if ( m_popupMenuStatus != NoPopup ) | 2983 | if ( m_popupMenuStatus != NoPopup ) | ||
2981 | return; | 2984 | return; | ||
2982 | 2985 | | |||
▲ Show 20 Lines • Show All 338 Lines • ▼ Show 20 Line(s) | 3271 | { | |||
3321 | numberText.replace( '-', MinusSymbol ); | 3324 | numberText.replace( '-', MinusSymbol ); | ||
3322 | 3325 | | |||
3323 | return numberText; | 3326 | return numberText; | ||
3324 | } | 3327 | } | ||
3325 | 3328 | | |||
3326 | 3329 | | |||
3327 | void View::mouseMoveEvent(QMouseEvent *e) | 3330 | void View::mouseMoveEvent(QMouseEvent *e) | ||
3328 | { | 3331 | { | ||
3332 | if ( m_previousMouseMovePos != e->globalPos() ) | ||||
3333 | { | ||||
3334 | m_AccumulatedDelta = 0; | ||||
3335 | } | ||||
3336 | m_previousMouseMovePos = e->globalPos(); | ||||
3337 | m_AccumulatedDelta = 0; | ||||
3329 | if ( m_isDrawing || !e) | 3338 | if ( m_isDrawing || !e) | ||
3330 | return; | 3339 | return; | ||
3331 | 3340 | | |||
3332 | bool inBounds = updateCrosshairPosition(); | 3341 | bool inBounds = updateCrosshairPosition(); | ||
3333 | if ( !m_haveRoot ) | 3342 | if ( !m_haveRoot ) | ||
3334 | setStatusBar( QString(), RootSection ); | 3343 | setStatusBar( QString(), RootSection ); | ||
3335 | 3344 | | |||
3336 | QString sx, sy; | 3345 | QString sx, sy; | ||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Line(s) | |||||
3384 | 3393 | | |||
3385 | void View::leaveEvent(QEvent *) | 3394 | void View::leaveEvent(QEvent *) | ||
3386 | { | 3395 | { | ||
3387 | setStatusBar( "", XSection ); | 3396 | setStatusBar( "", XSection ); | ||
3388 | setStatusBar( "", YSection ); | 3397 | setStatusBar( "", YSection ); | ||
3389 | 3398 | | |||
3390 | updateCrosshairPosition(); | 3399 | updateCrosshairPosition(); | ||
3391 | update(); | 3400 | update(); | ||
3392 | } | 3401 | } | ||
aacid: You may want to accumulate the deltas, some touchpads send lots of events with very small… | |||||
3393 | 3402 | | |||
3394 | 3403 | | |||
3404 | void View::wheelEvent(QWheelEvent *e) | ||||
3405 | { | ||||
3406 | m_AccumulatedDelta += e->delta(); | ||||
3407 | | ||||
3408 | if (e->modifiers() & Qt::ControlModifier) | ||||
3409 | { | ||||
3410 | if (m_AccumulatedDelta >= QWheelEvent::DefaultDeltasPerStep) | ||||
3411 | { | ||||
3412 | zoomIn( e->pos(), double(Settings::zoomInStep())/100.0 ); | ||||
3413 | m_AccumulatedDelta = 0; | ||||
3414 | } | ||||
3415 | else if (m_AccumulatedDelta <= -QWheelEvent::DefaultDeltasPerStep) | ||||
3416 | { | ||||
3417 | zoomIn( e->pos(), (double(Settings::zoomOutStep())/100.0) + 1.0 ); | ||||
3418 | m_AccumulatedDelta = 0; | ||||
3419 | } | ||||
3420 | e->accept(); | ||||
3421 | return; | ||||
3422 | } | ||||
3423 | else | ||||
3424 | { | ||||
3425 | m_AccumulatedDelta = 0; | ||||
3426 | } | ||||
3427 | QWidget::wheelEvent(e); | ||||
3428 | } | ||||
3429 | | ||||
3430 | | ||||
3395 | bool View::updateCrosshairPosition() | 3431 | bool View::updateCrosshairPosition() | ||
3396 | { | 3432 | { | ||
3397 | QPointF mousePos = mapFromGlobal( QCursor::pos() ); | 3433 | QPointF mousePos = mapFromGlobal( QCursor::pos() ); | ||
3398 | 3434 | | |||
3399 | bool out_of_bounds = false; // for the ypos | 3435 | bool out_of_bounds = false; // for the ypos | ||
3400 | 3436 | | |||
3401 | m_crosshairPosition = toReal( mousePos ); | 3437 | m_crosshairPosition = toReal( mousePos ); | ||
3402 | 3438 | | |||
▲ Show 20 Lines • Show All 199 Lines • ▼ Show 20 Line(s) | 3623 | { | |||
3602 | double real2x = (m_xmax-lx)/kx; | 3638 | double real2x = (m_xmax-lx)/kx; | ||
3603 | 3639 | | |||
3604 | double real1y = (m_ymax-ly)/ky; | 3640 | double real1y = (m_ymax-ly)/ky; | ||
3605 | double real2y = (m_ymin-ly)/ky; | 3641 | double real2y = (m_ymin-ly)/ky; | ||
3606 | 3642 | | |||
3607 | animateZoom( QRectF( QPointF( real1x, real1y ), QSizeF( real2x-real1x, real2y-real1y ) ) ); | 3643 | animateZoom( QRectF( QPointF( real1x, real1y ), QSizeF( real2x-real1x, real2y-real1y ) ) ); | ||
3608 | } | 3644 | } | ||
3609 | 3645 | | |||
3610 | 3646 | | |||
You either need to delete the existing one or not create one every single time otherwise we end up with lots of qpropertyanimations when we don't really need that many, no? aacid: You either need to delete the existing one or not create one every single time otherwise we end… | |||||
3611 | void View::animateZoom( const QRectF & _newCoords ) | 3647 | void View::animateZoom( const QRectF & _newCoords ) | ||
3612 | { | 3648 | { | ||
3613 | QRectF oldCoords( m_xmin, m_ymin, m_xmax-m_xmin, m_ymax-m_ymin ); | 3649 | QRectF oldCoords( m_xmin, m_ymin, m_xmax-m_xmin, m_ymax-m_ymin ); | ||
3614 | QRectF newCoords( _newCoords.normalized() ); | 3650 | QRectF newCoords( _newCoords.normalized() ); | ||
3615 | 3651 | | |||
3616 | if ( newCoords.left() == m_xmin && | 3652 | if ( newCoords.left() == m_xmin && | ||
3617 | newCoords.right() == m_xmax && | 3653 | newCoords.right() == m_xmax && | ||
3618 | newCoords.top() == m_ymin && | 3654 | newCoords.top() == m_ymin && | ||
3619 | newCoords.bottom() == m_ymax ) | 3655 | newCoords.bottom() == m_ymax ) | ||
3620 | return; | 3656 | return; | ||
3621 | 3657 | | |||
3622 | m_zoomMode = AnimatingZoom; | 3658 | m_zoomMode = AnimatingZoom; | ||
3623 | 3659 | | |||
3624 | double oldCoordsArea = (m_xmax-m_xmin) * (m_ymax-m_ymin); | 3660 | if ( style()->styleHint(QStyle::SH_Widget_Animate) && m_viewportAnimation->state() == QAbstractAnimation::Stopped ) | ||
3625 | double newCoordsArea = newCoords.width() * newCoords.height(); | | |||
3626 | | ||||
3627 | QPointF beginTL, beginBR, endTL, endBR; | | |||
3628 | | ||||
3629 | if ( oldCoordsArea > newCoordsArea ) | | |||
3630 | { | 3661 | { | ||
3631 | // zooming in | 3662 | m_viewportAnimation->setDuration( 150 ); | ||
3632 | beginTL = newCoords.topLeft(); | 3663 | m_viewportAnimation->setEasingCurve( QEasingCurve::OutCubic ); | ||
3633 | beginBR = newCoords.bottomRight(); | 3664 | m_viewportAnimation->setStartValue( oldCoords ); | ||
3634 | endTL = QPointF( m_xmin, m_ymin ); | 3665 | m_viewportAnimation->setEndValue( newCoords ); | ||
3635 | endBR = QPointF( m_xmax, m_ymax ); | 3666 | m_viewportAnimation->start(); | ||
3667 | connect(m_viewportAnimation, &QPropertyAnimation::finished, [this, newCoords] | ||||
3668 | { | ||||
3669 | finishAnimation( newCoords ); | ||||
3670 | }); | ||||
3636 | } | 3671 | } | ||
3637 | else | 3672 | else | ||
3638 | { | 3673 | { | ||
3639 | // zooming out | 3674 | finishAnimation( newCoords ); | ||
3640 | beginTL = QPointF( m_xmin, m_ymin ); | | |||
3641 | beginBR = QPointF( m_xmax, m_ymax ); | | |||
3642 | | ||||
3643 | double kx = ( m_xmin - m_xmax ) / ( newCoords.left() - newCoords.right() ); | | |||
3644 | double ky = ( m_ymin - m_ymax ) / ( newCoords.top() - newCoords.bottom() ); | | |||
3645 | | ||||
3646 | double lx = m_xmin - (kx * newCoords.left()); | | |||
3647 | double ly = m_ymin - (ky * newCoords.top()); | | |||
3648 | | ||||
3649 | endTL = QPointF( (kx * m_xmin) + lx, (ky * m_ymin) + ly ); | | |||
3650 | endBR = QPointF( (kx * m_xmax) + lx, (ky * m_ymax) + ly ); | | |||
3651 | } | 3675 | } | ||
3652 | 3676 | Settings::self()->save(); | |||
3653 | double MAX = 10; | | |||
3654 | double ms = MAX*16; // milliseconds to animate for | | |||
3655 | | ||||
3656 | for ( int i = 0; i <= MAX; ++i ) | | |||
3657 | { | | |||
3658 | QTime t; | | |||
3659 | t.start(); | | |||
3660 | | ||||
3661 | QPointF tl = (( i*endTL) + ((MAX-i)*beginTL)) / MAX; | | |||
3662 | QPointF br = (( i*endBR) + ((MAX-i)*beginBR)) / MAX; | | |||
3663 | | ||||
3664 | m_animateZoomRect = QRectF( tl, QSizeF( br.x()-tl.x(), br.y()-tl.y() ) ); | | |||
3665 | | ||||
3666 | repaint(); | | |||
3667 | | ||||
3668 | if ( i == MAX ) | | |||
3669 | break; | | |||
3670 | else while ( t.elapsed() < (ms/MAX) ) | | |||
3671 | ; // do nothing | | |||
3672 | } | 3677 | } | ||
3673 | 3678 | | |||
3674 | m_xmin = newCoords.left(); | 3679 | void View::finishAnimation( const QRectF & rect ) | ||
3675 | m_xmax = newCoords.right(); | 3680 | { | ||
3676 | m_ymin = newCoords.top(); | 3681 | m_xmin = rect.left(); | ||
3677 | m_ymax = newCoords.bottom(); | 3682 | m_xmax = rect.right(); | ||
3683 | m_ymin = rect.top(); | ||||
3684 | m_ymax = rect.bottom(); | ||||
3678 | 3685 | | |||
3679 | Settings::setXMin( Parser::number( m_xmin ) ); | 3686 | Settings::setXMin( Parser::number( m_xmin ) ); | ||
3680 | Settings::setXMax( Parser::number( m_xmax ) ); | 3687 | Settings::setXMax( Parser::number( m_xmax ) ); | ||
3681 | Settings::setYMin( Parser::number( m_ymin ) ); | 3688 | Settings::setYMin( Parser::number( m_ymin ) ); | ||
3682 | Settings::setYMax( Parser::number( m_ymax ) ); | 3689 | Settings::setYMax( Parser::number( m_ymax ) ); | ||
aacid: this function should probably be const | |||||
3683 | Settings::self()->save(); | | |||
3684 | MainDlg::self()->coordsDialog()->updateXYRange(); | 3690 | MainDlg::self()->coordsDialog()->updateXYRange(); | ||
3685 | MainDlg::self()->requestSaveCurrentState(); | 3691 | MainDlg::self()->requestSaveCurrentState(); | ||
3686 | 3692 | | |||
3687 | drawPlot(); //update all graphs | 3693 | drawPlot(); //update all graphs | ||
3688 | 3694 | | |||
3689 | m_zoomMode = Normal; | 3695 | m_zoomMode = Normal; | ||
3690 | } | 3696 | } | ||
3691 | 3697 | | |||
3698 | const QRectF View::getViewport() | ||||
3699 | { | ||||
3700 | return m_animateZoomRect; | ||||
3701 | } | ||||
3702 | | ||||
3703 | void View::setViewport( const QRectF & rect ) | ||||
3704 | { | ||||
3705 | m_animateZoomRect = rect; | ||||
3706 | repaint(); | ||||
3707 | } | ||||
3708 | | ||||
3692 | 3709 | | |||
tcanabrava: old style connect. | |||||
3693 | void View::translateView( int dx, int dy ) | 3710 | void View::translateView( int dx, int dy ) | ||
3694 | { | 3711 | { | ||
3695 | double rdx = xToReal( dx ) - xToReal( 0.0 ); | 3712 | double rdx = xToReal( dx ) - xToReal( 0.0 ); | ||
It seems that you are interpolating by hand, why don't you try to use something like a QEasingCurve + a QPropertyAnimation? tcanabrava: It seems that you are interpolating by hand, why don't you try to use something like a… | |||||
Because switching to QPropertyAnimation cannot be done without complete rewriting half of KmPlot classes and breaks the whole current structure. There should be implemented some property of View to hold the current viewport to tie it up with QPropertyAnimation, then it should be connected with some timer and updates, and maybe other things, I'm not a skilled Qt programmer... It is easy to use QEasingCurve and QPropertyAnimation when the widget is ready for this. View is a different thing now. It might be the stunning implementation with 6 lines, but it is impossible now. The proposed patch just works. People wanted this for more than 10 years (21 votes). Sorry. yurchor: Because switching to QPropertyAnimation cannot be done without complete rewriting half of… | |||||
3696 | double rdy = yToReal( dy ) - yToReal( 0.0 ); | 3713 | double rdy = yToReal( dy ) - yToReal( 0.0 ); | ||
3697 | 3714 | | |||
3698 | m_xmin += rdx; | 3715 | m_xmin += rdx; | ||
3699 | m_xmax += rdx; | 3716 | m_xmax += rdx; | ||
3700 | m_ymin += rdy; | 3717 | m_ymin += rdy; | ||
3701 | m_ymax += rdy; | 3718 | m_ymax += rdy; | ||
3702 | 3719 | | |||
3703 | Settings::setXMin( Parser::number( m_xmin ) ); | 3720 | Settings::setXMin( Parser::number( m_xmin ) ); | ||
▲ Show 20 Lines • Show All 541 Lines • Show Last 20 Lines |
You may want to accumulate the deltas, some touchpads send lots of events with very small deltas, so just doing >0 and <0 can make it very difficult to control, see https://cgit.kde.org/okular.git/commit/?id=7a50ce0edfc9be8bd23441e52a4f3a0c60f7e60f