void LineItem::creationPolygonChanged(View::CreationEvent event) { if (event == View::MousePress) { const QPolygonF poly = mapFromScene(parentView()->creationPolygon(View::MousePress)); setPos(poly.first().x(), poly.first().y()); setViewRect(QRectF(0.0, 0.0, 0.0, sizeOfGrip().height())); parentView()->scene()->addItem(this); //setZValue(1); return; } if (event == View::MouseMove) { const QPolygonF poly = mapFromScene(parentView()->creationPolygon(View::MouseMove)); if (!rect().isEmpty()) { rotateTowards(line().p2(), poly.last()); } QRectF r = rect(); r.setSize(QSizeF(QLineF(line().p1(), poly.last()).length(), r.height())); setViewRect(r); return; } if (event == View::MouseRelease) { const QPolygonF poly = mapFromScene(parentView()->creationPolygon(View::MouseRelease)); parentView()->disconnect(this, SLOT(deleteLater())); //Don't delete ourself parentView()->disconnect(this, SLOT(creationPolygonChanged(View::CreationEvent))); parentView()->setMouseMode(View::Default); maybeReparent(); emit creationComplete(); return; } }
void LineItem::setLine(const QLineF &line_) { setPos(line_.p1()); setViewRect(QRectF(0.0, 0.0, 0.0, sizeOfGrip().height())); if (!rect().isEmpty()) { rotateTowards(line().p2(), line_.p2()); } QRectF r = rect(); r.setSize(QSizeF(QLineF(line().p1(), line_.p2()).length(), r.height())); setViewRect(r); }
/** We received a request to paint the drawing area. */ void CSailDispLabel::paintEvent( QPaintEvent * ) { // erase viewport CSailPainter painter( this ); QRect rect = painter.viewport(); painter.eraseRect(rect); // check if the window was resized since last redraw if ( wasResized ) { setViewRect(painter.viewRect()); wasResized = 0; } // set coordinate system to match the logical viewport painter.setWindow(logicalRect()); painter.setFontSize(8, zoom()); painter.setPenWidth(); // draw the sail const CPanelGroup obj = dispObject(); painter.draw(obj); // optionally draw labels if (drawLabels) { painter.drawLabels(obj); /*/ draw markers on edges for test purpose painter.setFontSize(10, zoom/10); painter.drawMarkers(obj); */ } // painter.end(); }
void LineItem::updateChildGeometry(const QRectF &oldParentRect, const QRectF &newParentRect) { // parent has been resized: update the line's dimensions: // we would like to have lines in terms of relative endpoint locations, // but instead they are in terms of length (relative to parent width) // and angle, relative to the parent. qreal theta = rotationAngle()*M_PI/180.0; qreal oldL = relativeWidth()*oldParentRect.width(); // we want to keep the endpoints fixed relative to the parent, so // we need to calculate new lengths and angles. qreal newDx = cos(theta)*oldL*newParentRect.width()/oldParentRect.width(); qreal newDy = sin(theta)*oldL*newParentRect.height()/oldParentRect.height(); qreal newWidth = sqrt(newDx*newDx + newDy*newDy); QTransform transform; transform.rotate(atan2(newDy, newDx)*180.0/M_PI); // my brain hurts less for rotations when we center the object at 0,0 QRectF itemRect(-newWidth*0.5, -rect().height()*0.5, newWidth, rect().height()); // we don't now what the parents's origin is, so, add .x() and .y() setPos(relativeCenter().x() * newParentRect.width() + newParentRect.x(), relativeCenter().y() * newParentRect.height()+ newParentRect.y()); setViewRect(itemRect, true); setTransform(transform); setRelativeWidth(newWidth / newParentRect.width()); }
void LayoutBoxItem::appendItem(ViewItem *item) { if (item->parentItem() == this) return; item->setParentViewItem(this); setPos(view()->sceneRect().topLeft()); setViewRect(view()->sceneRect()); }
void LayoutBoxItem::appendItem(ViewItem *item) { if (item->parentItem() == this) return; item->setParentItem(this); layout()->addViewItem(item, layout()->rowCount(), 0, 1, layout()->columnCount()); setPos(parentView()->sceneRect().topLeft()); setViewRect(parentView()->sceneRect()); //singleshot to give plots a chance to set a projection rect QTimer::singleShot(0, layout(), SLOT(update())); }
void LabelItem::applyDataLockedDimensions() { PlotRenderItem *render_item = dynamic_cast<PlotRenderItem *>(parentViewItem()); if (render_item) { qreal parentWidth = render_item->width(); qreal parentHeight = render_item->height(); qreal parentX = render_item->rect().x(); qreal parentY = render_item->rect().y(); qreal parentDX = render_item->plotItem()->xMax() - render_item->plotItem()->xMin(); qreal parentDY = render_item->plotItem()->yMax() - render_item->plotItem()->yMin(); QPointF drP1 = _dataRelativeRect.topLeft(); QPointF drP2 = _dataRelativeRect.bottomRight(); QPointF P1(parentX + parentWidth*(drP1.x()-render_item->plotItem()->xMin())/parentDX, parentY + parentHeight*(render_item->plotItem()->yMax() - drP1.y())/parentDY); QPointF P2(parentX + parentWidth*(drP2.x()-render_item->plotItem()->xMin())/parentDX, parentY + parentHeight*(render_item->plotItem()->yMax() - drP2.y())/parentDY); qreal theta = atan2(P2.y() - P1.y(), P2.x() - P1.x()); qreal height = rect().height(); qreal width = rect().width(); if (_fixleft) { setPos(P1); setViewRect(0, -height, width, height); } else { setPos(P2); setViewRect(-width, -height, width, height); } QTransform transform; transform.rotateRadians(theta); setTransform(transform); updateRelativeSize(); } else { qDebug() << "apply data locked dimensions called without a render item (!)"; } }
void CircleItem::creationPolygonChanged(View::CreationEvent event) { if (event == View::EscapeEvent) { ViewItem::creationPolygonChanged(event); return; } if (event == View::MousePress) { const QPolygonF poly = mapFromScene(view()->creationPolygon(View::MousePress)); setPos(poly.first().x(), poly.first().y()); setViewRect(QRectF(0.0, 0.0, 0.0, sizeOfGrip().height())); setRect(-2,-2,4,4); view()->scene()->addItem(this); return; } if (event == View::MouseMove) { const QPolygonF poly = mapFromScene(view()->creationPolygon(View::MouseMove)); qreal dx = poly.last().x(); qreal dy = poly.last().y(); qreal r = qMax(qreal(2.0),sqrt(dx*dx + dy*dy)); QRectF newRect(-r, -r, 2.0*r, 2.0*r); setViewRect(newRect); return; } if (event == View::MouseRelease) { const QPolygonF poly = mapFromScene(view()->creationPolygon(View::MouseRelease)); view()->disconnect(this, SLOT(deleteLater())); //Don't delete ourself view()->disconnect(this, SLOT(creationPolygonChanged(View::CreationEvent))); view()->setMouseMode(View::Default); updateViewItemParent(); emit creationComplete(); return; } }
void LabelItem::updateChildGeometry(const QRectF &oldParentRect, const QRectF &newParentRect) { Q_UNUSED(oldParentRect); QRectF itemRect = rect(); if (fixLeft()) { QPointF newBottomLeft = newParentRect.topLeft() + QPointF(newParentRect.width() * _parentRelativeLeft.x(), newParentRect.height() * _parentRelativeLeft.y()); setPos(newBottomLeft); setViewRect(QRectF(0, -itemRect.height(), itemRect.width(), itemRect.height()), true); } else { QPointF newBottomRight = newParentRect.topLeft() + QPointF(newParentRect.width() * _parentRelativeRight.x(), newParentRect.height() * _parentRelativeRight.y()); setPos(newBottomRight); setViewRect(QRectF(-itemRect.width(), -itemRect.height(), itemRect.width(), itemRect.height()), true); } //setViewRect(itemRect, true); }
LayoutBoxItem::LayoutBoxItem(View *parent) : ViewItem(parent) { setAllowsLayout(false); setTypeName("Layout Box"); storePen(Qt::NoPen); setBrush(Qt::NoBrush); setAllowedGripModes(Move); view()->scene()->addItem(this); setPos(view()->sceneRect().topLeft()); setViewRect(view()->sceneRect()); setEnabled(true); }
LayoutBoxItem::LayoutBoxItem(View *parent) : ViewItem(parent) { setName("Layout Box"); setZValue(LAYOUTBOX_ZVALUE); setPen(Qt::NoPen); setBrush(Qt::NoBrush); setAllowedGripModes(Move); parentView()->scene()->addItem(this); //setZValue(1); setPos(parentView()->sceneRect().topLeft()); setViewRect(parentView()->sceneRect()); setEnabled(true); }
LegendItem::LegendItem(PlotItem *parentPlot) : ViewItem(parentPlot->view()), _plotItem(parentPlot), _auto(true), _verticalDisplay(true) { setTypeName(tr("Legend", "a legend in a plot")); _initializeShortName(); setFixedSize(true); setAllowedGripModes(Move /*| Resize*/ /*| Rotate*/ /*| Scale*/); setViewRect(0.0, 0.0, 0.0, 0.0); view()->scene()->addItem(this); setParentViewItem(_plotItem->renderItem()); QPointF origin = QPointF(_plotItem->plotRect().width() * 0.15, _plotItem->plotRect().height() * 0.15); setPos(origin); applyDefaults(); applyDialogDefaultsStroke(); applyDialogDefaultsFill(); applyDialogDefaultsLockPosToData(); }
void LabelItem::generateLabel(QPainter *p) { double lines = 1.0; if (_labelRc) { lines = _labelRc->lines; delete _labelRc; } Label::Parsed *parsed = Label::parse(_text); if (parsed) { parsed->chunk->attributes.color = _color; _dirty = false; QFont font(_font); if (_resized) { font.setPointSizeF(view()->scaledFontSize(_scale, *p->device())); Label::RenderContext *tmpRc = new Label::RenderContext(font, p); double fs_adjust = rect().height()/(tmpRc->fontHeight()*(lines+1)); _scale *= fs_adjust; delete tmpRc; } font.setPointSizeF(view()->scaledFontSize(_scale, *p->device())); _labelRc = new Label::RenderContext(font, p); Label::renderLabel(*_labelRc, parsed->chunk, true, false); _height = _labelRc->fontHeight(); // Make sure we have a rect for selection, movement, etc if (_resized) { _resized = false; double x0 = rect().x(); double y0 = rect().y(); double x1 = x0 + rect().width(); double y1 = y0 + rect().height(); double w = _labelRc->xMax; double h = (_labelRc->lines+1) * _height; switch(_activeGrip) { case TopLeftGrip: setViewRect(QRectF(x1-w,y1-h,w,h)); break; case TopRightGrip: setViewRect(QRectF(x0,y1-h,w,h)); break; case BottomLeftGrip: setViewRect(QRectF(x1-w,y0,w,h)); break; case BottomRightGrip: case NoGrip: default: setViewRect(QRectF(x0,y0,w,h)); break; } } else { if (fixLeft()) { setViewRect(QRectF(rect().left(), rect().bottom() - (_labelRc->lines+1) * _height, _labelRc->xMax, (_labelRc->lines+1) * _height),true); } else { setViewRect(QRectF(rect().right()-_labelRc->xMax, rect().bottom() - (_labelRc->lines+1) * _height, _labelRc->xMax, (_labelRc->lines+1) * _height),true); } } _paintTransform.reset(); _paintTransform.translate(rect().x(), rect().y() + _labelRc->fontAscent()); connect(_labelRc, SIGNAL(labelDirty()), this, SLOT(setDirty())); connect(_labelRc, SIGNAL(labelDirty()), this, SLOT(triggerUpdate())); delete parsed; } }
void LegendItem::paint(QPainter *painter) { if (!isVisible()) { return; } RelationList legendItems; if (_auto) { legendItems = plot()->renderItem(PlotRenderItem::Cartesian)->relationList(); } else { legendItems = _relations; } int count = legendItems.count(); if (count <= 0) { // no legend or box if there are no legend items return; } QFont font(_font); font.setPointSizeF(view()->scaledFontSize(_fontScale, *painter->device())); painter->setFont(font); // generate string list of relation names QStringList names; bool allAuto = true; bool sameX = true; bool sameYUnits = true; LabelInfo label_info = legendItems.at(0)->xLabelInfo(); QString yUnits = legendItems.at(0)->yLabelInfo().units; for (int i = 0; i<count; i++) { RelationPtr relation = legendItems.at(i); if (relation->descriptiveNameIsManual()) { allAuto = false; } if (relation->xLabelInfo() != label_info) { sameX = false; } // sameYUnits is false if any non empty units are defined differently. if (yUnits.isEmpty()) { yUnits = relation->yLabelInfo().units; } else if (relation->yLabelInfo().units != yUnits) { if (!relation->yLabelInfo().units.isEmpty()) { sameYUnits = false; } } } if (!allAuto) { for (int i = 0; i<count; i++) { names.append(legendItems.at(i)->descriptiveName()); } } else { for (int i = 0; i<count; i++) { RelationPtr relation = legendItems.at(i); QString label = relation->titleInfo().singleRenderItemLabel(); if (label.isEmpty()) { label_info = relation->yLabelInfo(); QString y_label = label_info.name; if (!sameYUnits) { if (!label_info.units.isEmpty()) { y_label = tr("%1 \\[%2\\]", "axis labels. %1 is quantity, %2 is units. eg Time [s]. '[' must be escaped.").arg(y_label).arg(label_info.units); } } if (!y_label.isEmpty()) { LabelInfo xlabel_info = relation->xLabelInfo(); if (!sameX) { label = tr("%1 vs %2", "describes a plot. %1 is X axis. %2 is Y axis").arg(y_label).arg(xlabel_info.name); } else if (xlabel_info.quantity.isEmpty()) { label = y_label; } else if (xlabel_info.quantity != xlabel_info.name) { label = tr("%1 vs %2", "describes a plot. %1 is X axis. %2 is Y axis").arg(y_label).arg(xlabel_info.name); } else { label = y_label; } } else { label = relation->descriptiveName(); } } int i_dup = names.indexOf(label); if (i_dup<0) { names.append(label); } else { RelationPtr dup_relation = legendItems.at(i_dup); if (!dup_relation->yLabelInfo().file.isEmpty()) { names.replace(i_dup, label + " (" + dup_relation->yLabelInfo().escapedFile() + ')'); } if (!relation->yLabelInfo().file.isEmpty()) { names.append(label + " (" + relation->yLabelInfo().escapedFile() + ')'); } } } } QSize legendSize(0, 0); QSize titleSize(0,0); Label::Parsed *parsed = Label::parse(_title); int pad = painter->fontMetrics().ascent()/4; Label::RenderContext rc(painter->font(), painter); Label::renderLabel(rc, parsed->chunk, false, false); if (!_title.isEmpty()) { titleSize.setWidth(rc.x+3*pad); titleSize.setHeight(painter->fontMetrics().height()+pad); } QList<QSize> sizes; int max_w = 0; int max_h = 0; for (int i = 0; i<count; i++) { RelationPtr relation = legendItems.at(i); QSize size; painter->save(); size = paintRelation(names.at(i), relation, painter, false); painter->restore(); sizes.append(size); max_w = qMax(max_w, size.width()); max_h = qMax(max_h, size.height()); } // determine number of rows and number of columns int n_rows = 0; int n_cols = 0; if (_verticalDisplay) { int h=titleSize.height(); for (int i = 0; i<count; i++) { h+=sizes.at(i).height(); } int max_legend_height = _plotItem->plotRect().height()*0.6+1; n_cols = qMin(count, h / max_legend_height + 1); n_rows = count / n_cols; while (n_rows*n_cols<count) { n_rows++; } } else { int w = 0; for (int i = 0; i<count; i++) { w+=sizes.at(i).width(); } int max_legend_width = _plotItem->plotRect().width()*0.8+1; n_rows = qMin(count, w / max_legend_width+1); n_cols = count/n_rows; while (n_rows*n_cols<count) { n_cols++; } } // determine the dimensions of each column QList<QSize> col_sizes; for (int i=0; i<n_cols; i++) { col_sizes.append(QSize(0,0)); } for (int i = 0; i<count; i++) { int col = i/n_rows; col_sizes[col].rheight()+= sizes.at(i).height(); col_sizes[col].setWidth(qMax(sizes.at(i).width(), col_sizes.at(col).width())); } // determine the dimensions of the legend int w = 0; int h = 0; for (int col = 0; col < n_cols; col++) { w += col_sizes.at(col).width(); h = qMax(h, col_sizes.at(col).height()); } legendSize.setHeight(h + titleSize.height()); legendSize.setWidth(qMax(titleSize.width(), w)); setViewRect(rect().x(), rect().y(), legendSize.width()+pad, legendSize.height()+pad); // Now paint everything painter->drawRect(rect()); int x=rect().x(); int y=rect().y(); if (!_title.isEmpty()) { rc.y = rect().y() + titleSize.height()-pad; rc.x = qMax(rect().x()+pad, rect().x() + legendSize.width()/2 - titleSize.width()/2); Label::renderLabel(rc, parsed->chunk, false, true); y+= titleSize.height(); } legendSize.setWidth(0); legendSize.setHeight(0); for (int i = 0; i<count; i++) { RelationPtr relation = legendItems.at(i); painter->save(); painter->translate(x,y); paintRelation(names.at(i), relation, painter, true); painter->restore(); int col = i/n_rows; int row = i%n_rows; if (row == n_rows-1) { // end of a column x += col_sizes.at(col).width(); y = rect().y() + titleSize.height(); } else { y += sizes.at(i).height(); } } delete parsed; }
void LegendItem::paint(QPainter *painter) { if (!isVisible()) { return; } RelationList legendItems; if (_auto) { legendItems = plot()->renderItem(PlotRenderItem::Cartesian)->relationList(); } else { legendItems = _relations; } int count = legendItems.count(); if (count <= 0) { // no legend or box if there are no legend items return; } QList<DrawnLegendItem> legendPixmaps; QSize legendSize(0, 0); QFont font(_font); font.setPointSizeF(view()->viewScaledFontSize(_fontScale)); // generate string list of relation names QStringList names; bool allAuto = true; bool sameX = true; bool sameYUnits = true; LabelInfo label_info = legendItems.at(0)->xLabelInfo(); QString yUnits = legendItems.at(0)->yLabelInfo().units; for (int i = 0; i<count; i++) { RelationPtr relation = legendItems.at(i); if (relation->descriptiveNameIsManual()) { allAuto = false; } if (relation->xLabelInfo() != label_info) { sameX = false; } // sameYUnits is false if any non empty units are defined differently. if (yUnits.isEmpty()) { yUnits = relation->yLabelInfo().units; } else if (relation->yLabelInfo().units != yUnits) { if (!relation->yLabelInfo().units.isEmpty()) { sameYUnits = false; } } } if (!allAuto) { for (int i = 0; i<count; i++) { names.append(legendItems.at(i)->descriptiveName()); } } else { for (int i = 0; i<count; i++) { RelationPtr relation = legendItems.at(i); QString label = relation->titleInfo().singleRenderItemLabel(); if (label.isEmpty()) { label_info = relation->yLabelInfo(); QString y_label = label_info.name; if (!sameYUnits) { if (!label_info.units.isEmpty()) { y_label = i18n("%1 \\[%2\\]").arg(y_label).arg(label_info.units); } } if (!y_label.isEmpty()) { LabelInfo xlabel_info = relation->xLabelInfo(); if (!sameX) { label = i18n("%1 vs %2").arg(y_label).arg(xlabel_info.name); } else if (xlabel_info.quantity.isEmpty()) { label = y_label; } else if (xlabel_info.quantity != xlabel_info.name) { label = i18n("%1 vs %2").arg(y_label).arg(xlabel_info.name); } else { label = y_label; } } else { label = relation->descriptiveName(); } } int i_dup = names.indexOf(label); if (i_dup<0) { names.append(label); } else { RelationPtr dup_relation = legendItems.at(i_dup); if (!dup_relation->yLabelInfo().file.isEmpty()) { names.replace(i_dup, label + " (" + dup_relation->yLabelInfo().file + ')'); } if (!relation->yLabelInfo().file.isEmpty()) { names.append(label + " (" + relation->yLabelInfo().file + ')'); } } } } for (int i = 0; i<count; i++) { RelationPtr relation = legendItems.at(i); DrawnLegendItem item; item.pixmap = QPixmap(LEGENDITEMMAXWIDTH, LEGENDITEMMAXHEIGHT); item.size = paintRelation(names.at(i), relation, &item.pixmap, font); if (_verticalDisplay) { legendSize.setWidth(qMax(legendSize.width(), item.size.width())); legendSize.setHeight(legendSize.height() + item.size.height()); } else { legendSize.setHeight(qMax(legendSize.height(), item.size.height())); legendSize.setWidth(legendSize.width() + item.size.width()); } legendPixmaps.append(item); } int x = rect().left(); int y = rect().top(); painter->save(); if (!_title.isEmpty()) { // Paint the title Label::Parsed *parsed = Label::parse(_title); if (parsed) { painter->save(); QPixmap pixmap(400, 100); pixmap.fill(Qt::transparent); QPainter pixmapPainter(&pixmap); Label::RenderContext rc(font, &pixmapPainter); QFontMetrics fm(font); rc.y = fm.ascent(); Label::renderLabel(rc, parsed->chunk, false); int startPoint = qMax(0, (legendSize.width() / 2) - (rc.x / 2)); int paddingValue = fm.height() / 4; setViewRect(viewRect().x(), viewRect().y(), qMax(rc.x, legendSize.width()), rc.y + legendSize.height() + paddingValue * 3); painter->drawRect(rect()); painter->drawPixmap(QPoint(x + startPoint, y + paddingValue), pixmap, QRect(0, 0, rc.x, fm.height())); painter->restore(); y += fm.height() + (paddingValue *2); delete parsed; parsed = 0; } } else { // No Title setViewRect(viewRect().x(), viewRect().y(), legendSize.width(), legendSize.height()); painter->drawRect(rect()); } foreach(const DrawnLegendItem &item, legendPixmaps) { painter->drawPixmap(QPoint(x, y), item.pixmap, QRect(0, 0, item.size.width(), item.size.height())); if (_verticalDisplay) { y += item.size.height(); } else { x += item.size.width(); } }
void LineItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { if (view()->viewMode() == View::Data) { event->ignore(); return; } if (!dragStartPosition.isNull() && event->buttons() & Qt::LeftButton) { if (view()->mouseMode() == View::Move) { startDragging(event->widget(), dragStartPosition.toPoint()); return; } } if (view()->mouseMode() == View::Default) { if (gripMode() == ViewItem::Move || activeGrip() == NoGrip) { view()->setMouseMode(View::Move); view()->undoStack()->beginMacro(tr("Move")); } else if (gripMode() == ViewItem::Resize) { view()->setMouseMode(View::Resize); view()->undoStack()->beginMacro(tr("Resize")); } } if (activeGrip() == NoGrip) return QGraphicsRectItem::mouseMoveEvent(event); double width = 0; double height = 0; double theta = 0; QPointF centerP; QPointF P1, P2; if (gripMode() == ViewItem::Resize) { switch(activeGrip()) { case RightMidGrip: P1 = mapToParent(QPoint(rect().left(), rect().center().y())); P2 = mapToParent(event->pos()); break; case LeftMidGrip: P1 = mapToParent(event->pos()); P2 = mapToParent(QPoint(rect().right(), rect().center().y())); break; default: return; } centerP = (P1 + P2) * 0.5; theta = atan2(P2.y() - P1.y(), P2.x() - P1.x()); height = rect().height(); double dx = P1.x() - P2.x(); double dy = P1.y() - P2.y(); width = sqrt(dx*dx + dy*dy)+1.0; if (activeGrip() == RightMidGrip) { setPos(P1); setViewRect(0,-height*0.5,width,height); } else if (activeGrip() == LeftMidGrip) { setPos(P2); setViewRect(-width, -height*0.5, width, height); } //setPos(centerP.x(), centerP.y()); //setViewRect(-width*0.5, -height*0.5, width, height); QTransform transform; transform.rotateRadians(theta); setTransform(transform); updateRelativeSize(true); } }