QPainterPath makePath(const int triRadius, const int triHeight, qreal y) { QPainterPath path; for(const QPair<qreal, qreal> &range : ranges) { if(range.first == range.second) { QPointF pos = aliasAlign(QPointF(range.first, y)); QPainterPath triangle; triangle.addPolygon( QPolygonF({pos + QPoint(0, triHeight), pos + QPoint(triRadius * 2, triHeight), pos + QPoint(triRadius, 0)})); triangle.closeSubpath(); path = path.united(triangle); } else { QPointF left = aliasAlign(QPointF(range.first, y)); QPointF right = aliasAlign(QPointF(range.second, y)); QPainterPath trapezoid; trapezoid.addPolygon( QPolygonF({left + QPoint(0, triHeight), right + QPoint(triRadius * 2, triHeight), right + QPoint(triRadius, 0), left + QPoint(triRadius, 0)})); trapezoid.closeSubpath(); path = path.united(trapezoid); } } return path; }
QPainterPath CrossOverItem::makePath(const QPointF& from, const QPointF& to) const { const qreal radius = settings::Loader::getStationRadius() + 5.0; QPolygonF by_x = QPolygonF() << QPointF(from.x(), from.y()-radius) << QPointF(from.x(), from.y()+radius) << QPointF(to.x(), to.y()+radius) << QPointF(to.x(), to.y()-radius); by_x.append(by_x.first()); QPolygonF by_y = QPolygonF() << QPointF(from.x()-radius, from.y()) << QPointF(from.x()+radius, from.y()) << QPointF(to.x()+radius, to.y()) << QPointF(to.x()-radius, to.y()); by_y.append(by_y.first()); QPainterPath start; start.addEllipse(from, radius, radius); QPainterPath body_x; body_x.addPolygon(by_x); QPainterPath body_y; body_y.addPolygon(by_y); QPainterPath end; end.addEllipse(to, radius, radius); QPainterPath result = start.united(body_x); result = result.united(body_y); result = result.united(end); return result; }
QPainterPath UBGraphicsCompass::shape() const { QPainterPath path = needleShape(); path = path.united(needleBaseShape()); path = path.united(needleArmShape()); path.addRect(hingeRect()); path = path.united(pencilArmShape()); path = path.united(pencilBaseShape()); path = path.united(pencilShape()); return path; }
void KarbonBooleanCommand::redo() { if (! d->resultingPath) { // transform input pathes to global coordinates QPainterPath pa = d->pathA->absoluteTransformation(0).map(d->pathA->outline()); QPainterPath pb = d->pathB->absoluteTransformation(0).map(d->pathB->outline()); QPainterPath pr; switch (d->operation) { case Intersection: pr = pa.intersected(pb); break; case Subtraction: pr = pa.subtracted(pb); break; case Exclusion: pr = pa.subtracted(pb); pr.addPath(pb.subtracted(pa)); break; case Union: pr = pa.united(pb); break; } QTransform transformationA = d->pathA->absoluteTransformation(0); // transform resulting path to local coordinate system of input path A pr = transformationA.inverted().map(pr); // create a path shape from the resulting path in local coordinates d->resultingPath = KoPathShape::createShapeFromPainterPath(pr); d->resultingPath->setStroke(d->pathA->stroke()); d->resultingPath->setBackground(d->pathA->background()); d->resultingPath->setShapeId(d->pathA->shapeId()); // the created shape has a transformation applied so we have to // apply the original transformation instead of replacing with it d->resultingPath->applyAbsoluteTransformation(transformationA); d->resultingPath->setName(d->pathA->name()); d->resultingPath->setZIndex(d->pathA->zIndex()); d->resultingPath->setFillRule(d->pathA->fillRule()); KoShapeGroup * group = dynamic_cast<KoShapeGroup*>(d->pathA->parent()); if (group) { QList<KoShape*> children; d->resultParentCmd = new KoShapeGroupCommand(group, children << d->resultingPath, this); } } if (d->shapeBasedDocument) { if (d->resultParent) d->resultParent->addShape(d->resultingPath); d->shapeBasedDocument->addShape(d->resultingPath); } KUndo2Command::redo(); d->isExecuted = true; }
void SpeechBubble::paintEvent(QPaintEvent * event) { QPainter painter(this); painter.setRenderHint(QPainter::TextAntialiasing, true); painter.setRenderHint(QPainter::Antialiasing, true); QRect rect = this->rect().adjusted(1,1,-1,-1); int pipWidth = 10; int pipOffset = 24; QPainterPath bubbleRect; if (!_reversed) { bubbleRect.addRoundedRect(QRect(rect.topLeft()+QPoint(pipWidth,0), rect.bottomRight()),5,5); } else { bubbleRect.addRoundedRect(QRect(rect.topLeft(), rect.bottomRight()-QPoint(pipWidth,0)),5,5); } QPainterPath bubblePip; QPoint start; if (!_reversed) { start = rect.topLeft()+QPoint(0,pipOffset); bubblePip.moveTo(start); bubblePip.lineTo(start+QPoint(pipWidth+1,-pipWidth)); bubblePip.lineTo(start+QPoint(pipWidth+1,pipWidth)); bubblePip.lineTo(start); } else { start = rect.topRight()+QPoint(0,pipOffset); bubblePip.moveTo(start); bubblePip.lineTo(start-QPoint(pipWidth+1,-pipWidth)); bubblePip.lineTo(start-QPoint(pipWidth+1,pipWidth)); bubblePip.lineTo(start); } QPainterPath bubble = bubblePip.united(bubbleRect); painter.setBrush(this->color); painter.setPen(Qt::black); painter.drawPath(bubble); }
void KarbonBooleanCommand::redo() { if (! d->resultingPath) { QPainterPath pa = d->pathA->absoluteTransformation(0).map(d->pathA->outline()); QPainterPath pb = d->pathB->absoluteTransformation(0).map(d->pathB->outline()); QPainterPath pr; switch (d->operation) { case Intersection: pr = pa.intersected(pb); break; case Subtraction: pr = pa.subtracted(pb); break; case Exclusion: pr = pa.subtracted(pb); pr.addPath(pb.subtracted(pa)); break; case Union: pr = pa.united(pb); break; } QTransform transformation = d->pathA->transformation(); pr = transformation.inverted().map(pr); d->resultingPath = KoPathShape::createShapeFromPainterPath(pr); d->resultingPath->setBorder(d->pathA->border()); d->resultingPath->setBackground(d->pathA->background()); d->resultingPath->setShapeId(d->pathA->shapeId()); d->resultingPath->setTransformation(transformation); d->resultingPath->setName(d->pathA->name()); d->resultingPath->setZIndex(d->pathA->zIndex()); d->resultingPath->setFillRule(d->pathA->fillRule()); KoShapeGroup * group = dynamic_cast<KoShapeGroup*>(d->pathA->parent()); if (group) { QList<KoShape*> children; d->resultParentCmd = new KoShapeGroupCommand(group, children << d->resultingPath, this); } } if (d->controller) { if (d->resultParent) d->resultParent->addShape(d->resultingPath); d->controller->addShape(d->resultingPath); } QUndoCommand::redo(); d->isExecuted = true; }
void tst_QPainterPath::operators_data() { QTest::addColumn<QPainterPath>("test"); QTest::addColumn<QPainterPath>("expected"); QPainterPath a; QPainterPath b; a.addRect(0, 0, 100, 100); b.addRect(50, 50, 100, 100); QTest::newRow("a & b") << (a & b) << a.intersected(b); QTest::newRow("a | b") << (a | b) << a.united(b); QTest::newRow("a + b") << (a + b) << a.united(b); QTest::newRow("a - b") << (a - b) << a.subtracted(b); QPainterPath c = a; QTest::newRow("a &= b") << (a &= b) << a.intersected(b); c = a; QTest::newRow("a |= b") << (a |= b) << a.united(b); c = a; QTest::newRow("a += b") << (a += b) << a.united(b); c = a; QTest::newRow("a -= b") << (a -= b) << a.subtracted(b); }
QPainterPath DrawingPolygonItem::shape() const { // This code should work, but doesn't QPainterPath path; QList<DrawingItemPoint*> points = DrawingPolygonItem::points(); path.moveTo(points.first()->pos()); for(auto pointIter = points.begin()+1; pointIter != points.end(); pointIter++) path.lineTo((*pointIter)->pos()); path.closeSubpath(); QPainterPath shape = itemShapeFromPath(path, pen()); if (brush().color().alpha() > 0) shape = shape.united(path); return shape; }
void TableGesture::paintCellSelection(QPainter* p) { if (!m_table || !m_canvas || !p) return; p->save(); p->scale(m_canvas->scale(), m_canvas->scale()); p->translate(-m_doc->minCanvasCoordinate.x(), -m_doc->minCanvasCoordinate.y()); p->setTransform(m_table->getTransform(), true); p->setRenderHint(QPainter::Antialiasing); p->setPen(QPen(QColor(100, 200, 255), 3.0 / m_canvas->scale(), Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin)); p->setBrush(QColor(100, 200, 255, 50)); /* * The code below makes selectionPath a union of the cell rectangles of the selected cells. * Since the cell rectangles are adjacent, they must be expanded slightly (1.0) for the * uniting to work. This may not be the fastest way to compose the path of the selection, * but it makes for some very simple code. And the result looks good. */ const QPointF offset = m_table->gridOffset(); QPainterPath selectionPath; foreach (const TableCell& cell, m_table->selectedCells()) { QRectF cellRect = cell.boundingRect(); cellRect.translate(offset); cellRect.adjust(-1.0, -1.0, 1.0, 1.0); QPainterPath cellPath; cellPath.addRect(cellRect); selectionPath = selectionPath.united(cellPath); } p->drawPath(selectionPath); p->restore(); }
void QSanCommandProgressBar::paintEvent(QPaintEvent *e) { m_mutex.lock(); int val = this->m_val; int max = this->m_max; m_mutex.unlock(); int width = this->width(); int height = this->height(); QPainter painter(this); painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); if (orientation() == Qt::Vertical) { painter.translate(0, height); qSwap(width, height); painter.rotate(-90); } painter.drawPixmap(0, 0, width, height, m_progBg); double percent = 1 - (double)val / (double)max; QRectF rect = QRectF(0, 0, percent * width, height); //ÒÔrectµÄÓÒ±ßΪÖÐÖᣬ7Ϊ°ë¾¶»Ò»¸öÍÖÔ² QRectF ellipseRect; ellipseRect.setTopLeft(QPointF(rect.right() - 7, rect.top())); ellipseRect.setBottomRight(QPointF(rect.right() + 7, rect.bottom())); QPainterPath rectPath; QPainterPath ellipsePath; rectPath.addRect(rect); ellipsePath.addEllipse(ellipseRect); QPainterPath polygonPath = rectPath.united(ellipsePath); painter.setClipPath(polygonPath); painter.drawPixmap(0, 0, width, height, m_prog); }
void tSunMoonDialog::ProcessMoonPixmap( QPixmap& moonPixmap ) { if( m_MoonData.Phase < 0.99 ) { QRect r = moonPixmap.rect(); qreal diameter = r.width() * 0.744; QRectF rF( r.center().x() - 0.5 - diameter / 2, r.center().y() + 1 - diameter / 2, diameter, diameter ); QPainterPath darkMoonPath; if( m_MoonData.Phase > 0.01 ) { QPainterPath halfMoonPath; halfMoonPath.moveTo( rF.left() + rF.width() / 2, rF.top() + rF.height() ); qreal sweep = 180; if( m_MoonData.Waxing ) { sweep *= -1; } halfMoonPath.arcTo( rF.left(), rF.top(), diameter, diameter, 90, sweep ); halfMoonPath.lineTo( rF.left() + rF.width() / 2, rF.top() ); QPainterPath cresentMoonPath; cresentMoonPath.addEllipse( rF.center(), diameter * cos( m_MoonData.Phase * M_PI ) / 2, diameter / 2 ); if( m_MoonData.Phase < 0.5 ) { darkMoonPath = halfMoonPath.united( cresentMoonPath ); } else { darkMoonPath = halfMoonPath.subtracted( cresentMoonPath ); } } else { darkMoonPath.addEllipse( rF.center(), diameter / 2, diameter / 2 ); } QPainter painter( &moonPixmap ); painter.setRenderHint( QPainter::Antialiasing ); painter.setPen( Qt::NoPen ); QColor c( 0, 0, 0, 170 ); painter.setBrush( QBrush( c ) ); painter.drawPath( darkMoonPath ); painter.end(); } // invert the image if in northern hemisphere if( m_Position.Y() >= 0 ) { QPixmap tempPixmap( moonPixmap ); moonPixmap.fill( QColor( 0, 0, 0, 0 ) ); QPainter painter( &moonPixmap ); painter.rotate( 180 ); painter.drawPixmap( QPoint( -moonPixmap.width(), -moonPixmap.height() ), tempPixmap ); painter.end(); } }
QPainterPath ArtisticTextToolSelection::outline() { if (!hasSelection()) return QPainterPath(); CharIndex charPos = m_currentShape->indexOfChar(m_selectionStart); if (charPos.first < 0) return QPainterPath(); QPainterPath outline; QPolygonF polygon; QList<ArtisticTextRange> ranges = m_currentShape->text(); if (ranges.size() == 0) return outline; int globalCharIndex = m_selectionStart; int remainingChars = m_selectionCount; while (remainingChars) { const ArtisticTextRange ¤tRange = ranges[charPos.first]; int currentTextLength = currentRange.text().length(); while (charPos.second < currentTextLength && remainingChars > 0) { const QPointF pos = m_currentShape->charPositionAt(globalCharIndex); const qreal angle = m_currentShape->charAngleAt(globalCharIndex); QTransform charTransform; charTransform.translate( pos.x() - 1, pos.y() ); charTransform.rotate( 360. - angle ); QFontMetricsF metrics(currentRange.font()); polygon.prepend(charTransform.map(QPointF(0.0, -metrics.ascent()))); polygon.append(charTransform.map(QPointF(0.0, metrics.descent()))); // advance to next character charPos.second++; globalCharIndex++; remainingChars--; // next character has y-offset or we are at the end of this text range const bool hasYOffset = currentRange.hasYOffset(charPos.second); const bool atRangeEnd = charPos.second == currentTextLength; const bool atSelectionEnd = remainingChars == 0; if (hasYOffset || atRangeEnd || atSelectionEnd) { if (hasYOffset || atRangeEnd) { const QChar c = currentRange.text().at(charPos.second-1); const qreal w = metrics.width(c); polygon.prepend(charTransform.map(QPointF(w, -metrics.ascent()))); polygon.append(charTransform.map(QPointF(w, metrics.descent()))); } else { const QPointF pos = m_currentShape->charPositionAt(globalCharIndex); const qreal angle = m_currentShape->charAngleAt(globalCharIndex); charTransform.reset(); charTransform.translate( pos.x() - 1, pos.y() ); charTransform.rotate( 360. - angle ); polygon.prepend(charTransform.map(QPointF(0.0, -metrics.ascent()))); polygon.append(charTransform.map(QPointF(0.0, metrics.descent()))); } QPainterPath p; p.addPolygon(polygon); outline = outline.united(p); polygon.clear(); } } // go to first character of next text range charPos.first++; charPos.second = 0; } // transform to document coordinates return m_currentShape->absoluteTransformation(0).map(outline); }
void MovableWidget::paintEvent(QPaintEvent*) { int shadow = 3; QPoint centerCard = rect().center(); QPainterPath arrow; QPointF arrowTarget = rect().bottomRight(); qreal arrowSize = 100; QRectF internalCard(QPointF(0, 0), QSizeF(rect().size() - QSizeF(arrowSize, arrowSize))); qreal arrowGuideX1 = arrowTarget.x(); qreal arrowGuideY1 = arrowTarget.y(); qreal arrowGuideX2 = centerCard.x(); qreal arrowGuideY2 = centerCard.y(); qreal a = 90; if (arrowGuideX1 != arrowGuideX2) { qreal k = (arrowGuideY1 - arrowGuideY2) / (arrowGuideX1 - arrowGuideX2); a = atan(k) * 180 / M_PI; } arrow.moveTo(arrowTarget); arrow.lineTo( arrowGuideX2 + 100 * cos((a - 90) * (M_PI / 180)), arrowGuideY2 + 100 * sin((a - 90) * (M_PI / 180))); arrow.lineTo( arrowGuideX2 + 100 * cos((a + 90) * (M_PI / 180)), arrowGuideY2 + 100 * sin((a + 90) * (M_PI / 180))); arrow.lineTo(arrowTarget); QPainterPath path; path.setFillRule(Qt::WindingFill); path.addRoundedRect(internalCard.x(), internalCard.y(), internalCard.width() - shadow, internalCard.height() - shadow, 5, 5, Qt::AbsoluteSize); QPainterPath cardPath = path.united(arrow); QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); painter.setRenderHint(QPainter::TextAntialiasing, true); painter.setRenderHint(QPainter::SmoothPixmapTransform, false); painter.setRenderHint(QPainter::NonCosmeticDefaultPen, false); painter.setCompositionMode(QPainter::CompositionMode_SourceOver); // shadow cardPath.translate(shadow, shadow); painter.fillPath(cardPath, QColor(255, 0, 0)); cardPath.translate(-shadow, -shadow); painter.setPen(QColor(0, 0, 0)); painter.fillPath(cardPath, QColor(255, 255, 255)); QPainterPath topPath; topPath.addRect(internalCard.x(), internalCard.y(), internalCard.width() - shadow, 19); topPath = path.intersected(topPath); painter.fillPath(topPath, QColor(127, 127, 127)); QLinearGradient gradient(internalCard.x(), internalCard.y() + 19, internalCard.x(), internalCard.y() + 19 + 23); gradient.setColorAt(0, GRADIENT_0); gradient.setColorAt(1, GRADIENT_1); QPainterPath top2Path; top2Path.addRect(internalCard.x(), internalCard.y() + 19, internalCard.width() - shadow, 23); top2Path = path.intersected(top2Path); painter.fillPath(top2Path, QBrush(gradient)); painter.drawPath(cardPath); }
void FrequencyPlotVRuler::paintEvent(QPaintEvent*) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); FrequencyPlotView* view = qobject_cast<FrequencyPlotView*>(parentWidget()); FrequencyPlotScene* s = view->scene(); QPointF topLeft = view->mapToScene(0, 0); QPointF bottomRight = view->mapToScene(view->viewport()->width(), view->viewport()->height()); double dbStep = abs(s->yToDb(0) - s->yToDb(30)); double dbBase = pow(10, floor(log10(dbStep))); if (dbStep >= 5 * dbBase) dbStep = 5 * dbBase; else if (dbStep >= 2 * dbBase) dbStep = 2 * dbBase; else dbStep = dbBase; double fromDb = floor(s->yToDb(topLeft.y()) / dbStep) * dbStep; double toDb = ceil(s->yToDb(bottomRight.y()) / dbStep) * dbStep; painter.setPen(QColor(50, 50, 50)); for (double db = toDb; db <= fromDb; db += dbStep) { if (abs(db) < 1e-6) db = 0; double y = s->dbToY(db); if (y != -1) painter.drawText(0, y - topLeft.y() - 1, width(), 0, Qt::TextDontClip | Qt::AlignCenter, QString("%0").arg(db)); } QPoint mousePos = view->getLastMousePos(); if (!mousePos.isNull()) { QPointF mouseScenePos = view->mapToScene(mousePos); double db = s->yToDb(mouseScenePos.y()); double y = s->dbToY(db); if (y != -1) { QString text = QString("%0").arg(db, 0, 'f', 1); QFontMetrics metrics = painter.fontMetrics(); QRectF rect = metrics.boundingRect(text); float center = y - topLeft.y() - 1; rect = QRectF(ceil(width() / 2) - ceil(rect.width() / 2) - 2.5, center - rect.height() / 2 + 1, rect.width() + 3, rect.height()); QPainterPath path; path.addRect(rect); QPainterPath rightTriangle; rightTriangle.moveTo(QPoint(rect.right(), center - 2)); rightTriangle.lineTo(QPoint(rect.right(), center + 4)); rightTriangle.lineTo(QPoint(rect.right() + 4, center + 1)); path = path.united(rightTriangle); painter.setPen(Qt::black); painter.setBrush(Qt::white); painter.drawPath(path); painter.setPen(Qt::blue); painter.drawText(0, center, width() - 2, 0, Qt::TextDontClip | Qt::AlignCenter, text); } } }
void FrequencyPlotHRuler::paintEvent(QPaintEvent*) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); FrequencyPlotView* view = qobject_cast<FrequencyPlotView*>(parentWidget()); FrequencyPlotScene* s = view->scene(); QFontMetrics metrics = painter.fontMetrics(); painter.setPen(QColor(50, 50, 50)); QPointF topLeft = view->mapToScene(0, 0); QPointF bottomRight = view->mapToScene(view->viewport()->width(), view->viewport()->height()); int offsetLeft = view->viewportMargins().left(); double fromHz = s->xToHz(topLeft.x()); double toHz = s->xToHz(bottomRight.x()); const vector<double>& bands = s->getBands(); if (bands.empty()) { double hzBase = pow(10, floor(log10(fromHz))); fromHz = floor(fromHz / hzBase) * hzBase; fromHz += hzBase; if (round(fromHz / hzBase) >= 10) hzBase *= 10; for (double hz = fromHz; hz <= toHz;) { double x = s->hzToX(hz); if (x != -1) { QString text; if (hz < 1000) text = QString("%0").arg(hz); else text = QString("%0k").arg(hz / 1000); if (metrics.width(text) + 2 < s->hzToX(hz + hzBase) - x) painter.drawText(x - topLeft.x() + offsetLeft + 1, 0, 0, height(), Qt::TextDontClip | Qt::AlignCenter, text); } hz += hzBase; if (round(hz / hzBase) >= 10) hzBase *= 10; } } else { vector<double>::const_iterator it = lower_bound(bands.cbegin(), bands.cend(), fromHz); for (; it != bands.cend() && *it < toHz; it++) { double hz = *it; double x = s->hzToX(hz); if (x != -1) { QString text; if (hz < 1000) text = QString("%0").arg(hz); else text = QString("%0k").arg(hz / 1000); painter.drawText(x - topLeft.x() + offsetLeft + 1, 0, 0, height(), Qt::TextDontClip | Qt::AlignCenter, text); } } } QPoint mousePos = view->getLastMousePos(); if (!mousePos.isNull()) { QPointF mouseScenePos = view->mapToScene(mousePos); double hz = s->xToHz(mouseScenePos.x()); double x = s->hzToX(hz); if (x != -1) { QString text = QString("%0").arg(hz, 0, 'f', 1); QFontMetrics metrics = painter.fontMetrics(); QRectF rect = metrics.boundingRect(text); float center = x - topLeft.x() + offsetLeft + 1; rect = QRectF(center - ceil(rect.width() / 2) - 2 + 0.5, ceil(height() / 2) - ceil(rect.height() / 2) + 1.5, rect.width() + 3, rect.height()); QPainterPath path; path.addRect(rect); QPainterPath topTriangle; topTriangle.moveTo(QPoint(center - 3, rect.top() + 1)); topTriangle.lineTo(QPoint(center + 3, rect.top() + 1)); topTriangle.lineTo(QPoint(center, rect.top() - 3)); path = path.united(topTriangle); painter.setPen(Qt::black); painter.setBrush(Qt::white); painter.drawPath(path); painter.setPen(Qt::blue); painter.drawText(center, 0, 0, height(), Qt::TextDontClip | Qt::AlignCenter, text); } } }
// This function generates puzzle piece shapes. // ---------- // unit - the size of the rectangular base of the puzzle piece // status - flags of TabStatus values that describe the shape of this puzzle piece // tabFull - the full size of tabs including stroke, offset, tolerance // tabSize - size of tabs // tabOffset - offset of tabs (meaning: how far away they are from the edge of the piece) // tabTolerance - extra size to the tabs (so that merging works flawlessly, without visual artifacts) // blankSize - size of blanks // blankOffset - offset of blanks (meaning: how far away they are from the edge of the piece) // ---------- static QPainterPath createPuzzleShape(QSize unit, int status, qreal tabFull, qreal tabSize, qreal tabOffset, qreal tabTolerance, qreal blankSize, qreal blankOffset) { QPainterPath rectClip; rectClip.addRect(tabFull - 1, tabFull - 1, unit.width() + 1, unit.height() + 1); QPainterPath clip = rectClip; // Left if (status & Puzzle::Creation::LeftBlank) { QPainterPath leftBlank; leftBlank.addEllipse(QPointF(tabFull + blankOffset, tabFull + unit.height() / 2.0), blankSize, blankSize); clip = clip.subtracted(leftBlank); } else if (status & Puzzle::Creation::LeftTab) { QPainterPath leftTab; leftTab.addEllipse(QPointF(tabSize + tabTolerance, tabFull + unit.height() / 2.0), tabSize + tabTolerance, tabSize + tabTolerance); clip = clip.united(leftTab); } // Top if (status & Puzzle::Creation::TopBlank) { QPainterPath topBlank; topBlank.addEllipse(QPointF(tabFull + unit.width() / 2.0, tabFull + blankOffset), blankSize, blankSize); clip = clip.subtracted(topBlank); } else if (status & Puzzle::Creation::TopTab) { QPainterPath topTab; topTab.addEllipse(QPointF(tabFull + unit.width() / 2.0, tabSize + tabTolerance), tabSize + tabTolerance, tabSize + tabTolerance); clip = clip.united(topTab); } // Right if (status & Puzzle::Creation::RightTab) { QPainterPath rightTab; rightTab.addEllipse(QPointF(tabFull + unit.width() + tabOffset, tabFull + unit.height() / 2.0), tabSize + tabTolerance, tabSize + tabTolerance); clip = clip.united(rightTab); } else if (status & Puzzle::Creation::RightBlank) { QPainterPath rightBlank; rightBlank.addEllipse(QPointF(tabFull + unit.width() - blankOffset, tabFull + unit.height() / 2.0), blankSize, blankSize); clip = clip.subtracted(rightBlank); } // Bottom if (status & Puzzle::Creation::BottomTab) { QPainterPath bottomTab; bottomTab.addEllipse(QPointF(tabFull + unit.width() / 2.0, tabFull + unit.height() + tabOffset), tabSize + tabTolerance, tabSize + tabTolerance); clip = clip.united(bottomTab); } else if (status & Puzzle::Creation::BottomBlank) { QPainterPath bottomBlank; bottomBlank.addEllipse(QPointF(tabFull + unit.width() / 2.0, tabFull + unit.height() - blankOffset), blankSize, blankSize); clip = clip.subtracted(bottomBlank); } clip = clip.simplified(); return clip; }
GraphicsPortItem::GraphicsPortItem(GraphicsClientItemsClient *client_, const QString &fullPortName_, int style_, QFont font_, int padding, QGraphicsItem *parent) : QGraphicsPathItem(parent), client(client_), fullPortName(fullPortName_), shortPortName(fullPortName.split(":")[1]), dataType(client->getPortType(fullPortName)), isInput(client->getPortFlags(fullPortName) & JackPortIsInput), style(style_), font(font_), showMenu(false) { bool gradient = false; QColor captionColor(0xfc, 0xf9, 0xc2); setPen(QPen(QBrush(Qt::black), 2)); setBrush(QBrush(captionColor)); setFlags(QGraphicsItem::ItemSendsScenePositionChanges); setCursor(Qt::ArrowCursor); font.setStyleStrategy(QFont::PreferAntialias); QFontMetrics fontMetrics(font); int portPadding = padding; QGraphicsSimpleTextItem *portTextItem = new QGraphicsSimpleTextItem(shortPortName, this); portTextItem->setFont(font); portTextItem->setPos(portPadding, 0); portRect = portTextItem->boundingRect().adjusted(-portPadding, -portPadding, portPadding, portPadding).translated(portTextItem->pos()); QPainterPath portPath; if (style == 0) { portPath = portPath.united(EllipsePath(portRect)); } else if (style == 1) { portPath = portPath.united(SpeechBubblePath(portRect, portRect.height() / 4, portRect.height() / 4, Qt::AbsoluteSize)); } else if (style == 2) { portPath = portPath.united(RoundedRectanglePath(portRect, portPadding + fontMetrics.height() / 2, portPadding + fontMetrics.height() / 2)); } else if (style == 3) { portPath = portPath.united(RectanglePath(portRect)); } setPath(portPath); // register the port registration callback at the jack server: QObject::connect(client, SIGNAL(portRegistered(QString,QString,int)), this, SLOT(onPortRegistered(QString,QString,int)), Qt::QueuedConnection); QObject::connect(client, SIGNAL(portUnregistered(QString,QString,int)), this, SLOT(onPortUnregistered(QString,QString,int)), Qt::QueuedConnection); QObject::connect(client, SIGNAL(portConnected(QString,QString)), this, SLOT(onPortConnected(QString,QString)), Qt::QueuedConnection); QObject::connect(client, SIGNAL(portDisconnected(QString,QString)), this, SLOT(onPortDisconnected(QString,QString)), Qt::QueuedConnection); if (gradient) { QLinearGradient gradient(portRect.topLeft(), portRect.bottomRight()); gradient.setColorAt(0, Qt::white); gradient.setColorAt(1, QColor("wheat")); setBrush(QBrush(gradient)); } // create the context menu: connectMenu = contextMenu.addMenu("Connect"); disconnectMenu = contextMenu.addMenu("Disconnect"); // create the entries in connect- and disconnect-menus, as well as graphical representations of existing connections: QStringList connectedPorts = client->getConnectedPorts(fullPortName); QSet<QString> connectedPortsSet; for (int i = 0; i < connectedPorts.size(); i++) { // create an entry in the disconnect-menu: QAction *action = disconnectMenu->addAction(connectedPorts[i]); action->setData(connectedPorts[i]); QObject::connect(action, SIGNAL(triggered()), this, SLOT(onDisconnectAction())); mapPortNamesToActions[connectedPorts[i]] = action; connectedPortsSet.insert(connectedPorts[i]); // create a graphical representation of the connection: if (isInput) { client->getPortConnectionItem(connectedPorts[i], fullPortName)->setPos(fullPortName, getConnectionScenePos()); } else { client->getPortConnectionItem(fullPortName, connectedPorts[i])->setPos(fullPortName, getConnectionScenePos()); } } // get all available ports that can be connected to this: QStringList connectablePorts = client->getPorts(0, dataType.toAscii().data(), isInput ? JackPortIsOutput : JackPortIsInput); for (int i = 0; i < connectablePorts.size(); i++) { // skip ports that are already connected: if (!connectedPortsSet.contains(connectablePorts[i])) { // create an entry in the connect-menu: QAction *action = connectMenu->addAction(connectablePorts[i]); action->setData(connectablePorts[i]); QObject::connect(action, SIGNAL(triggered()), this, SLOT(onConnectAction())); mapPortNamesToActions[connectablePorts[i]] = action; } } disconnectMenu->setEnabled(disconnectMenu->actions().size()); connectMenu->setEnabled(connectMenu->actions().size()); }