reworked the functions that allow to specify how JKQTPlotter reacts to mouse single-click actions

This commit is contained in:
Jan W. Krieger 2019-01-27 23:24:12 +01:00
parent dabc061de9
commit 75d8fc8314
5 changed files with 377 additions and 227 deletions

View File

@ -97,20 +97,59 @@ TestUserInteraction::TestUserInteraction(QWidget *parent) :
connect(chkZoomByMouseWheel, SIGNAL(toggled(bool)), plot, SLOT(setZoomByMouseWheel(bool))); connect(chkZoomByMouseWheel, SIGNAL(toggled(bool)), plot, SLOT(setZoomByMouseWheel(bool)));
// add a QComboBox that allows to set the left mouse button action for the JKQTPlotter // add a QComboBox that allows to set the left mouse button action for the JKQTPlotter
cmbMouseAction=new QComboBox(this); cmbLeftNoModMouseAction=new QComboBox(this);
layForm->addRow("mouse action:", cmbMouseAction); layForm->addRow("mouse action: left-click, no modifiers", cmbLeftNoModMouseAction);
cmbMouseAction->addItem("NoMouseAction"); cmbLeftNoModMouseAction->addItem("PanPlotOnMove");
cmbMouseAction->addItem("PanPlotOnMove"); cmbLeftNoModMouseAction->addItem("PanPlotOnRelease");
cmbMouseAction->addItem("PanPlotOnRelease"); cmbLeftNoModMouseAction->addItem("ZoomRectangle");
cmbMouseAction->addItem("ZoomRectangle"); cmbLeftNoModMouseAction->addItem("RectangleEvents");
cmbMouseAction->addItem("RectangleEvents"); cmbLeftNoModMouseAction->addItem("CircleEvents");
cmbMouseAction->addItem("CircleEvents"); cmbLeftNoModMouseAction->addItem("EllipseEvents");
cmbMouseAction->addItem("EllipseEvents"); cmbLeftNoModMouseAction->addItem("LineEvents");
cmbMouseAction->addItem("LineEvents"); cmbLeftNoModMouseAction->addItem("ScribbleEvents");
cmbMouseAction->addItem("ScribbleEvents"); cmbLeftNoModMouseAction->addItem("NoMouseAction");
cmbMouseAction->addItem("ClickEvents"); cmbLeftNoModMouseAction->setCurrentIndex(2);
connect(cmbMouseAction, SIGNAL(currentIndexChanged(int)), this, SLOT(setLeftMouseAction(int))); connect(cmbLeftNoModMouseAction, SIGNAL(currentIndexChanged(int)), this, SLOT(setLeftMouseAction(int)));
setLeftMouseAction(cmbMouseAction->currentIndex()); setLeftMouseAction(cmbLeftNoModMouseAction->currentIndex());
// add a QComboBox that allows to set the left mouse button action for the JKQTPlotter
cmbLeftCtrlModMouseAction=new QComboBox(this);
layForm->addRow("mouse action: left-click, Ctrl modifier", cmbLeftCtrlModMouseAction);
cmbLeftCtrlModMouseAction->addItem("PanPlotOnMove");
cmbLeftCtrlModMouseAction->addItem("PanPlotOnRelease");
cmbLeftCtrlModMouseAction->addItem("ZoomRectangle");
cmbLeftCtrlModMouseAction->addItem("RectangleEvents");
cmbLeftCtrlModMouseAction->addItem("CircleEvents");
cmbLeftCtrlModMouseAction->addItem("EllipseEvents");
cmbLeftCtrlModMouseAction->addItem("LineEvents");
cmbLeftCtrlModMouseAction->addItem("ScribbleEvents");
cmbLeftCtrlModMouseAction->addItem("NoMouseAction");
cmbLeftCtrlModMouseAction->setCurrentIndex(0);
connect(cmbLeftCtrlModMouseAction, SIGNAL(currentIndexChanged(int)), this, SLOT(setLeftCtrlMouseAction(int)));
setLeftCtrlMouseAction(cmbLeftCtrlModMouseAction->currentIndex());
// add a QComboBox that allows to set the left mouse button action for the JKQTPlotter
cmbRightNoModMouseAction=new QComboBox(this);
layForm->addRow("mouse action: right-click, no modifiers", cmbRightNoModMouseAction);
cmbRightNoModMouseAction->addItem("PanPlotOnMove");
cmbRightNoModMouseAction->addItem("PanPlotOnRelease");
cmbRightNoModMouseAction->addItem("ZoomRectangle");
cmbRightNoModMouseAction->addItem("RectangleEvents");
cmbRightNoModMouseAction->addItem("CircleEvents");
cmbRightNoModMouseAction->addItem("EllipseEvents");
cmbRightNoModMouseAction->addItem("LineEvents");
cmbRightNoModMouseAction->addItem("ScribbleEvents");
cmbRightNoModMouseAction->addItem("ContextMenu");
cmbRightNoModMouseAction->setCurrentIndex(5);
connect(cmbRightNoModMouseAction, SIGNAL(currentIndexChanged(int)), this, SLOT(setRightMouseAction(int)));
setRightMouseAction(cmbRightNoModMouseAction->currentIndex());
// add a QComboBox that allows to set whether the right mouse button may show the context menu on a single click
chkRightClickShowsContextMenu=new QCheckBox(this);
chkRightClickShowsContextMenu->setChecked(plot->isRightClickShowsContextMenuEnabled());
layForm->addRow("mouse action: right-click shows context menu:", chkRightClickShowsContextMenu);
connect(chkRightClickShowsContextMenu, SIGNAL(toggled(bool)), plot, SLOT(enableRightClickShowsContextMenu(bool)));
// and add a QLabel to show the different events of the JKQTPlotter: // and add a QLabel to show the different events of the JKQTPlotter:
labMouseMoved=new QLabel(this); labMouseMoved=new QLabel(this);
layForm->addRow("last mouse moved:", labMouseMoved); layForm->addRow("last mouse moved:", labMouseMoved);
@ -124,7 +163,6 @@ TestUserInteraction::TestUserInteraction(QWidget *parent) :
connect(plot, SIGNAL(plotNewZoomRectangle(double, double, double, double, Qt::KeyboardModifiers)), this, SLOT(plotNewZoomRectangle(double, double, double, double, Qt::KeyboardModifiers))); connect(plot, SIGNAL(plotNewZoomRectangle(double, double, double, double, Qt::KeyboardModifiers)), this, SLOT(plotNewZoomRectangle(double, double, double, double, Qt::KeyboardModifiers)));
connect(plot, SIGNAL(contextMenuOpened(double, double, QMenu*)), this, SLOT(contextMenuOpened(double, double, QMenu*))); connect(plot, SIGNAL(contextMenuOpened(double, double, QMenu*)), this, SLOT(contextMenuOpened(double, double, QMenu*)));
connect(plot, SIGNAL(zoomChangedLocally(double, double, double, double, JKQTPlotter*)), this, SLOT(zoomChangedLocally(double, double, double, double, JKQTPlotter*))); connect(plot, SIGNAL(zoomChangedLocally(double, double, double, double, JKQTPlotter*)), this, SLOT(zoomChangedLocally(double, double, double, double, JKQTPlotter*)));
connect(plot, SIGNAL(userClickFinished(double, double, Qt::KeyboardModifiers)), this, SLOT(userClickFinished(double, double, Qt::KeyboardModifiers)));
connect(plot, SIGNAL(userScribbleClick(double, double, Qt::KeyboardModifiers, bool, bool)), this, SLOT(userScribbleClick(double, double, Qt::KeyboardModifiers, bool, bool))); connect(plot, SIGNAL(userScribbleClick(double, double, Qt::KeyboardModifiers, bool, bool)), this, SLOT(userScribbleClick(double, double, Qt::KeyboardModifiers, bool, bool)));
connect(plot, SIGNAL(userRectangleFinished(double, double, double, double, Qt::KeyboardModifiers)), this, SLOT(userRectangleFinished(double, double, double, double, Qt::KeyboardModifiers))); connect(plot, SIGNAL(userRectangleFinished(double, double, double, double, Qt::KeyboardModifiers)), this, SLOT(userRectangleFinished(double, double, double, double, Qt::KeyboardModifiers)));
connect(plot, SIGNAL(userLineFinished(double, double, double, double, Qt::KeyboardModifiers)), this, SLOT(userLineFinished(double, double, double, double, Qt::KeyboardModifiers))); connect(plot, SIGNAL(userLineFinished(double, double, double, double, Qt::KeyboardModifiers)), this, SLOT(userLineFinished(double, double, double, double, Qt::KeyboardModifiers)));
@ -138,7 +176,20 @@ TestUserInteraction::TestUserInteraction(QWidget *parent) :
void TestUserInteraction::setLeftMouseAction(int index) void TestUserInteraction::setLeftMouseAction(int index)
{ {
plot->setMouseActionMode(static_cast<JKQTPlotter::MouseActionModes>(index)); if (index==cmbLeftNoModMouseAction->count()-1) plot->deregisterMouseDragAction(Qt::LeftButton, Qt::NoModifier);
else plot->registerMouseDragAction(Qt::LeftButton, Qt::NoModifier, static_cast<JKQTPlotter::MouseActionMode>(index));
}
void TestUserInteraction::setLeftCtrlMouseAction(int index)
{
if (index==cmbLeftCtrlModMouseAction->count()-1) plot->deregisterMouseDragAction(Qt::LeftButton, Qt::ControlModifier);
else plot->registerMouseDragAction(Qt::LeftButton, Qt::ControlModifier, static_cast<JKQTPlotter::MouseActionMode>(index));
}
void TestUserInteraction::setRightMouseAction(int index)
{
if (index==cmbRightNoModMouseAction->count()-1) plot->deregisterMouseDragAction(Qt::RightButton, Qt::NoModifier);
else plot->registerMouseDragAction(Qt::RightButton, Qt::NoModifier, static_cast<JKQTPlotter::MouseActionMode>(index));
} }
void TestUserInteraction::setPlotMagnification(int index) void TestUserInteraction::setPlotMagnification(int index)
@ -182,11 +233,6 @@ void TestUserInteraction::zoomChangedLocally(double newxmin, double newxmax, dou
labMouseAction->setText(QString("zoomChangedLocally(x=%1..%2, y=%3..%4)").arg(newxmin).arg(newxmax).arg(newymin).arg(newymax)); labMouseAction->setText(QString("zoomChangedLocally(x=%1..%2, y=%3..%4)").arg(newxmin).arg(newxmax).arg(newymin).arg(newymax));
} }
void TestUserInteraction::userClickFinished(double x, double y, Qt::KeyboardModifiers modifiers)
{
labMouseAction->setText(QString("userClickFinished(%1, %2, modifiers=%3)").arg(x).arg(y).arg(KeyboradMod2String(modifiers)));
}
void TestUserInteraction::userScribbleClick(double x, double y, Qt::KeyboardModifiers modifiers, bool first, bool last) void TestUserInteraction::userScribbleClick(double x, double y, Qt::KeyboardModifiers modifiers, bool first, bool last)
{ {
static int counter=0; static int counter=0;
@ -207,12 +253,12 @@ void TestUserInteraction::userLineFinished(double x1, double y1, double x2, doub
void TestUserInteraction::userCircleFinished(double x, double y, double radius, Qt::KeyboardModifiers modifiers) void TestUserInteraction::userCircleFinished(double x, double y, double radius, Qt::KeyboardModifiers modifiers)
{ {
labMouseAction->setText(QString("userRectangleFinished(x=%1, y=%2, radius=%3, modifiers=%4)").arg(x).arg(y).arg(radius).arg(KeyboradMod2String(modifiers))); labMouseAction->setText(QString("userCircleFinished(x=%1, y=%2, radius=%3, modifiers=%4)").arg(x).arg(y).arg(radius).arg(KeyboradMod2String(modifiers)));
} }
void TestUserInteraction::userEllipseFinished(double x, double y, double radiusX, double radiusY, Qt::KeyboardModifiers modifiers) void TestUserInteraction::userEllipseFinished(double x, double y, double radiusX, double radiusY, Qt::KeyboardModifiers modifiers)
{ {
labMouseAction->setText(QString("userRectangleFinished(x=%1, y=%2, radiusX=%3, radiusY=%4, modifiers=%5)").arg(x).arg(y).arg(radiusX).arg(radiusY).arg(KeyboradMod2String(modifiers))); labMouseAction->setText(QString("userEllipseFinished(x=%1, y=%2, radiusX=%3, radiusY=%4, modifiers=%5)").arg(x).arg(y).arg(radiusX).arg(radiusY).arg(KeyboradMod2String(modifiers)));
} }
QString TestUserInteraction::KeyboradMod2String(Qt::KeyboardModifiers modifiers) { QString TestUserInteraction::KeyboradMod2String(Qt::KeyboardModifiers modifiers) {

View File

@ -22,6 +22,8 @@ class TestUserInteraction : public QMainWindow
public slots: public slots:
void setLeftMouseAction(int index); void setLeftMouseAction(int index);
void setLeftCtrlMouseAction(int index);
void setRightMouseAction(int index);
void setPlotMagnification(int index); void setPlotMagnification(int index);
void plotMouseMove(double x, double y); void plotMouseMove(double x, double y);
@ -30,7 +32,6 @@ class TestUserInteraction : public QMainWindow
void plotNewZoomRectangle(double mouseDragRectXStart, double mouseDragRectXEnd, double mouseDragRectYStart, double mouseDragRectYEnd, Qt::KeyboardModifiers modifiers); void plotNewZoomRectangle(double mouseDragRectXStart, double mouseDragRectXEnd, double mouseDragRectYStart, double mouseDragRectYEnd, Qt::KeyboardModifiers modifiers);
void contextMenuOpened(double x, double y, QMenu* contextMenu); void contextMenuOpened(double x, double y, QMenu* contextMenu);
void zoomChangedLocally(double newxmin, double newxmax, double newymin, double newymax, JKQTPlotter* sender); void zoomChangedLocally(double newxmin, double newxmax, double newymin, double newymax, JKQTPlotter* sender);
void userClickFinished(double x, double y, Qt::KeyboardModifiers modifiers);
void userScribbleClick(double x, double y, Qt::KeyboardModifiers modifiers, bool first, bool last); void userScribbleClick(double x, double y, Qt::KeyboardModifiers modifiers, bool first, bool last);
void userRectangleFinished(double x, double y, double width, double height, Qt::KeyboardModifiers modifiers); void userRectangleFinished(double x, double y, double width, double height, Qt::KeyboardModifiers modifiers);
void userLineFinished(double x1, double y1, double x2, double y2, Qt::KeyboardModifiers modifiers); void userLineFinished(double x1, double y1, double x2, double y2, Qt::KeyboardModifiers modifiers);
@ -47,7 +48,10 @@ class TestUserInteraction : public QMainWindow
QCheckBox* chkShowToolbar; QCheckBox* chkShowToolbar;
QCheckBox* chkToolbarAlwaysOn; QCheckBox* chkToolbarAlwaysOn;
QCheckBox* chkGrid; QCheckBox* chkGrid;
QComboBox* cmbMouseAction; QComboBox* cmbLeftNoModMouseAction;
QComboBox* cmbLeftCtrlModMouseAction;
QComboBox* cmbRightNoModMouseAction;
QCheckBox* chkRightClickShowsContextMenu;
QCheckBox* chkLogX; QCheckBox* chkLogX;
QCheckBox* chkLogY; QCheckBox* chkLogY;
QCheckBox* chkZoomByMouseWheel; QCheckBox* chkZoomByMouseWheel;

View File

@ -3390,10 +3390,10 @@ void JKQTMathText::useXITS()
//fontSans=fam; //fontSans=fam;
fontMathRoman=fam; fontMathRoman=fam;
fontMathSans=fam; fontMathSans=fam;
fontTypewriter=fam; //fontTypewriter=fam;
fontBlackboard=fam; fontBlackboard=fam;
fontCaligraphic=fam; //fontCaligraphic=fam;
fontScript=fam; //fontScript=fam;
fontBraces=fam; fontBraces=fam;
fontSymbol=fam; fontSymbol=fam;
fontGreek=fam; fontGreek=fam;

View File

@ -106,8 +106,10 @@ void JKQTPlotter::init(bool datastore_internal, QWidget* parent, JKQTPDatastore*
displayMousePosition=true; displayMousePosition=true;
displayToolbar=true; displayToolbar=true;
toolbarAlwaysOn=false; toolbarAlwaysOn=false;
mouseActionMode=JKQTPlotter::ZoomRectangle; rightClickShowsContextMenu=true;
//zoomByDoubleAndRightMouseClick=true; registerMouseDragAction(Qt::LeftButton, Qt::NoModifier, MouseActionMode::ZoomRectangle);
registerMouseDragAction(Qt::LeftButton, Qt::ControlModifier, MouseActionMode::PanPlotOnMove);
zoomByMouseWheel=true; zoomByMouseWheel=true;
setMouseTracking(true); setMouseTracking(true);
@ -231,18 +233,6 @@ QPainter::CompositionMode JKQTPlotter::getUserActionCompositionMode() const
return this->userActionCompositionMode; return this->userActionCompositionMode;
} }
void JKQTPlotter::setMouseActionMode(const JKQTPlotter::MouseActionModes &__value)
{
if (this->mouseActionMode != __value) {
this->mouseActionMode = __value;
updateCursor();
}
}
JKQTPlotter::MouseActionModes JKQTPlotter::getMouseActionMode() const
{
return this->mouseActionMode;
}
void JKQTPlotter::loadSettings(const QSettings& settings, const QString& group) { void JKQTPlotter::loadSettings(const QSettings& settings, const QString& group) {
plotter->loadSettings(settings, group); plotter->loadSettings(settings, group);
@ -265,7 +255,7 @@ void JKQTPlotter::saveSettings(QSettings& settings, const QString& group) const
void JKQTPlotter::paintUserAction() { void JKQTPlotter::paintUserAction() {
if (mouseDragingRectangle) { if (currentMouseDragAction.isValid() && mouseDragingRectangle) {
image=oldImage; image=oldImage;
if (image.width()>0 && image.height()>0 && !image.isNull()) { if (image.width()>0 && image.height()>0 && !image.isNull()) {
JKQTPEnhancedPainter painter(&image); JKQTPEnhancedPainter painter(&image);
@ -283,22 +273,22 @@ void JKQTPlotter::paintUserAction() {
double y2=plotter->y2p(mouseDragRectYEnd)*magnification; double y2=plotter->y2p(mouseDragRectYEnd)*magnification;
double dx=x2-x1; double dx=x2-x1;
double dy=y2-y1; double dy=y2-y1;
if ((mouseActionMode==JKQTPlotter::ZoomRectangle) || (mouseActionMode==JKQTPlotter::RectangleEvents)) { if ((currentMouseDragAction.mode==JKQTPlotter::ZoomRectangle) || (currentMouseDragAction.mode==JKQTPlotter::RectangleEvents)) {
painter.setOpacity(0.2); painter.setOpacity(0.2);
painter.fillRect(QRectF(x1, y1, x2-x1, y2-y1), QBrush(userActionColor)); painter.fillRect(QRectF(x1, y1, x2-x1, y2-y1), QBrush(userActionColor));
painter.setOpacity(1.0); painter.setOpacity(1.0);
painter.drawRect(QRectF(x1, y1, x2-x1, y2-y1)); painter.drawRect(QRectF(x1, y1, x2-x1, y2-y1));
} else if (mouseActionMode==JKQTPlotter::CircleEvents) { } else if (currentMouseDragAction.mode==JKQTPlotter::CircleEvents) {
QColor zc=userActionColor; QColor zc=userActionColor;
zc.setAlphaF(0.2); zc.setAlphaF(0.2);
painter.setBrush(QBrush(zc)); painter.setBrush(QBrush(zc));
painter.drawEllipse(QPointF(x1, y1), qMin(fabs(dx), fabs(dy)), qMin(fabs(dx), fabs(dy))); painter.drawEllipse(QPointF(x1, y1), qMin(fabs(dx), fabs(dy)), qMin(fabs(dx), fabs(dy)));
} else if (mouseActionMode==JKQTPlotter::EllipseEvents) { } else if (currentMouseDragAction.mode==JKQTPlotter::EllipseEvents) {
QColor zc=userActionColor; QColor zc=userActionColor;
zc.setAlphaF(0.2); zc.setAlphaF(0.2);
painter.setBrush(QBrush(zc)); painter.setBrush(QBrush(zc));
painter.drawEllipse(QPointF(x1, y1), fabs(dx), fabs(dy)); painter.drawEllipse(QPointF(x1, y1), fabs(dx), fabs(dy));
} else if (mouseActionMode==JKQTPlotter::LineEvents) { } else if (currentMouseDragAction.mode==JKQTPlotter::LineEvents) {
QPen pp=p; QPen pp=p;
pp.setColor(userActionColor); pp.setColor(userActionColor);
painter.setPen(pp); painter.setPen(pp);
@ -329,17 +319,18 @@ void JKQTPlotter::mouseMoveEvent ( QMouseEvent * event ) {
if (!displayToolbar) { if (!displayToolbar) {
toolbar->hide(); toolbar->hide();
} }
if (( (mouseActionMode==JKQTPlotter::ZoomRectangle) || if (currentMouseDragAction.isValid()) {
(mouseActionMode==JKQTPlotter::RectangleEvents) || if (( (currentMouseDragAction.mode==JKQTPlotter::ZoomRectangle) ||
(mouseActionMode==JKQTPlotter::CircleEvents) || (currentMouseDragAction.mode==JKQTPlotter::RectangleEvents) ||
(mouseActionMode==JKQTPlotter::EllipseEvents) || (currentMouseDragAction.mode==JKQTPlotter::CircleEvents) ||
(mouseActionMode==JKQTPlotter::ScribbleEvents) || (currentMouseDragAction.mode==JKQTPlotter::EllipseEvents) ||
(mouseActionMode==JKQTPlotter::PanPlotOnMove) || (currentMouseDragAction.mode==JKQTPlotter::ScribbleEvents) ||
(mouseActionMode==JKQTPlotter::PanPlotOnRelease) || (currentMouseDragAction.mode==JKQTPlotter::PanPlotOnMove) ||
(mouseActionMode==JKQTPlotter::LineEvents) ) && (currentMouseDragAction.mode==JKQTPlotter::PanPlotOnRelease) ||
mouseDragingRectangle && (event->buttons() & Qt::LeftButton)) (currentMouseDragAction.mode==JKQTPlotter::LineEvents) ) &&
mouseDragingRectangle)
{ {
if (mouseActionMode==JKQTPlotter::ScribbleEvents || mouseActionMode==JKQTPlotter::PanPlotOnMove) { if (currentMouseDragAction.mode==JKQTPlotter::ScribbleEvents || currentMouseDragAction.mode==JKQTPlotter::PanPlotOnMove) {
// start is last event position // start is last event position
mouseDragRectXStart=mouseDragRectXEnd; mouseDragRectXStart=mouseDragRectXEnd;
mouseDragRectYStart=mouseDragRectYEnd; mouseDragRectYStart=mouseDragRectYEnd;
@ -353,13 +344,13 @@ void JKQTPlotter::mouseMoveEvent ( QMouseEvent * event ) {
paintUserAction(); paintUserAction();
event->accept(); event->accept();
//std::cout<<mouseZoomingTStart<<" -- "<<mouseZoomingTEnd<<std::endl; //std::cout<<mouseZoomingTStart<<" -- "<<mouseZoomingTEnd<<std::endl;
if (mouseActionMode==JKQTPlotter::ZoomRectangle) { if (currentMouseDragAction.mode==JKQTPlotter::ZoomRectangle) {
emit plotNewZoomRectangle(mouseDragRectXStart, mouseDragRectXEnd, mouseDragRectYStart, mouseDragRectYEnd, event->modifiers()); emit plotNewZoomRectangle(mouseDragRectXStart, mouseDragRectXEnd, mouseDragRectYStart, mouseDragRectYEnd, event->modifiers());
} }
if ((mouseActionMode==JKQTPlotter::ScribbleEvents) && ((mouseDragRectXStart!=mouseDragRectXEnd) || (mouseDragRectYStart!=mouseDragRectYEnd)) ) { if ((currentMouseDragAction.mode==JKQTPlotter::ScribbleEvents) && ((mouseDragRectXStart!=mouseDragRectXEnd) || (mouseDragRectYStart!=mouseDragRectYEnd)) ) {
emit userScribbleClick(mouseDragRectXEnd, mouseDragRectYEnd, event->modifiers(), false, false); emit userScribbleClick(mouseDragRectXEnd, mouseDragRectYEnd, event->modifiers(), false, false);
} }
if ((mouseActionMode==JKQTPlotter::PanPlotOnMove) && ((mouseDragRectXStart!=mouseDragRectXEnd) || (mouseDragRectYStart!=mouseDragRectYEnd)) ) { if ((currentMouseDragAction.mode==JKQTPlotter::PanPlotOnMove) && ((mouseDragRectXStart!=mouseDragRectXEnd) || (mouseDragRectYStart!=mouseDragRectYEnd)) ) {
QRectF zoomRect= QRectF(QPointF(plotter->x2p(getXAxis()->getMin()),plotter->y2p(getYAxis()->getMax())), QPointF(plotter->x2p(getXAxis()->getMax()),plotter->y2p(getYAxis()->getMin()))); QRectF zoomRect= QRectF(QPointF(plotter->x2p(getXAxis()->getMin()),plotter->y2p(getYAxis()->getMax())), QPointF(plotter->x2p(getXAxis()->getMax()),plotter->y2p(getYAxis()->getMin())));
if ( (mouseLastClickX/magnification<plotter->getInternalPlotBorderLeft()) || (mouseLastClickX/magnification>plotter->getPlotWidth()+plotter->getInternalPlotBorderLeft()) ) { if ( (mouseLastClickX/magnification<plotter->getInternalPlotBorderLeft()) || (mouseLastClickX/magnification>plotter->getPlotWidth()+plotter->getInternalPlotBorderLeft()) ) {
zoomRect.translate(0, mouseDragRectYStartPixel-mouseDragRectYEndPixel); zoomRect.translate(0, mouseDragRectYStartPixel-mouseDragRectYEndPixel);
@ -374,61 +365,42 @@ void JKQTPlotter::mouseMoveEvent ( QMouseEvent * event ) {
event->accept(); event->accept();
/*if (emitSignals)*/ //emit plotMouseMove(x, y); /*if (emitSignals)*/ //emit plotMouseMove(x, y);
} }
}
// emit clicked signal, if event occured inside plot only // emit clicked signal, if event occured inside plot only
if ( (event->x()/magnification>=plotter->getInternalPlotBorderLeft()) && (event->x()/magnification<=plotter->getPlotWidth()+plotter->getInternalPlotBorderLeft()) && if ( (event->x()/magnification>=plotter->getInternalPlotBorderLeft()) && (event->x()/magnification<=plotter->getPlotWidth()+plotter->getInternalPlotBorderLeft()) &&
((event->y()-getPlotYOffset())/magnification>=plotter->getInternalPlotBorderTop()) && ((event->y()-getPlotYOffset())/magnification<=plotter->getPlotHeight()+plotter->getInternalPlotBorderTop()) ) { ((event->y()-getPlotYOffset())/magnification>=plotter->getInternalPlotBorderTop()) && ((event->y()-getPlotYOffset())/magnification<=plotter->getPlotHeight()+plotter->getInternalPlotBorderTop()) ) {
emit plotMouseMove(plotter->p2x(event->x()/magnification), plotter->p2y((event->y()-getPlotYOffset())/magnification)); emit plotMouseMove(plotter->p2x(event->x()/magnification), plotter->p2y((event->y()-getPlotYOffset())/magnification));
} }
updateCursor();
} }
void JKQTPlotter::mousePressEvent ( QMouseEvent * event ){ void JKQTPlotter::mousePressEvent ( QMouseEvent * event ){
if (event->button()==Qt::LeftButton) { currentMouseDragAction.clear();
auto actionIT=findMatchingMouseDragAction(event->button(), event->modifiers());
if (actionIT!=registeredMouseActionModes.end()) {
// we found a matching action
currentMouseDragAction=MouseDragAction(actionIT.key().first, actionIT.key().second, actionIT.value());
mouseLastClickX=event->x(); mouseLastClickX=event->x();
mouseLastClickY=event->y(); mouseLastClickY=event->y();
if ( (mouseActionMode!=JKQTPlotter::NoMouseAction))
{
mouseDragRectXStart=plotter->p2x(event->x()/magnification); mouseDragRectXStart=plotter->p2x(event->x()/magnification);
mouseDragRectYStart=plotter->p2y((event->y()-getPlotYOffset())/magnification); mouseDragRectYStart=plotter->p2y((event->y()-getPlotYOffset())/magnification);
mouseDragRectXEndPixel=mouseDragRectXStartPixel=event->x(); mouseDragRectXEndPixel=mouseDragRectXStartPixel=event->x();
mouseDragRectYEndPixel=mouseDragRectYStartPixel=event->y(); mouseDragRectYEndPixel=mouseDragRectYStartPixel=event->y();
mouseDragingRectangle=true; mouseDragingRectangle=true;
oldImage=image; oldImage=image;
if (currentMouseDragAction.mode==JKQTPlotter::ScribbleEvents) emit userScribbleClick(mouseDragRectXStart, mouseDragRectYStart, event->modifiers(), true, false);
event->accept(); event->accept();
if (mouseActionMode==JKQTPlotter::ScribbleEvents) emit userScribbleClick(mouseDragRectXStart, mouseDragRectYStart, event->modifiers(), true, false); } else if (event->button()==Qt::RightButton && event->modifiers()==Qt::NoModifier && rightClickShowsContextMenu) {
if (mouseActionMode==JKQTPlotter::ClickEvents) emit userClickFinished(mouseDragRectXStart, mouseDragRectYStart, event->modifiers());
}
} else if (event->button()==Qt::RightButton) {
mouseLastClickX=event->x(); mouseLastClickX=event->x();
mouseLastClickY=event->y(); mouseLastClickY=event->y();
if (rightMouseButtonAction==JKQTPlotter::RightMouseButtonZoom) {
double xmin=plotter->p2x((long)round(static_cast<double>(plotter->getInternalPlotBorderLeft())-static_cast<double>(plotter->getPlotWidth())/2.0));
double xmax=plotter->p2x((long)round(static_cast<double>(plotter->getInternalPlotBorderLeft())+1.5*static_cast<double>(plotter->getPlotWidth())));
double ymin=plotter->p2y((long)round(static_cast<double>(plotter->getInternalPlotBorderTop())+1.5*static_cast<double>(plotter->getPlotHeight())));
double ymax=plotter->p2y((long)round(static_cast<double>(plotter->getInternalPlotBorderTop())-static_cast<double>(plotter->getPlotHeight())/2.0));
if (plotter->getXAxis()->isLogAxis()) {
if (xmin<=0) xmin=1;
if (xmax<=0) xmax=10;
}
if (plotter->getYAxis()->isLogAxis()) {
if (ymin<=0) ymin=1;
if (ymax<=0) ymax=10;
}
/*plotter->getXAxis->setRange(xmin, xmax);
plotter->getYAxis->setRange(ymin, ymax);*/
//redrawPlot();
/*if (plotter->isEmittingSignalsEnabled())*/ emit zoomChangedLocally(xmin, xmax, ymin, ymax, this);
plotter->setXY(xmin, xmax, ymin, ymax);
//update();
event->accept();
} else if (rightMouseButtonAction==JKQTPlotter::RightMouseButtonContextMenu) {
openContextMenu(event->x(), event->y()); openContextMenu(event->x(), event->y());
event->accept(); event->accept();
} }
}
// emit clicked signal, if event occured inside plot only // emit clicked signal, if event occured inside plot only
if ( (event->x()/magnification>=plotter->getInternalPlotBorderLeft()) && (event->x()/magnification<=plotter->getPlotWidth()+plotter->getInternalPlotBorderLeft()) && if ( (event->x()/magnification>=plotter->getInternalPlotBorderLeft()) && (event->x()/magnification<=plotter->getPlotWidth()+plotter->getInternalPlotBorderLeft()) &&
@ -436,13 +408,14 @@ void JKQTPlotter::mousePressEvent ( QMouseEvent * event ){
emit plotMouseClicked(plotter->p2x(event->x()/magnification), plotter->p2y((event->y()-getPlotYOffset())/magnification), event->modifiers(), event->button()); emit plotMouseClicked(plotter->p2x(event->x()/magnification), plotter->p2y((event->y()-getPlotYOffset())/magnification), event->modifiers(), event->button());
event->accept(); event->accept();
} }
updateCursor();
} }
void JKQTPlotter::mouseReleaseEvent ( QMouseEvent * event ){ void JKQTPlotter::mouseReleaseEvent ( QMouseEvent * event ){
if ((event->flags()&Qt::MouseEventCreatedDoubleClick)==Qt::MouseEventCreatedDoubleClick) { if ((event->flags()&Qt::MouseEventCreatedDoubleClick)==Qt::MouseEventCreatedDoubleClick) {
return; return;
} }
if (mouseDragingRectangle && event->button()==Qt::LeftButton) { if (currentMouseDragAction.isValid()) {
mouseDragRectXEnd=plotter->p2x(event->x()/magnification); mouseDragRectXEnd=plotter->p2x(event->x()/magnification);
mouseDragRectYEnd=plotter->p2y((event->y()-getPlotYOffset())/magnification); mouseDragRectYEnd=plotter->p2y((event->y()-getPlotYOffset())/magnification);
mouseDragRectXEndPixel=event->x(); mouseDragRectXEndPixel=event->x();
@ -458,7 +431,7 @@ void JKQTPlotter::mouseReleaseEvent ( QMouseEvent * event ){
double y2=mouseDragRectYEnd; double y2=mouseDragRectYEnd;
if ((mouseDragRectXStart!=mouseDragRectXEnd) && (mouseDragRectYStart!=mouseDragRectYEnd)) { if ((mouseDragRectXStart!=mouseDragRectXEnd) && (mouseDragRectYStart!=mouseDragRectYEnd)) {
if (mouseActionMode==JKQTPlotter::ZoomRectangle) { if (currentMouseDragAction.mode==JKQTPlotter::ZoomRectangle) {
double xmin=mouseDragRectXStart; double xmin=mouseDragRectXStart;
double xmax=mouseDragRectXEnd; double xmax=mouseDragRectXEnd;
@ -467,7 +440,7 @@ void JKQTPlotter::mouseReleaseEvent ( QMouseEvent * event ){
emit zoomChangedLocally(xmin, xmax, ymin, ymax, this); emit zoomChangedLocally(xmin, xmax, ymin, ymax, this);
plotter->setXY(xmin, xmax, ymin, ymax); plotter->setXY(xmin, xmax, ymin, ymax);
} else if (mouseActionMode==JKQTPlotter::PanPlotOnRelease) { } else if (currentMouseDragAction.mode==JKQTPlotter::PanPlotOnRelease) {
QRectF zoomRect= QRectF(QPointF(plotter->x2p(getXAxis()->getMin()),plotter->y2p(getYAxis()->getMax())), QPointF(plotter->x2p(getXAxis()->getMax()),plotter->y2p(getYAxis()->getMin()))); QRectF zoomRect= QRectF(QPointF(plotter->x2p(getXAxis()->getMin()),plotter->y2p(getYAxis()->getMax())), QPointF(plotter->x2p(getXAxis()->getMax()),plotter->y2p(getYAxis()->getMin())));
if ( (mouseLastClickX/magnification<plotter->getInternalPlotBorderLeft()) || (mouseLastClickX/magnification>plotter->getPlotWidth()+plotter->getInternalPlotBorderLeft()) ) { if ( (mouseLastClickX/magnification<plotter->getInternalPlotBorderLeft()) || (mouseLastClickX/magnification>plotter->getPlotWidth()+plotter->getInternalPlotBorderLeft()) ) {
zoomRect.translate(0, mouseDragRectYStartPixel-mouseDragRectYEndPixel); zoomRect.translate(0, mouseDragRectYStartPixel-mouseDragRectYEndPixel);
@ -477,22 +450,23 @@ void JKQTPlotter::mouseReleaseEvent ( QMouseEvent * event ){
zoomRect.translate(mouseDragRectXStartPixel-mouseDragRectXEndPixel, mouseDragRectYStartPixel-mouseDragRectYEndPixel); zoomRect.translate(mouseDragRectXStartPixel-mouseDragRectXEndPixel, mouseDragRectYStartPixel-mouseDragRectYEndPixel);
} }
setXY(plotter->p2x(zoomRect.left()), plotter->p2x(zoomRect.right()), plotter->p2y(zoomRect.bottom()), plotter->p2y(zoomRect.top())); setXY(plotter->p2x(zoomRect.left()), plotter->p2x(zoomRect.right()), plotter->p2y(zoomRect.bottom()), plotter->p2y(zoomRect.top()));
} else if (mouseActionMode==JKQTPlotter::RectangleEvents) { } else if (currentMouseDragAction.mode==JKQTPlotter::RectangleEvents) {
emit userRectangleFinished(x1, y1, x2-x1, y2-y1, event->modifiers()); emit userRectangleFinished(x1, y1, x2-x1, y2-y1, event->modifiers());
} else if (mouseActionMode==JKQTPlotter::CircleEvents) { } else if (currentMouseDragAction.mode==JKQTPlotter::CircleEvents) {
emit userCircleFinished(x1, y1, qMin(fabs(x2-x1), fabs(y2-y1)), event->modifiers()); emit userCircleFinished(x1, y1, qMin(fabs(x2-x1), fabs(y2-y1)), event->modifiers());
} else if (mouseActionMode==JKQTPlotter::EllipseEvents) { } else if (currentMouseDragAction.mode==JKQTPlotter::EllipseEvents) {
emit userEllipseFinished(x1, y1, fabs(x2-x1), fabs(y2-y1), event->modifiers()); emit userEllipseFinished(x1, y1, fabs(x2-x1), fabs(y2-y1), event->modifiers());
} else if (mouseActionMode==JKQTPlotter::LineEvents) { } else if (currentMouseDragAction.mode==JKQTPlotter::LineEvents) {
emit userLineFinished(x1, y1, x2, y2, event->modifiers()); emit userLineFinished(x1, y1, x2, y2, event->modifiers());
} else if (mouseActionMode==JKQTPlotter::ScribbleEvents) {
emit userScribbleClick(x1, y1, event->modifiers(), false, true);
} }
} }
if (mouseActionMode!=JKQTPlotter::ZoomRectangle) update(); if (currentMouseDragAction.mode!=JKQTPlotter::ZoomRectangle) update();
if (currentMouseDragAction.mode==JKQTPlotter::ScribbleEvents) emit userScribbleClick(x1, y1, event->modifiers(), false, true);
event->accept(); event->accept();
} }
currentMouseDragAction.clear();
updateCursor();
} }
void JKQTPlotter::mouseDoubleClickEvent ( QMouseEvent * event ){ void JKQTPlotter::mouseDoubleClickEvent ( QMouseEvent * event ){
@ -531,18 +505,22 @@ void JKQTPlotter::mouseDoubleClickEvent ( QMouseEvent * event ){
emit plotMouseDoubleClicked(plotter->p2x(event->x()/magnification), plotter->p2y((event->y()-getPlotYOffset())/magnification), event->modifiers(), event->button()); emit plotMouseDoubleClicked(plotter->p2x(event->x()/magnification), plotter->p2y((event->y()-getPlotYOffset())/magnification), event->modifiers(), event->button());
} else { event->ignore(); } } else { event->ignore(); }
updateCursor();
currentMouseDragAction.clear();
} }
void JKQTPlotter::keyReleaseEvent(QKeyEvent *event) { void JKQTPlotter::keyReleaseEvent(QKeyEvent *event) {
QWidget::keyPressEvent(event); QWidget::keyPressEvent(event);
if (event->key()==Qt::Key_Escape && event->modifiers()==Qt::NoModifier) { if (event->key()==Qt::Key_Escape && event->modifiers()==Qt::NoModifier) {
if (mouseDragingRectangle) { if (mouseDragingRectangle || currentMouseDragAction.isValid()) {
mouseDragingRectangle=false; mouseDragingRectangle=false;
image=oldImage; image=oldImage;
currentMouseDragAction.clear();
update(); update();
event->accept(); event->accept();
} }
} }
updateCursor();
} }
void JKQTPlotter::wheelEvent ( QWheelEvent * event ) { void JKQTPlotter::wheelEvent ( QWheelEvent * event ) {
@ -560,6 +538,8 @@ void JKQTPlotter::wheelEvent ( QWheelEvent * event ) {
} else { } else {
event->ignore(); event->ignore();
} }
updateCursor();
currentMouseDragAction.clear();
} }
int JKQTPlotter::getPlotYOffset() { int JKQTPlotter::getPlotYOffset() {
@ -644,38 +624,40 @@ void JKQTPlotter::initContextMenu()
void JKQTPlotter::updateCursor() { void JKQTPlotter::updateCursor() {
if (mouseActionMode==JKQTPlotter::ZoomRectangle) { if (!currentMouseDragAction.isValid()) {
QBitmap cursor(":/JKQTPlotter/jkqtp_cursor_zoom.png"); setCursor(QCursor(Qt::ArrowCursor));
QBitmap mask(":/JKQTPlotter/jkqtp_cursor_zoom_mask.png"); } else {
if (currentMouseDragAction.mode==JKQTPlotter::ZoomRectangle) {
static QBitmap cursor(":/JKQTPlotter/jkqtp_cursor_zoom.png");
static QBitmap mask(":/JKQTPlotter/jkqtp_cursor_zoom_mask.png");
setCursor(QCursor(cursor, mask, 9, 14)); setCursor(QCursor(cursor, mask, 9, 14));
} else if (mouseActionMode==JKQTPlotter::RectangleEvents) { } else if (currentMouseDragAction.mode==JKQTPlotter::RectangleEvents) {
QBitmap cursor(":/JKQTPlotter/jkqtp_cursor_rectangle.png"); static QBitmap cursor(":/JKQTPlotter/jkqtp_cursor_rectangle.png");
QBitmap mask(":/JKQTPlotter/jkqtp_cursor_rectangle_mask.png"); static QBitmap mask(":/JKQTPlotter/jkqtp_cursor_rectangle_mask.png");
setCursor(QCursor(cursor, mask, 9, 14)); setCursor(QCursor(cursor, mask, 9, 14));
} else if (mouseActionMode==JKQTPlotter::PanPlotOnMove || mouseActionMode==JKQTPlotter::PanPlotOnRelease) { } else if (currentMouseDragAction.mode==JKQTPlotter::PanPlotOnMove || currentMouseDragAction.mode==JKQTPlotter::PanPlotOnRelease) {
setCursor(QCursor(Qt::OpenHandCursor)); setCursor(QCursor(Qt::ClosedHandCursor));
} else if (mouseActionMode==JKQTPlotter::CircleEvents) { } else if (currentMouseDragAction.mode==JKQTPlotter::CircleEvents) {
QBitmap cursor(":/JKQTPlotter/jkqtp_cursor_circle.png"); static QBitmap cursor(":/JKQTPlotter/jkqtp_cursor_circle.png");
QBitmap mask(":/JKQTPlotter/jkqtp_cursor_circle_mask.png"); static QBitmap mask(":/JKQTPlotter/jkqtp_cursor_circle_mask.png");
setCursor(QCursor(cursor, mask, 9, 14)); setCursor(QCursor(cursor, mask, 9, 14));
} else if (mouseActionMode==JKQTPlotter::EllipseEvents) { } else if (currentMouseDragAction.mode==JKQTPlotter::EllipseEvents) {
QBitmap cursor(":/JKQTPlotter/jkqtp_cursor_ellipse.png"); static QBitmap cursor(":/JKQTPlotter/jkqtp_cursor_ellipse.png");
QBitmap mask(":/JKQTPlotter/jkqtp_cursor_ellipse_mask.png"); static QBitmap mask(":/JKQTPlotter/jkqtp_cursor_ellipse_mask.png");
setCursor(QCursor(cursor, mask, 9, 14)); setCursor(QCursor(cursor, mask, 9, 14));
} else if (mouseActionMode==JKQTPlotter::LineEvents) { } else if (currentMouseDragAction.mode==JKQTPlotter::LineEvents) {
QBitmap cursor(":/JKQTPlotter/jkqtp_cursor_line.png"); static QBitmap cursor(":/JKQTPlotter/jkqtp_cursor_line.png");
QBitmap mask(":/JKQTPlotter/jkqtp_cursor_line_mask.png"); static QBitmap mask(":/JKQTPlotter/jkqtp_cursor_line_mask.png");
setCursor(QCursor(cursor, mask, 9, 14)); setCursor(QCursor(cursor, mask, 9, 14));
} else if (mouseActionMode==JKQTPlotter::ClickEvents) { } else if (currentMouseDragAction.mode==JKQTPlotter::ScribbleEvents) {
setCursor(QCursor(Qt::CrossCursor)); static QBitmap cursor(":/JKQTPlotter/jkqtp_cursor_scribble.png");
} else if (mouseActionMode==JKQTPlotter::ScribbleEvents) { static QBitmap mask(":/JKQTPlotter/jkqtp_cursor_scribble_mask.png");
QBitmap cursor(":/JKQTPlotter/jkqtp_cursor_scribble.png");
QBitmap mask(":/JKQTPlotter/jkqtp_cursor_scribble_mask.png");
setCursor(QCursor(cursor, mask, 9, 14)); setCursor(QCursor(cursor, mask, 9, 14));
} else { } else {
setCursor(QCursor(Qt::ArrowCursor)); setCursor(QCursor(Qt::ArrowCursor));
} }
} }
}
void JKQTPlotter::synchronizeXAxis(double newxmin, double newxmax, double /*newymin*/, double /*newymax*/, JKQTPlotter * /*sender*/) { void JKQTPlotter::synchronizeXAxis(double newxmin, double newxmax, double /*newymin*/, double /*newymax*/, JKQTPlotter * /*sender*/) {
@ -891,16 +873,21 @@ void JKQTPlotter::reactGraphVisible(bool visible)
} }
} }
void JKQTPlotter::setZoomByMouseRectangle(bool zomByrectangle) {
if (zomByrectangle) mouseActionMode=JKQTPlotter::ZoomRectangle;
else mouseActionMode=JKQTPlotter::NoMouseAction;
}
void JKQTPlotter::setRightMouseButtonAction(const JKQTPlotter::RightMouseButtonAction &__value) void JKQTPlotter::setRightMouseButtonAction(const JKQTPlotter::RightMouseButtonAction &__value)
{ {
this->rightMouseButtonAction = __value; this->rightMouseButtonAction = __value;
} }
void JKQTPlotter::enableRightClickShowsContextMenu(bool enabled)
{
this->rightClickShowsContextMenu=enabled;
}
void JKQTPlotter::disableRightClickShowsContextMenu(bool disabled)
{
enableRightClickShowsContextMenu(!disabled);
}
JKQTPlotter::RightMouseButtonAction JKQTPlotter::getActionRightMouseButton() const JKQTPlotter::RightMouseButtonAction JKQTPlotter::getActionRightMouseButton() const
{ {
return this->rightMouseButtonAction; return this->rightMouseButtonAction;
@ -955,16 +942,17 @@ int JKQTPlotter::getMouseLastClickY() const {
return this->mouseLastClickY; return this->mouseLastClickY;
} }
bool JKQTPlotter::isRightClickShowsContextMenuEnabled() const
{
return this->rightClickShowsContextMenu;
}
void JKQTPlotter::setMagnification(double m) void JKQTPlotter::setMagnification(double m)
{ {
magnification=m; magnification=m;
redrawPlot(); redrawPlot();
} }
bool JKQTPlotter::getZoomByMouseRectangle() const {
return (mouseActionMode==JKQTPlotter::ZoomRectangle);
}
void JKQTPlotter::modifyContextMenu(QMenu * /*menu*/) void JKQTPlotter::modifyContextMenu(QMenu * /*menu*/)
{ {
} }
@ -1034,6 +1022,27 @@ void JKQTPlotter::openSpecialContextMenu(int x, int y)
} }
} }
QHash<QPair<Qt::MouseButton,Qt::KeyboardModifier>, JKQTPlotter::MouseActionMode>::const_iterator JKQTPlotter::findMatchingMouseDragAction(Qt::MouseButton button, Qt::KeyboardModifiers modifiers) const
{
if (modifiers.testFlag(Qt::ShiftModifier)) {
return registeredMouseActionModes.find(qMakePair<Qt::MouseButton, Qt::KeyboardModifier>(button, Qt::ShiftModifier));
} else if (modifiers.testFlag(Qt::ControlModifier)) {
return registeredMouseActionModes.find(qMakePair<Qt::MouseButton, Qt::KeyboardModifier>(button, Qt::ControlModifier));
} else if (modifiers.testFlag(Qt::AltModifier)) {
return registeredMouseActionModes.find(qMakePair<Qt::MouseButton, Qt::KeyboardModifier>(button, Qt::AltModifier));
} else if (modifiers.testFlag(Qt::MetaModifier)) {
return registeredMouseActionModes.find(qMakePair<Qt::MouseButton, Qt::KeyboardModifier>(button, Qt::MetaModifier));
} else if (modifiers.testFlag(Qt::KeypadModifier)) {
return registeredMouseActionModes.find(qMakePair<Qt::MouseButton, Qt::KeyboardModifier>(button, Qt::KeypadModifier));
} else if (modifiers.testFlag(Qt::GroupSwitchModifier)) {
return registeredMouseActionModes.find(qMakePair<Qt::MouseButton, Qt::KeyboardModifier>(button, Qt::GroupSwitchModifier));
} else {
return registeredMouseActionModes.find(qMakePair<Qt::MouseButton, Qt::KeyboardModifier>(button, Qt::NoModifier));
}
return registeredMouseActionModes.end();
}
void JKQTPlotter::setPlotUpdateEnabled(bool enable) void JKQTPlotter::setPlotUpdateEnabled(bool enable)
{ {
@ -1042,8 +1051,47 @@ void JKQTPlotter::setPlotUpdateEnabled(bool enable)
//qDebug()<<objectName()<<" doDrawing="<<doDrawing; //qDebug()<<objectName()<<" doDrawing="<<doDrawing;
} }
void JKQTPlotter::registerMouseDragAction(Qt::MouseButton button, Qt::KeyboardModifier modifier, JKQTPlotter::MouseActionMode action)
{
registeredMouseActionModes[qMakePair<Qt::MouseButton, Qt::KeyboardModifier>(button, modifier)]=action;
}
void JKQTPlotter::deregisterMouseDragAction(Qt::MouseButton button, Qt::KeyboardModifier modifier)
{
registeredMouseActionModes.remove(qMakePair<Qt::MouseButton, Qt::KeyboardModifier>(button, modifier));
}
void JKQTPlotter::clearAllRegisteredMouseDragActions()
{
registeredMouseActionModes.clear();
}
void initJKQTPlotterResources() void initJKQTPlotterResources()
{ {
initJKQTBasePlotterResources(); initJKQTBasePlotterResources();
} }
JKQTPlotter::MouseDragAction::MouseDragAction():
mode(ZoomRectangle), modifier(Qt::NoModifier), mouseButton(Qt::LeftButton), valid(false)
{
}
JKQTPlotter::MouseDragAction::MouseDragAction(Qt::MouseButton _mouseButton, Qt::KeyboardModifier _modifier, JKQTPlotter::MouseActionMode _mode):
mode(_mode), modifier(_modifier), mouseButton(_mouseButton), valid(true)
{
}
bool JKQTPlotter::MouseDragAction::isValid() const {
return valid;
}
void JKQTPlotter::MouseDragAction::clear()
{
valid=false;
mode=ZoomRectangle;
modifier=Qt::NoModifier;
mouseButton=Qt::LeftButton;
}

View File

@ -156,7 +156,31 @@ LIB_EXPORT void initJKQTPlotterResources();
* *
* \subsection JKQTPLOTTER_USERMOUSEINTERACTION Mouse-Interaction in JKQTPlotter * \subsection JKQTPLOTTER_USERMOUSEINTERACTION Mouse-Interaction in JKQTPlotter
* *
* JKQTPlotter offers several methods that allow to customize, how it reacts to mouse actions:
* - registerMouseDragAction() tells JKQTPlotter to perform a certain action (selected from JKQTPlotter::MouseActionMode)
* when a specified mouse button is pushed while a specified (or no) keyborad modifiers (e.g. CTRL,ALT,SHIFT...) is pressed.
* By default JKQTPlotter calls these two registers in its constructors:
* \code
* registerMouseDragAction(Qt::LeftButton, Qt::NoModifier, JKQTPlotter::MouseActionMode::ZoomRectangle);
* registerMouseDragAction(Qt::LeftButton, Qt::ControlModifier, JKQTPlotter::MouseActionMode::PanPlotOnMove);
* \endcode
* Therefore by default you can draw a zoom rectangle with the left mouse button without modifiers
* and you can pan/drag the plot with the left mouse-button while keeping CTRL pressed.
* - deregisterMouseDragAction() deletes a previously defined unser-interaction
* - clearAllRegisteredMouseDragActions() deletes all previously specified user-actions
* .
* *
* The right mouse button has a special role: If it is single-clicked and no JKQTPlotter::MouseActionMode is specified
* for the vent, it opens the context menu, unless you call \c enableRightClickShowsContextMenu(false) .
*
* For any mouse-click, one of the following signals is emitted:
* - plotMouseClicked() for any single-click (during the pressDown-Event!)
* - plotMouseDoubleClicked() for any double-click
* .
* In addition the signal plotMouseMove() is called whenever the mouse moves over the plot.
* Additional signals may be emitted, depending on the currently active JKQTPlotter::MouseActionMode.
*
* Pressing the ESC key will stop the current JKQTPlotter::MouseActionMode.
* *
* \see \ref JKQTPlotterUserInteraction * \see \ref JKQTPlotterUserInteraction
* *
@ -189,9 +213,8 @@ class LIB_EXPORT JKQTPlotter: public QWidget {
public: public:
/** \brief availble user-action mode this JKQtPlotter use when mouse events occur. /** \brief availble user-action mode this JKQtPlotter use when mouse events occur.
* This allows you to e.g. draw rectangles or lines over the plot and receive a signal, when the drawing finishes */ * This allows you to e.g. draw rectangles or lines over the plot and receive a signal, when the drawing finishes */
enum MouseActionModes { enum MouseActionMode {
NoMouseAction=0, /*!< \brief no action is to be performed */ PanPlotOnMove=0, /*!< \brief the user can drag the current plot window while keeping the left mouse-button pushed down (=panning), the new widow is applied/displayed whenever the mouse moves */
PanPlotOnMove, /*!< \brief the user can drag the current plot window while keeping the left mouse-button pushed down (=panning), the new widow is applied/displayed whenever the mouse moves */
PanPlotOnRelease, /*!< \brief the user can drag the current plot window while keeping the left mouse-button pushed down (=panning), the new widow is applied/displayed when the left mouse button is released */ PanPlotOnRelease, /*!< \brief the user can drag the current plot window while keeping the left mouse-button pushed down (=panning), the new widow is applied/displayed when the left mouse button is released */
ZoomRectangle, /*!< \brief draw a rectangle and when finish zoom to that rectangle */ ZoomRectangle, /*!< \brief draw a rectangle and when finish zoom to that rectangle */
RectangleEvents, /*!< \brief draw a rectangle and when finished execute the signal userRectangleFinished() */ RectangleEvents, /*!< \brief draw a rectangle and when finished execute the signal userRectangleFinished() */
@ -199,7 +222,6 @@ class LIB_EXPORT JKQTPlotter: public QWidget {
EllipseEvents, /*!< \brief draw an ellipse and when finished execute the signal userEllipseFinished() */ EllipseEvents, /*!< \brief draw an ellipse and when finished execute the signal userEllipseFinished() */
LineEvents, /*!< \brief draw a line and when finished execute the signal userLineFinished() */ LineEvents, /*!< \brief draw a line and when finished execute the signal userLineFinished() */
ScribbleEvents, /*!< \brief let the user scribble on the plot (left mouse button is kept pressed) and call userScribbleClick() for each new position */ ScribbleEvents, /*!< \brief let the user scribble on the plot (left mouse button is kept pressed) and call userScribbleClick() for each new position */
ClickEvents /*!< \brief sinply call userClickFinished() for every single-click of the mouse button */
}; };
/** \brief options of how to react to a right mouse button click */ /** \brief options of how to react to a right mouse button click */
@ -209,7 +231,7 @@ class LIB_EXPORT JKQTPlotter: public QWidget {
RightMouseButtonContextMenu=2 /*!< \brief show the context menu when clicking the right mouse button */ RightMouseButtonContextMenu=2 /*!< \brief show the context menu when clicking the right mouse button */
}; };
/** \brief options of how to react to a left mouse button double-click (single-click events are described by MouseActionModes) */ /** \brief options of how to react to a left mouse button double-click (single-click events are described by MouseActionMode) */
enum LeftDoubleClickAction { enum LeftDoubleClickAction {
LeftDoubleClickDefault, /*!< \brief */ LeftDoubleClickDefault, /*!< \brief */
LeftDoubleClickContextMenu, /*!< \brief open the context menu when the left mouse button is double-clicked */ LeftDoubleClickContextMenu, /*!< \brief open the context menu when the left mouse button is double-clicked */
@ -273,11 +295,6 @@ class LIB_EXPORT JKQTPlotter: public QWidget {
\see userActionCompositionMode for more information */ \see userActionCompositionMode for more information */
QPainter::CompositionMode getUserActionCompositionMode() const; QPainter::CompositionMode getUserActionCompositionMode() const;
/*! \brief returns the current mouseActionMode.
\details Description of the parameter mouseActionMode is: <BLOCKQUOTE> specifies the user-action mode this JKQtPlotter use when mouse events occur.
* This allows you to e.g. draw rectangles or lines over the plot and receive a signal, when the drawing finishes </BLOCKQUOTE>
\see mouseActionMode for more information */
MouseActionModes getMouseActionMode() const;
/** \brief loads the plot properties from a QSettings object */ /** \brief loads the plot properties from a QSettings object */
void loadSettings(const QSettings &settings, const QString& group=QString("plots")); void loadSettings(const QSettings &settings, const QString& group=QString("plots"));
@ -350,8 +367,14 @@ class LIB_EXPORT JKQTPlotter: public QWidget {
*/ */
void setPlotUpdateEnabled(bool enable); void setPlotUpdateEnabled(bool enable);
/*! \brief checks whether to \c getMouseActionMode()==JKQTPlotter::ZoomRectangle */ /** \brief registeres a certain mouse action \a action to be executed when a mouse drag operation is
bool getZoomByMouseRectangle() const; * initialized with the given \a button and \a modifier */
void registerMouseDragAction(Qt::MouseButton button, Qt::KeyboardModifier modifier, MouseActionMode action);
/** \brief deregisteres the mouse action to be executed when a mouse drag operation is
* initialized with the given \a button and \a modifier */
void deregisterMouseDragAction(Qt::MouseButton button, Qt::KeyboardModifier modifier);
/** \brief clear all registeres mouse actions */
void clearAllRegisteredMouseDragActions();
/*! \brief returns the property rightMouseButtonAction ( \copybrief rightMouseButtonAction ). /*! \brief returns the property rightMouseButtonAction ( \copybrief rightMouseButtonAction ).
\details Description of the parameter rightMouseButtonAction is: <BLOCKQUOTE>\copydoc rightMouseButtonAction </BLOCKQUOTE> \details Description of the parameter rightMouseButtonAction is: <BLOCKQUOTE>\copydoc rightMouseButtonAction </BLOCKQUOTE>
\see rightMouseButtonAction for more information */ \see rightMouseButtonAction for more information */
@ -478,6 +501,13 @@ class LIB_EXPORT JKQTPlotter: public QWidget {
inline double getKeyFontSize() const { inline double getKeyFontSize() const {
return getConstplotter()->getKeyFontSize(); return getConstplotter()->getKeyFontSize();
} }
/** \brief checks, whether showing the context menu on a right-button click on the mouse is enabled
* \see enableRightClickShowsContextMenu(), disableRightClickShowsContextMenu(), JKQTPLOTTER_USERMOUSEINTERACTION
*/
bool isRightClickShowsContextMenuEnabled() const;
public slots: public slots:
/** \brief set the current plot magnification */ /** \brief set the current plot magnification */
void setMagnification(double m); void setMagnification(double m);
@ -579,13 +609,7 @@ class LIB_EXPORT JKQTPlotter: public QWidget {
\details Description of the parameter userActionCompositionMode is: <BLOCKQUOTE>\copydoc userActionCompositionMode </BLOCKQUOTE> \details Description of the parameter userActionCompositionMode is: <BLOCKQUOTE>\copydoc userActionCompositionMode </BLOCKQUOTE>
\see userActionCompositionMode for more information */ \see userActionCompositionMode for more information */
void setUserActionCompositionMode(const QPainter::CompositionMode & __value); void setUserActionCompositionMode(const QPainter::CompositionMode & __value);
/*! \brief sets the current mouseActionMode .
\details Description of the parameter mouseActionMode is: <BLOCKQUOTE> specifies the user-action mode this JKQtPlotter use when mouse events occur.
* This allows you to e.g. draw rectangles or lines over the plot and receive a signal, when the drawing finishes </BLOCKQUOTE>
\see mouseActionMode for more information */
void setMouseActionMode(const MouseActionModes & __value);
/*! \brief equivalent to \c setMouseActionMode(JKQTPlotter::ZoomRectangle) */
void setZoomByMouseRectangle(bool zomByrectangle);
/*! \brief sets the property zoomByMouseWheel ( \copybrief zoomByMouseWheel ) to the specified \a __value. /*! \brief sets the property zoomByMouseWheel ( \copybrief zoomByMouseWheel ) to the specified \a __value.
\details Description of the parameter zoomByMouseWheel is: <BLOCKQUOTE>\copydoc zoomByMouseWheel </BLOCKQUOTE> \details Description of the parameter zoomByMouseWheel is: <BLOCKQUOTE>\copydoc zoomByMouseWheel </BLOCKQUOTE>
@ -602,6 +626,14 @@ class LIB_EXPORT JKQTPlotter: public QWidget {
\see rightMouseButtonAction for more information */ \see rightMouseButtonAction for more information */
void setRightMouseButtonAction(const RightMouseButtonAction & __value); void setRightMouseButtonAction(const RightMouseButtonAction & __value);
/** \brief enables showing the context menu on a right-button click on the mouse
* \see disableRightClickShowsContextMenu(), JKQTPLOTTER_USERMOUSEINTERACTION
*/
void enableRightClickShowsContextMenu(bool enabled=true);
/** \brief disables showing the context menu on a right-button click on the mouse
* \see enableRightClickShowsContextMenu(), JKQTPLOTTER_USERMOUSEINTERACTION
*/
void disableRightClickShowsContextMenu(bool disabled=true);
/** \brief may be connected to zoomChangedLocally() of a different plot and synchronizes the local x-axis to the other x-axis */ /** \brief may be connected to zoomChangedLocally() of a different plot and synchronizes the local x-axis to the other x-axis */
void synchronizeXAxis(double newxmin, double newxmax, double newymin, double newymax, JKQTPlotter* sender); void synchronizeXAxis(double newxmin, double newxmax, double newymin, double newymax, JKQTPlotter* sender);
@ -665,7 +697,7 @@ class LIB_EXPORT JKQTPlotter: public QWidget {
* \param button mouse-button that was used for the click * \param button mouse-button that was used for the click
*/ */
void plotMouseDoubleClicked(double x, double y, Qt::KeyboardModifiers modifiers, Qt::MouseButton button); void plotMouseDoubleClicked(double x, double y, Qt::KeyboardModifiers modifiers, Qt::MouseButton button);
/** \brief emitted when mouseActionMode==JKQTPlotter::ZoomRectangle and the drawing of the new zoom rectangle is finished (=mouse key released) /** \brief emitted when the mouse action JKQTPlotter::ZoomRectangle and the drawing of the new zoom rectangle is finished (=mouse key released)
* *
* \param mouseDragRectXStart start of the selected x-range (in plot coordinates) * \param mouseDragRectXStart start of the selected x-range (in plot coordinates)
* \param mouseDragRectXEnd end of the selected x-range (in plot coordinates) * \param mouseDragRectXEnd end of the selected x-range (in plot coordinates)
@ -707,14 +739,7 @@ class LIB_EXPORT JKQTPlotter: public QWidget {
*/ */
void zoomChangedLocally(double newxmin, double newxmax, double newymin, double newymax, JKQTPlotter* sender); void zoomChangedLocally(double newxmin, double newxmax, double newymin, double newymax, JKQTPlotter* sender);
/** \brief emitted when mouseActionMode==JKQTPlotter::ClickEvents and a click event from the mouse occurs inside the plot /** \brief emitted when the mouse action JKQTPlotter::ScribbleEvents and a click event from the mouse occurs inside the plot,
*
* \param x x-position of the mouse (in plot coordinates)
* \param y y-position of the mouse (in plot coordinates)
* \param modifiers key-modifiers when the click occured
*/
void userClickFinished(double x, double y, Qt::KeyboardModifiers modifiers);
/** \brief emitted when mouseActionMode==JKQTPlotter::ScribbleEvents and a click event from the mouse occurs inside the plot,
* or the mouse moved while the left button is pressed down * or the mouse moved while the left button is pressed down
* *
* \param x x-position of the mouse (in plot coordinates) * \param x x-position of the mouse (in plot coordinates)
@ -724,7 +749,7 @@ class LIB_EXPORT JKQTPlotter: public QWidget {
* \param last if \c true: this is the last event of a series that ends when releasing the mouse-button, within the series, this is \c false * \param last if \c true: this is the last event of a series that ends when releasing the mouse-button, within the series, this is \c false
*/ */
void userScribbleClick(double x, double y, Qt::KeyboardModifiers modifiers, bool first, bool last); void userScribbleClick(double x, double y, Qt::KeyboardModifiers modifiers, bool first, bool last);
/** \brief emitted when mouseActionMode==JKQTPlotter::RectangleEvents and the drawing of the new rectangle is finished (=mouse key released) /** \brief emitted when the mouse action JKQTPlotter::RectangleEvents and the drawing of the new rectangle is finished (=mouse key released)
* *
* \param x x-coordinate of the bottom left corner of the rectangle (in plot coordinates) * \param x x-coordinate of the bottom left corner of the rectangle (in plot coordinates)
* \param y y-coordinate of the bottom left corner of the rectangle (in plot coordinates) * \param y y-coordinate of the bottom left corner of the rectangle (in plot coordinates)
@ -733,7 +758,7 @@ class LIB_EXPORT JKQTPlotter: public QWidget {
* \param modifiers key-modifiers when the rectangle was finished * \param modifiers key-modifiers when the rectangle was finished
*/ */
void userRectangleFinished(double x, double y, double width, double height, Qt::KeyboardModifiers modifiers); void userRectangleFinished(double x, double y, double width, double height, Qt::KeyboardModifiers modifiers);
/** \brief emitted when mouseActionMode==JKQTPlotter::LineEvents and the drawing of the new line is finished (=mouse key released) /** \brief emitted when the mouse action JKQTPlotter::LineEvents and the drawing of the new line is finished (=mouse key released)
* *
* \param x1 x-coordinate of the start of the line (in plot coordinates) * \param x1 x-coordinate of the start of the line (in plot coordinates)
* \param y1 y-coordinate of the start of the line (in plot coordinates) * \param y1 y-coordinate of the start of the line (in plot coordinates)
@ -742,7 +767,7 @@ class LIB_EXPORT JKQTPlotter: public QWidget {
* \param modifiers key-modifiers when the rectangle was finished * \param modifiers key-modifiers when the rectangle was finished
*/ */
void userLineFinished(double x1, double y1, double x2, double y2, Qt::KeyboardModifiers modifiers); void userLineFinished(double x1, double y1, double x2, double y2, Qt::KeyboardModifiers modifiers);
/** \brief emitted when mouseActionMode==JKQTPlotter::CircleEvents and the drawing of the new circle is finished (=mouse key released) /** \brief emitted when the mouse action JKQTPlotter::CircleEvents and the drawing of the new circle is finished (=mouse key released)
* *
* \param x x-coordinate of the center of the circle (in plot coordinates) * \param x x-coordinate of the center of the circle (in plot coordinates)
* \param y y-coordinate of the center of the circle (in plot coordinates) * \param y y-coordinate of the center of the circle (in plot coordinates)
@ -750,7 +775,7 @@ class LIB_EXPORT JKQTPlotter: public QWidget {
* \param modifiers key-modifiers when the rectangle was finished * \param modifiers key-modifiers when the rectangle was finished
*/ */
void userCircleFinished(double x, double y, double radius, Qt::KeyboardModifiers modifiers); void userCircleFinished(double x, double y, double radius, Qt::KeyboardModifiers modifiers);
/** \brief emitted when mouseActionMode==JKQTPlotter::EllipseEvents and the drawing of the new ellipse is finished (=mouse key released) /** \brief emitted when the mouse action JKQTPlotter::EllipseEvents and the drawing of the new ellipse is finished (=mouse key released)
* *
* \param x x-coordinate of the center of the ellipse (in plot coordinates) * \param x x-coordinate of the center of the ellipse (in plot coordinates)
* \param y y-coordinate of the center of the ellipse (in plot coordinates) * \param y y-coordinate of the center of the ellipse (in plot coordinates)
@ -763,6 +788,34 @@ class LIB_EXPORT JKQTPlotter: public QWidget {
protected: protected:
/** \brief ties a MouseActionMode to a mouse-button and a keyboard-modifier
* \internal
*/
struct LIB_EXPORT MouseDragAction {
/** \brief constructs an invalid object */
MouseDragAction();
MouseDragAction(Qt::MouseButton _mouseButton, Qt::KeyboardModifier _modifier, MouseActionMode _mode);
MouseActionMode mode;
Qt::KeyboardModifier modifier;
Qt::MouseButton mouseButton;
bool isValid() const;
void clear();
private:
bool valid;
};
/** \brief the currently executed MouseDragAction */
MouseDragAction currentMouseDragAction;
/** \brief lists all availble mouse action modes */
QHash<QPair<Qt::MouseButton,Qt::KeyboardModifier>, MouseActionMode> registeredMouseActionModes;
/** \brief searches registeredMouseActionModes for a matching action */
QHash<QPair<Qt::MouseButton,Qt::KeyboardModifier>, MouseActionMode>::const_iterator findMatchingMouseDragAction(Qt::MouseButton button, Qt::KeyboardModifiers modifiers) const;
/** \brief specifies whether to show the context menu, when the right button of the mouse is clicked */
bool rightClickShowsContextMenu;
/** \brief you may overwrite this method to modify the given context emnu before it is displayed. /** \brief you may overwrite this method to modify the given context emnu before it is displayed.
* *
* The plotter will fill the menu with the default items and then call this method. The default implementation does NOTHING. * The plotter will fill the menu with the default items and then call this method. The default implementation does NOTHING.
@ -771,10 +824,6 @@ class LIB_EXPORT JKQTPlotter: public QWidget {
void init(bool datastore_internal, QWidget* parent, JKQTPDatastore* datast); void init(bool datastore_internal, QWidget* parent, JKQTPDatastore* datast);
/** \brief specifies the user-action mode this JKQtPlotter use when mouse events occur.
* This allows you to e.g. draw rectangles or lines over the plot and receive a signal, when the drawing finishes */
MouseActionModes mouseActionMode;
bool doDrawing; bool doDrawing;
/** \brief JKQTBasePlotter used to plot */ /** \brief JKQTBasePlotter used to plot */
@ -889,19 +938,14 @@ class LIB_EXPORT JKQTPlotter: public QWidget {
/** \brief event handler for a mouse down event /** \brief event handler for a mouse down event
* *
* If the left mouse button is pressed down this starts the drawing of a zoom rectangle with * This event determines the action to be performed from registeredMouseActionModes
* the mouse. This method sets mouseZooming to \c true and stores the current time in the private * and then sets currentMouseDragAction accordingly and starts the mouse action.
* property mouseZoomingTStart. All this is only executed when the mouse is inside the coordinate
* system.
*
* If the right mouse button is clicked this zooms out of the coordinate system by a factor of two.
*/ */
void mousePressEvent ( QMouseEvent * event ); void mousePressEvent ( QMouseEvent * event );
/** \brief event handler for a mouse release event /** \brief event handler for a mouse release event
* *
* If the left mouse button is released (and mouseZooming is \c true ) this stops drawing a * this finishes the action, started by mousePressEvent()
* zoom rectangle and emits a tzoomChangedLocally() event.
*/ */
void mouseReleaseEvent ( QMouseEvent * event ); void mouseReleaseEvent ( QMouseEvent * event );
@ -916,7 +960,7 @@ class LIB_EXPORT JKQTPlotter: public QWidget {
/** \brief resizes the internal representation (image) of the graphs */ /** \brief resizes the internal representation (image) of the graphs */
void resizeEvent(QResizeEvent *event); void resizeEvent(QResizeEvent *event);
/** \brief called, when the mouse leaves the widget, hides the toolbar (if visible) */
void leaveEvent ( QEvent * event ); void leaveEvent ( QEvent * event );
/** \brief specifies whether to display a toolbar with buttons when the mouse is in the upper border of the plot /** \brief specifies whether to display a toolbar with buttons when the mouse is in the upper border of the plot
@ -1007,5 +1051,13 @@ class LIB_EXPORT JKQTPlotter: public QWidget {
}; };
/** \brief qHash-variant used by JKQTPlotter
* \internal
* \ingroup jkqtpplotterclasses
*/
template<>
inline uint qHash(const QPair<Qt::MouseButton,Qt::KeyboardModifier> &key, uint seed ) noexcept(noexcept(qHash(key.first, seed)) && noexcept(qHash(key.second, seed))) {
return static_cast<uint>(key.first)+static_cast<uint>(key.second);
}
#endif // JKQTPLOTTER_H #endif // JKQTPLOTTER_H