Skip to content

Commit

Permalink
Graph Panel widget: fixed a problem with graph panels not always bein…
Browse files Browse the repository at this point in the history
…g properly aligned (closes #1619).
  • Loading branch information
agarny committed Apr 23, 2018
2 parents ae667ff + 485982b commit 7937ca9
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 59 deletions.
1 change: 1 addition & 0 deletions doc/downloads/index.js
Expand Up @@ -39,6 +39,7 @@ var jsonData = { "versions": [
"changes": [
{ "change": "<strong>General:</strong> upgraded to Qt 5.9.5 LTS (see issue <a href=\"https://github.com/opencor/opencor/issues/1615\">#1615</a>). Fixed some seemingly random crashes (especially on Windows; see issue <a href=\"https://github.com/opencor/opencor/issues/1574\">#1574</a>)." },
{ "change": "<strong>Data store interface:</strong> fixed a problem with the returned size of a data store being wrong in some cases (see issue <a href=\"https://github.com/opencor/opencor/issues/1579\">#1579</a>)." },
{ "change": "<strong>Graph Panel widget:</strong> fixed a problem with graph panels not always being properly aligned (see issue <a href=\"https://github.com/opencor/opencor/issues/1619\">#1619</a>)." },
{ "change": "<strong>PMR support:</strong> fixed a problem with the PMR Workspaces window potentially not reflecting the Git status of a folder (see issue <a href=\"https://github.com/opencor/opencor/issues/1582\">#1582</a>). Updated the description of our different PMR instances (see issue <a href=\"https://github.com/opencor/opencor/issues/1583\">#1583</a>)." },
{ "change": "<strong>CellML support:</strong> now provide more information when imports cannot be fully instantiated (see issue <a href=\"https://github.com/opencor/opencor/issues/1595\">#1595</a>)." },
{ "change": "<strong>SED-ML support:</strong> fixed a problem with OpenCOR crashing when saving an empty SED-ML file (see issue <a href=\"https://github.com/opencor/opencor/issues/1572\">#1572</a>)." },
Expand Down
Expand Up @@ -1205,7 +1205,7 @@ void Property::setVisible(bool pVisible)
void Property::select() const
{
// Have our owner select ourselves (i.e. our value), preserving the position
// of our horizontal scrollbar
// of our horizontal scroll bar

int horizontalScrollBarValue = mOwner->horizontalScrollBar()->value();

Expand Down
Expand Up @@ -1271,7 +1271,7 @@ void FileOrganiserWindowWidget::deleteItems()
collapseEmptyFolders(mModel->invisibleRootItem());

// Resize the widget to its contents in case its width was too wide (and
// therefore required a horizontal scrollbar), but is now fine
// therefore required a horizontal scroll bar), but is now fine

resizeToContents();
}
Expand Down
Expand Up @@ -1243,6 +1243,8 @@ void SimulationExperimentViewInformationGraphPanelAndGraphsWidget::updateGraphIn

// Update the graph's title

QString oldTitle = graph->title();

graph->setTitle(properties[1]->value());

// Check that the parameters represented by the value of the X and Y
Expand Down Expand Up @@ -1312,10 +1314,14 @@ void SimulationExperimentViewInformationGraphPanelAndGraphsWidget::updateGraphIn

graph->setSymbol(symbolStyle, symbolFillColor, symbolColor, symbolSize);

// Let people know if the X and/or Y parameters of our graph have changed or
// replot it if its settings have changed
// Update our graph's GUI if the title of our graph is different (which may
// result in our legend's width being updated), let people know if the X
// and/or Y parameters of our graph have changed, or replot it if its
// settings have changed

if ( (oldParameterX != graph->parameterX())
if (oldTitle != graph->title()) {
graph->plot()->updateGui();
} else if ( (oldParameterX != graph->parameterX())
|| (oldParameterY != graph->parameterY())) {
emit graphUpdated(graph);
} else if ((oldLinePen != linePen) || graphSymbolUpdated) {
Expand Down Expand Up @@ -1421,9 +1427,9 @@ void SimulationExperimentViewInformationGraphPanelAndGraphsWidget::graphPanelPro
graphPanelPlot->setZoomRegionFilled(zoomRegionProperties[4]->booleanValue());
graphPanelPlot->setZoomRegionFillColor(zoomRegionProperties[5]->colorValue());

graphPanelPlot->setUpdatesEnabled(true);
graphPanelPlot->updateGui();

graphPanelPlot->forceAlignWithNeighbors();
graphPanelPlot->setUpdatesEnabled(true);
}

//==============================================================================
Expand Down
Expand Up @@ -717,7 +717,7 @@ void SimulationExperimentViewWidget::updateContentsInformationGui(SimulationExpe
{
// Update our simualtion widget's GUI and that of its children
// Note: for column widths, we set the last column width to zero to avoid
// potential issues, should the vertical scrollbar be visible...
// potential issues, should the vertical scroll bar be visible...

pSimulationWidget->setSizes(mSimulationWidgetSizes);

Expand Down
174 changes: 127 additions & 47 deletions src/plugins/widget/GraphPanelWidget/src/graphpanelplotwidget.cpp
Expand Up @@ -36,6 +36,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QImageWriter>
#include <QMenu>
#include <QPaintEvent>
#include <QTimer>

//==============================================================================

Expand Down Expand Up @@ -457,6 +458,17 @@ void GraphPanelPlotGraph::setSymbol(const QwtSymbol::Style &pStyle,

//==============================================================================

QString GraphPanelPlotGraph::title() const
{
// Return our title

Q_ASSERT(mDummyRun);

return mDummyRun->title().text();
}

//==============================================================================

void GraphPanelPlotGraph::setTitle(const QString &pTitle)
{
// Set the title of our different runs
Expand Down Expand Up @@ -1004,7 +1016,8 @@ GraphPanelPlotLegendWidget::GraphPanelPlotLegendWidget(GraphPanelPlotWidget *pPa
mFontSize(pParent->fontSize()),
mBackgroundColor(pParent->backgroundColor()),
mForegroundColor(pParent->surroundingAreaForegroundColor()),
mLegendLabels(QMap<GraphPanelPlotGraph *, QwtLegendLabel *>())
mLegendLabels(QMap<GraphPanelPlotGraph *, QwtLegendLabel *>()),
mSizeHintWidth(0)
{
// Have our legend items use as much horizontal space as possible

Expand Down Expand Up @@ -1165,25 +1178,21 @@ void GraphPanelPlotLegendWidget::renderLegend(QPainter *pPainter,

//==============================================================================

QSize GraphPanelPlotLegendWidget::sizeHint() const
void GraphPanelPlotLegendWidget::setSizeHintWidth(int pSizeHintWidth)
{
// Determine and return our size hint, based on our active state and on the
// 'raw' size hint of our owner's neigbours' legend, if any
// Set our internal size hint width

QSize res = mActive?
QwtLegend::isEmpty()?
QSize(0, 0):
QwtLegend::sizeHint():
QSize(0, 0);
mSizeHintWidth = pSizeHintWidth;
}

foreach (GraphPanelPlotWidget *ownerNeighbor, mOwner->neighbors()) {
GraphPanelPlotLegendWidget *legend = static_cast<GraphPanelPlotLegendWidget *>(ownerNeighbor->legend());
//==============================================================================

if (legend->isActive())
res.setWidth(qMax(res.width(), legend->QwtLegend::sizeHint().width()));
}
QSize GraphPanelPlotLegendWidget::sizeHint() const
{
// Return our size hint, based on our internal size hint width and the
// height of our default size hint

return res;
return QSize(mSizeHintWidth, QwtLegend::sizeHint().height());
}

//==============================================================================
Expand Down Expand Up @@ -1223,14 +1232,6 @@ void GraphPanelPlotLegendWidget::updateWidget(QWidget *pWidget,

legendLabel->setPalette(newPalette);

// Make sure that the width of our owner's neighbours' legend is the
// same as ours

int legendWidth = sizeHint().width();

foreach (GraphPanelPlotWidget *ownerNeighbor, mOwner->neighbors())
ownerNeighbor->setLegendWidth(legendWidth);

// Make sure that updates are enabled
// Note: indeed, when setting its data, QwtLegendLabel (which is used by
// QwtLegend) prevents itself from updating, and then reallows
Expand All @@ -1255,7 +1256,7 @@ void GraphPanelPlotLegendWidget::updateWidget(QWidget *pWidget,

void GraphPanelPlotLegendWidget::addGraph(GraphPanelPlotGraph *pGraph)
{
// Associate our last contents widget's child with the given graph
// Associate the given graph with our last contents widget's child

mLegendLabels.insert(pGraph, static_cast<QwtLegendLabel *>(contentsWidget()->children().last()));
}
Expand All @@ -1271,6 +1272,20 @@ void GraphPanelPlotLegendWidget::removeGraph(GraphPanelPlotGraph *pGraph)

//==============================================================================

bool GraphPanelPlotLegendWidget::needScrollBar() const
{
// Determine and return whether we need a (vertical) scroll bar

int legendLabelsHeight = 0;

foreach (QwtLegendLabel *legendLabel, mLegendLabels)
legendLabelsHeight += legendLabel->height();

return !pos().y() && (legendLabelsHeight > height());
}

//==============================================================================

void GraphPanelPlotLegendWidget::legendChecked(const QVariant &pItemInfo)
{
// Make sure that the corresponding graph panel is selected
Expand Down Expand Up @@ -2607,14 +2622,14 @@ bool GraphPanelPlotWidget::setAxes(double pMinX, double pMaxX, double pMinY,
if (pSynchronizeAxes) {
if ( mSynchronizeXAxisAction->isChecked()
&& mSynchronizeYAxisAction->isChecked()) {
foreach (GraphPanelPlotWidget *neighbor, mNeighbors)
neighbor->setAxes(pMinX, pMaxX, pMinY, pMaxY, false, false, false);
foreach (GraphPanelPlotWidget *plot, mNeighbors)
plot->setAxes(pMinX, pMaxX, pMinY, pMaxY, false, false, false);
} else if (xAxisValuesChanged && mSynchronizeXAxisAction->isChecked()) {
foreach (GraphPanelPlotWidget *neighbor, mNeighbors)
neighbor->setAxes(pMinX, pMaxX, neighbor->minY(), neighbor->maxY(), false, false, false);
foreach (GraphPanelPlotWidget *plot, mNeighbors)
plot->setAxes(pMinX, pMaxX, plot->minY(), plot->maxY(), false, false, false);
} else if (yAxisValuesChanged && mSynchronizeYAxisAction->isChecked()) {
foreach (GraphPanelPlotWidget *neighbor, mNeighbors)
neighbor->setAxes(neighbor->minX(), neighbor->maxX(), pMinY, pMaxY, false, false, false);
foreach (GraphPanelPlotWidget *plot, mNeighbors)
plot->setAxes(plot->minX(), plot->maxX(), pMinY, pMaxY, false, false, false);
}

alignWithNeighbors(pCanReplot,
Expand Down Expand Up @@ -2749,8 +2764,56 @@ void GraphPanelPlotWidget::setTitleAxis(int pAxisId, const QString &pTitleAxis)

setAxisTitle(pAxisId, axisTitle);
}
}

//==============================================================================

void GraphPanelPlotWidget::doUpdateGui()
{
// Resize our legend and that of our neighbours

GraphPanelPlotWidgets selfPlusNeighbors = GraphPanelPlotWidgets() << this << mNeighbors;
int legendWidth = 0;

forceAlignWithNeighbors();
foreach (GraphPanelPlotWidget *plot, selfPlusNeighbors) {
GraphPanelPlotLegendWidget *legend = static_cast<GraphPanelPlotLegendWidget *>(plot->legend());

legendWidth = qMax(legendWidth, legend->QwtLegend::sizeHint().width());

if (legend->needScrollBar()) {
legendWidth = qMax(legendWidth,
legend->QwtLegend::sizeHint().width()+legend->scrollExtent(Qt::Vertical));
}
}

foreach (GraphPanelPlotWidget *plot, selfPlusNeighbors) {
GraphPanelPlotLegendWidget *legend = static_cast<GraphPanelPlotLegendWidget *>(plot->legend());

legend->setSizeHintWidth(legend->needScrollBar()?
legendWidth-legend->scrollExtent(Qt::Vertical):
legendWidth);
}

// Reenable updates for our legend
// Note: see addGraph() for the reasoning behind it...

legend()->setUpdatesEnabled(true);

// Make sure that we are still properly aligned with our neighbours

alignWithNeighbors(true, true);
}

//==============================================================================

void GraphPanelPlotWidget::updateGui(bool pSingleShot)
{
// Update our GUI, either through a single shot or directly

if (pSingleShot)
QTimer::singleShot(0, this, &GraphPanelPlotWidget::doUpdateGui);
else
doUpdateGui();
}

//==============================================================================
Expand Down Expand Up @@ -2990,6 +3053,10 @@ void GraphPanelPlotWidget::resizeEvent(QResizeEvent *pEvent)
// Update the size of our overlay widget

mOverlayWidget->resize(pEvent->size());

// Update our GUI (and that of our neighbours)

updateGui();
}

//==============================================================================
Expand All @@ -3001,7 +3068,8 @@ void GraphPanelPlotWidget::wheelEvent(QWheelEvent *pEvent)
if ( !(pEvent->modifiers() & Qt::ShiftModifier)
&& !(pEvent->modifiers() & Qt::ControlModifier)
&& !(pEvent->modifiers() & Qt::AltModifier)
&& !(pEvent->modifiers() & Qt::MetaModifier)) {
&& !(pEvent->modifiers() & Qt::MetaModifier)
&& canvas()->rect().contains(pEvent->pos()-canvas()->pos())) {
// Make sure that we are not already carrying out a action

if (mAction == None) {
Expand Down Expand Up @@ -3037,6 +3105,12 @@ bool GraphPanelPlotWidget::addGraph(GraphPanelPlotGraph *pGraph)

// Attach the given graph to ourselves and keep track of it, as well as ask
// our legend to keep track of it too
// Note: we temporarily disable updates for our legend, this to avoid some
// black areas from quickly appearing on macOS (when adding a graph
// that results in the vertical scroll bar being shown). It gets
// reenabled in updateGUI()...

legend()->setUpdatesEnabled(false);

pGraph->attach(this);

Expand All @@ -3048,10 +3122,14 @@ bool GraphPanelPlotWidget::addGraph(GraphPanelPlotGraph *pGraph)

mLegend->setChecked(pGraph, true);

// To add a graph may result in the legend getting shown, so we need to make
// sure that our neighbours are aware of it
// To add a graph may affect our GUI (and that of our neighbours), so update
// it
// Note: we do it through a single shot since otherwise the new legend label
// won't have been added yet and our legend may not be of the right
// width (e.g. after having added a graph that would result in the
// legend's vertical scroll bar to appear)...

forceAlignWithNeighbors();
updateGui(true);

return true;
}
Expand All @@ -3067,6 +3145,10 @@ bool GraphPanelPlotWidget::removeGraph(GraphPanelPlotGraph *pGraph)

// Detach the given graph from ourselves, stop tracking it (and ask our
// legend to do the same) and delete it
// Note: see addGraph() when it comes to temporarily disabling updates for
// our legend...

legend()->setUpdatesEnabled(false);

pGraph->detach();

Expand All @@ -3076,10 +3158,10 @@ bool GraphPanelPlotWidget::removeGraph(GraphPanelPlotGraph *pGraph)

delete pGraph;

// To remove a graph may result in the legend getting hidden, so we need to
// make sure that our neighbours are aware of it
// To remove a graph may affect our GUI (and that of our neighbours), so
// update it

forceAlignWithNeighbors();
updateGui();

return true;
}
Expand Down Expand Up @@ -3170,6 +3252,11 @@ void GraphPanelPlotWidget::alignWithNeighbors(bool pCanReplot,
axisWidget(QwtPlot::xBottom)->getMinBorderDist(oldMinBorderDistStartX, oldMinBorderDistEndX);

foreach (GraphPanelPlotWidget *plot, selfPlusNeighbors) {
plot->setUpdatesEnabled(false);
// Note: this is needed on Windows and Linux otherwise to resize our
// graph panels will result in the X axis flashing due to our call
// to xScaleWidget->setMinBorderDist(0, 0) below...

QwtScaleWidget *xScaleWidget = plot->axisWidget(QwtPlot::xBottom);

xScaleWidget->setMinBorderDist(0, 0);
Expand Down Expand Up @@ -3230,16 +3317,9 @@ void GraphPanelPlotWidget::alignWithNeighbors(bool pCanReplot,
replot();
}
}
}
}

//==============================================================================

void GraphPanelPlotWidget::forceAlignWithNeighbors()
{
// Force the re-alignment with our neighbours

alignWithNeighbors(true, true);
plot->setUpdatesEnabled(true);
}
}

//==============================================================================
Expand Down

0 comments on commit 7937ca9

Please sign in to comment.