void tst_applicationwindow::implicitFill() { QQmlEngine engine; QQmlComponent component(&engine); component.loadUrl(testFileUrl("fill.qml")); QObject* created = component.create(); QScopedPointer<QObject> cleanup(created); QVERIFY(created); QQuickWindow* window = qobject_cast<QQuickWindow*>(created); QVERIFY(window); QVERIFY(!window->isVisible()); QCOMPARE(window->width(), 400); QCOMPARE(window->height(), 400); window->show(); QVERIFY(QTest::qWaitForWindowActive(window)); QQuickItem *stackView = window->property("stackView").value<QQuickItem*>(); QVERIFY(stackView); QCOMPARE(stackView->width(), 400.0); QCOMPARE(stackView->height(), 400.0); QQuickItem *nextItem = window->property("nextItem").value<QQuickItem*>(); QVERIFY(nextItem); QVERIFY(QMetaObject::invokeMethod(window, "pushNextItem")); QCOMPARE(nextItem->width(), 400.0); QCOMPARE(nextItem->height(), 400.0); }
QQuickItem *GlobalFunctions::itemAt(QQuickItem* parent, int x, int y, QJSValue matcher) { if (!parent) return nullptr; QList<QQuickItem *> children = QQuickItemPrivate::get(parent)->paintOrderChildItems(); for (int i = children.count() - 1; i >= 0; --i) { QQuickItem *child = children.at(i); // Map coordinates to the child element's coordinate space QPointF point = parent->mapToItem(child, QPointF(x, y)); if (child->isVisible() && point.x() >= 0 && child->width() >= point.x() && point.y() >= 0 && child->height() >= point.y()) { if (!matcher.isCallable()) return child; QQmlEngine* engine = qmlEngine(child); if (!engine) return child; QJSValue newObj = engine->newQObject(child); if (matcher.call(QJSValueList() << newObj).toBool()) { return child; } } } return nullptr; }
void Tracking::updatePositionMarker() { if ( m_marbleQuickItem && m_positionMarker && m_positionMarkerType == Circle ) { Coordinate* position = 0; bool visible = (m_marbleQuickItem->model()->planetId() == QLatin1String("earth")); if ( m_positionSource && m_positionSource->hasPosition() ) { position = m_positionSource->position(); } else if ( hasLastKnownPosition() ) { position = lastKnownPosition(); } else { visible = false; } qreal x(0), y(0); if ( position ) { Marble::GeoDataCoordinates const pos( position->longitude(), position->latitude(), 0.0, GeoDataCoordinates::Degree ); visible = visible && m_marbleQuickItem->map()->viewport()->screenCoordinates( pos.longitude(), pos.latitude(), x, y ); QQuickItem* item = qobject_cast<QQuickItem*>( m_positionMarker ); if ( item ) { item->setVisible( visible ); if ( visible ) { item->setX( x - item->width() / 2.0 ); item->setY( y - item->height() / 2.0 ); } } } } else if ( m_positionMarkerType != Circle ) { QQuickItem* item = qobject_cast<QQuickItem*>( m_positionMarker ); if ( item ) { item->setVisible( false ); } } }
void TestSimpleQmlLoad::compileAndLoadItem() { QQmlEngine *engine = new QQmlEngine; const QString TEST_FILE(":/testqml/testitem.qml"); QQmlComponent* component = compileAndLoad(engine, TEST_FILE); QVERIFY(component); QObject *myObject = component->create(); QQuickItem *item = qobject_cast<QQuickItem*>(myObject); int width = item->width(); // width = 100 QVERIFY(width == 100); delete component; delete engine; }
void StretchRow::layoutChildrenWithDefaultSize() { //static int count = 0; //qDebug() << "Row Default Size" << ++count; Q_ASSERT(m_defaultSize != 0); const QList<QQuickItem *> childrenList = childItems(); if (childrenList.isEmpty()) return; const int layoutHeight = height(); qreal currX = m_leftMargin; for (QList<QQuickItem *>::const_iterator it = childrenList.constBegin(); it != childrenList.constEnd(); ++it) { QQuickItem* child = (*it); if (child == Q_NULLPTR || !child->isVisible()) { continue; } // add spacing if it is not the first item: if (currX > 0) { currX += m_spacing; } if (currX != child->x()) child->setX(currX); // check if item has a stretch proportion set: if (child->implicitWidth() < 0) { // yes -> set it to default size: qreal newWidth = m_defaultSize * child->implicitWidth() * -1; if (newWidth != child->width()) child->setWidth(newWidth); } // set height of all items to fill the layout: if (layoutHeight != child->height()) child->setHeight(layoutHeight); currX += child->width(); } currX += m_rightMargin; // set implicit size to fit all items: if (currX != implicitWidth()) setImplicitWidth(currX); }
void TestSimpleQmlLoad::compileAndLoadSubItem1() { QQmlEngine *engine = new QQmlEngine; const QString TEST_FILE(":/testqml/testsubitem1.qml"); const QString TEST_DEPENDENCY(":/testqml/SubItem.qml"); QList<QString> dependencies; dependencies.append(TEST_DEPENDENCY); QQmlComponent* component = compileAndLoad(engine, TEST_FILE, dependencies); QVERIFY(component); QObject *myObject = component->create(); QQuickItem *item = qobject_cast<QQuickItem*>(myObject); int width = item->width(); QVERIFY(width == 10); delete component; delete engine; }
void TestSimpleQmlLoad::compileAndLoadFunction1() { QQmlEngine *engine = new QQmlEngine; const QString TEST_FILE(":/testqml/testfunction1.qml"); QQmlComponent* component = compileAndLoad(engine, TEST_FILE); QVERIFY(component); QObject *myObject = component->create(); QVERIFY(myObject); QQuickItem *item = qobject_cast<QQuickItem*>(myObject); int width = item->width(); QVERIFY(width == 100); int height = item->height(); //QVERIFY(height == width * 2); item->setWidth(220); height = item->height(); QVERIFY(height == 20); delete component; delete engine; }
void TestSimpleQmlLoad::loadScript1() { QQmlEngine *engine = new QQmlEngine; const QString TEST_FILE(":/testqml/testscript1.qml"); QQmlComponent* component = load(engine, TEST_FILE); QVERIFY(component); QObject *myObject = component->create(); QQuickItem *item = qobject_cast<QQuickItem*>(myObject); int width = item->width(); QVERIFY(width == 100); int height = item->height(); QVERIFY(height == 201); item->setWidth(15); height = item->height(); QVERIFY(height == 31); delete component; delete engine; }
void TestSimpleQmlLoad::compileAndLoadScript1() { QQmlEngine *engine = new QQmlEngine; const QString TEST_FILE(":/testqml/testscript1.qml"); const QString TEST_SCRIPT(":/testqml/testscript1.js"); QList<QString> dependencies; dependencies.append(TEST_SCRIPT); QQmlComponent* component = compileAndLoad(engine, TEST_FILE, dependencies); QVERIFY(component); QObject *myObject = component->create(); QQuickItem *item = qobject_cast<QQuickItem*>(myObject); int width = item->width(); QVERIFY(width == 100); int height = item->height(); QVERIFY(height == 201); item->setWidth(15); height = item->height(); QVERIFY(height == 31); delete component; delete engine; }
/*! Traverse QObject based items. */ void SceneGraphTraverse::traverseObject(TasObject* objectInfo, QObject* object, TasCommand* command) { Q_UNUSED(command); QQuickItem* item = qobject_cast<QQuickItem*>(object); if (item) { QQmlContext* context = QQmlEngine::contextForObject(object); if (context) { QString name = context->nameForObject(object); objectInfo->addAttribute("QML_ID", name); } #ifdef USE_QTQML_PRIVATE_HEADERS addTypeInfo(item, objectInfo); #endif mTraverseUtils->addObjectDetails(objectInfo, object); objectInfo->addAttribute("objectType", TYPE_QSCENEGRAPH); QPointF point = item->mapToScene(QPoint()); // needed for visualizer objectInfo->addAttribute("x", (int)point.x()); objectInfo->addAttribute("y", (int)point.y()); objectInfo->addAttribute("x_absolute", (int)point.x()); objectInfo->addAttribute("y_absolute", (int)point.y()); objectInfo->addAttribute("x_relative", item->x()); objectInfo->addAttribute("y_relative", item->y()); // TODO already included? objectInfo->addAttribute("width", item->width()); objectInfo->addAttribute("height", item->height()); } }
void StretchColumn::layoutChildrenWithDefaultSize() { //static int count = 0; //qDebug() << "Column Default Size" << ++count; Q_ASSERT(m_defaultSize != 0); const QList<QQuickItem *> childrenList = childItems(); if (childrenList.isEmpty()) return; const int contentWidth = width() - m_leftMargin - m_rightMargin; qreal currY = 0; for (QList<QQuickItem *>::const_iterator it = childrenList.constBegin(); it != childrenList.constEnd(); ++it) { QQuickItem* child = (*it); if (child == Q_NULLPTR || !child->isVisible()) { continue; } // add spacing if it is not the first item: if (currY > 0) { currY += m_spacing; } if (currY != child->y()) child->setY(currY); // check if item has a stretch proportion set: if (child->implicitHeight() < 0) { // yes -> set it to default size multiplied by relative size: qreal newHeight = m_defaultSize * child->implicitHeight() * -1; if (newHeight != child->height()) child->setHeight(newHeight); } // set width of all items to fill the layout: if (m_leftMargin != child->x()) child->setX(m_leftMargin); if (contentWidth != child->width()) child->setWidth(contentWidth); currY += child->height(); } // set implicit size to fit all items: if (currY != implicitHeight()) setImplicitHeight(currY); }
void QQuickComponentsLinearLayout::reconfigureLayout() { if (!isComponentComplete()) return; const int count = m_items.count(); if (count == 0) return; qreal totalSpacing = 0; qreal totalSizeHint = 0; qreal totalMinimumSize = 0; qreal totalMaximumSize = 0; QVector<QQuickComponentsLayoutInfo> itemData; for (int i = 0; i < count; i++) { QQuickItem *item = m_items.at(i); QObject *attached = qmlAttachedPropertiesObject<QQuickComponentsLayout>(item); QQuickComponentsLayoutAttached *info = static_cast<QQuickComponentsLayoutAttached *>(attached); QQuickComponentsLayoutInfo data; if (m_orientation == Horizontal) { data.sizeHint = item->implicitWidth(); data.minimumSize = info->minimumWidth(); data.maximumSize = info->maximumWidth(); data.expansive = (info->horizontalSizePolicy() == QQuickComponentsLayout::Expanding); data.stretch = info->horizontalSizePolicy() == Expanding ? 1.0 : 0; } else { data.sizeHint = item->implicitHeight(); data.minimumSize = info->minimumHeight(); data.maximumSize = info->maximumHeight(); data.expansive = (info->verticalSizePolicy() == QQuickComponentsLayout::Expanding); data.stretch = info->verticalSizePolicy() == Expanding ? 1.0 : 0; } itemData.append(data); // sum totalSizeHint += data.sizeHint; totalMinimumSize += data.minimumSize; totalMaximumSize += data.maximumSize; // don't count last spacing if (i < count - 1) totalSpacing += data.spacing + m_spacing; } if (m_orientation == Horizontal) { qDeclarativeLayoutCalculate(itemData, 0, count, 0, width(), m_spacing); for (int i = 0; i < count; i++) { QQuickItem *item = m_items.at(i); const QQuickComponentsLayoutInfo &data = itemData.at(i); item->setX(data.pos); item->setY(height()/2 - item->height()/2); item->setWidth(data.size); } } else { qDeclarativeLayoutCalculate(itemData, 0, count, 0, height(), m_spacing); for (int i = 0; i < count; i++) { QQuickItem *item = m_items.at(i); const QQuickComponentsLayoutInfo &data = itemData.at(i); item->setY(data.pos); item->setX(width()/2 - item->width()/2); item->setHeight(data.size); } } // propagate hints to upper levels QObject *attached = qmlAttachedPropertiesObject<QQuickComponentsLayout>(this); QQuickComponentsLayoutAttached *info = static_cast<QQuickComponentsLayoutAttached *>(attached); if (m_orientation == Horizontal) { setImplicitWidth(totalSizeHint); info->setMinimumWidth(totalMinimumSize + totalSpacing); info->setMaximumWidth(totalMaximumSize + totalSpacing); } else { setImplicitHeight(totalSizeHint); info->setMinimumHeight(totalMinimumSize + totalSpacing); info->setMaximumHeight(totalMaximumSize + totalSpacing); } }
void ScreenshotService::getScreenshot(TasCommandModel& model, TasResponse& response) { QListIterator<TasTarget*> i(model.targetList()); QString errorMsg = PARSE_ERROR; QImage screenshot; QString pictureFormat = "PNG"; while (i.hasNext()) { TasTarget* commandTarget = i.next(); QString targetId = commandTarget->id(); QString targetType = commandTarget->type(); TasCommand* command = commandTarget->findCommand("Screenshot"); // are required for command completion if (targetId.isEmpty() || targetType.isEmpty() || !command) { continue; } if (!command->parameter("format").isEmpty()) { pictureFormat = command->parameter("format"); } if (!isFormatSupported(pictureFormat)) { errorMsg = "Given format " + pictureFormat + "is not supported. Supported formats are: PNG, JPEG and BMP."; break; } bool draw = (command->parameter("draw") == "true"); QWidget* widget = 0; QQuickWindow* qtQuickWindow = 0; WId winId = 0; QRect rect(0,0,-1,-1); errorMsg = "Taking screenshot failed!"; if (targetType == TYPE_GRAPHICS_VIEW) { //TasLogger::logger()->debug("TYPE_GRAPHICS_VIEW Target id:" + targetId); QGraphicsItem* item = findGraphicsItem(targetId); if (item) { QGraphicsView* view = getViewForItem(item); if(view) { ItemLocationDetails locationDetails = TestabilityUtils::getItemLocationDetails(item); rect = QRect(locationDetails.windowPoint.x(), locationDetails.windowPoint.y(), locationDetails.width, locationDetails.height); if (draw) { widget = view->window(); } else { winId = view->window()->winId(); } } else { errorMsg = "Could not find a GraphicsView for the GraphicsItem!"; } } else { errorMsg = "Could not find the GraphicsItem!"; } } else if (targetType == TYPE_STANDARD_VIEW) { //TasLogger::logger()->debug("TYPE_STANDARD_VIEW about to find widget Target id:" + targetId); widget = findWidget(targetId); if (widget) { if ((widget->isWindow() && !draw) || widget->inherits("QDesktopWidget")) { winId = widget->winId(); widget = 0; } else if (!draw) { QPoint point = widget->mapToGlobal(QPoint(0,0)); QPoint windowPoint = widget->window()->mapFromGlobal(point); rect = QRect(windowPoint.x(), windowPoint.y(), widget->rect().width(), widget->rect().width()); winId = widget->window()->winId(); widget = 0; } } else { TasLogger::logger()->debug("ScreenshotService::executeService application has no visible ui!"); errorMsg = "Application has no visible ui!"; } } else if (targetType == TYPE_QSCENEGRAPH) { QQuickItem* item = TestabilityUtils::findQuickItem(targetId); if (item) { QPointF offset = item->mapToScene(QPointF(0,0)); rect = QRect(-offset.x(), -offset.y(), item->width(), item->height()); qtQuickWindow = item->window(); } } else { //TasLogger::logger()->debug("TYPE_APPLICATION_VIEW about to find application window Target id:" + targetId); widget = getApplicationWidget(); if (!widget) { QWindow *window = getApplicationWindow(); //in case no window false, return the desktop qtQuickWindow = qobject_cast<QQuickWindow *>(window); if (!window) { widget = qApp->desktop(); } } } if (widget) { screenshot = widget->grab(rect).toImage(); if (!screenshot.isNull()) { screenshot.setText("tas_id", objectId(widget)); } } else if (qtQuickWindow) { screenshot = qtQuickWindow->grabWindow(); if (!screenshot.isNull()) { screenshot.setText("tas_id", objectId(qtQuickWindow)); } } else if (winId) { screenshot = QPixmap::grabWindow(winId, rect.x(), rect.y(), rect.width(), rect.height()).toImage(); if (!screenshot.isNull()) { screenshot.setText("tas_id", QString::number(winId)); } } break; } if (!screenshot.isNull()) { QByteArray bytes; QBuffer buffer(&bytes); buffer.open(QIODevice::WriteOnly); screenshot.save(&buffer, pictureFormat.toLatin1()); response.setData(bytes); buffer.close(); } else { response.setErrorMessage(errorMsg); } }
void StretchRow::layoutChildrenWithProportions() { //static int count = 0; //qDebug() << "Row Proportions" << ++count; const QList<QQuickItem*> childrenList = childItems(); if (childrenList.isEmpty()) return; if (width() <= 0) return; int visibleItems = 0; qreal availableForStretch = width() - m_leftMargin - m_rightMargin; qreal sumStretchProportions = 0.0; // iterate over all children and calculate available size to stretch items: for (QList<QQuickItem *>::const_iterator it = childrenList.constBegin(); it != childrenList.constEnd(); ++it) { QQuickItem* child = (*it); if (child == Q_NULLPTR || !child->isVisible()) { continue; } if (child->implicitWidth() >= 0) { // no stretch proportion set -> leave size and remove it from available space: availableForStretch -= child->width(); } else { // a stretch proportion is set -> add it to sum: sumStretchProportions += (child->implicitWidth() * -1); } visibleItems++; } // remove spacing from available space: availableForStretch -= m_spacing * (visibleItems - 1); const int layoutHeight = height(); QPointer<QQuickItem> lastStretchItem = nullptr; qreal currX = m_leftMargin; for (QList<QQuickItem *>::const_iterator it = childrenList.constBegin(); it != childrenList.constEnd(); ++it) { QQuickItem* child = (*it); if (child == Q_NULLPTR || !child->isVisible()) { continue; } // add spacing if it is not the first item: if (currX > 0) { currX += m_spacing; } if (currX != child->x()) child->setX(currX); // check if item has a stretch proportion set (if not do nothing): if (child->implicitWidth() < 0) { // get the stretch proportion: qreal stretchProportion = (child->implicitWidth() * -1); // calculate the relation of the total space available for stretched items // that this item will use: // (sumStretchProportion can not be 0 (in divison) because if this "if" is executed, // there has been at least one item with a stretch proportion set) qreal relationOfSpaceAvailableForStretch = stretchProportion / sumStretchProportions; qreal newWidth = qRound(availableForStretch * relationOfSpaceAvailableForStretch); if (newWidth != child->width()) child->setWidth(newWidth); lastStretchItem = child; } // set height of all items to fill the layout: if (layoutHeight != child->height()) child->setHeight(layoutHeight); currX += child->width(); } currX += m_rightMargin; // check if last item fills whole remaining space in this layout: // (can happen because of rounding mistakes) if (lastStretchItem) { double pxMissing = width() - currX; if (pxMissing > 0.0001) { // qInfo() << "StretchRow layout mismatch: " << pxMissing; // it does not -> adjust it: lastStretchItem->setWidth(lastStretchItem->width() + pxMissing); } } }
QAbstractAnimationJob* QQuickParentAnimation::transition(QQuickStateActions &actions, QQmlProperties &modified, TransitionDirection direction, QObject *defaultTarget) { Q_D(QQuickParentAnimation); struct QQuickParentAnimationData : public QAbstractAnimationAction { QQuickParentAnimationData() : reverse(false) {} ~QQuickParentAnimationData() { qDeleteAll(pc); } QQuickStateActions actions; //### reverse should probably apply on a per-action basis bool reverse; QList<QQuickParentChange *> pc; virtual void doAction() { for (int ii = 0; ii < actions.count(); ++ii) { const QQuickAction &action = actions.at(ii); if (reverse) action.event->reverse(); else action.event->execute(); } } }; QQuickParentAnimationData *data = new QQuickParentAnimationData; QQuickParentAnimationData *viaData = new QQuickParentAnimationData; bool hasExplicit = false; if (d->target && d->newParent) { data->reverse = false; QQuickAction myAction; QQuickParentChange *pc = new QQuickParentChange; pc->setObject(d->target); pc->setParent(d->newParent); myAction.event = pc; data->pc << pc; data->actions << myAction; hasExplicit = true; if (d->via) { viaData->reverse = false; QQuickAction myVAction; QQuickParentChange *vpc = new QQuickParentChange; vpc->setObject(d->target); vpc->setParent(d->via); myVAction.event = vpc; viaData->pc << vpc; viaData->actions << myVAction; } //### once actions have concept of modified, // loop to match appropriate ParentChanges and mark as modified } if (!hasExplicit) for (int i = 0; i < actions.size(); ++i) { QQuickAction &action = actions[i]; if (action.event && action.event->type() == QQuickActionEvent::ParentChange && (!d->target || static_cast<QQuickParentChange*>(action.event)->object() == d->target)) { QQuickParentChange *pc = static_cast<QQuickParentChange*>(action.event); QQuickAction myAction = action; data->reverse = action.reverseEvent; //### this logic differs from PropertyAnimation // (probably a result of modified vs. done) if (d->newParent) { QQuickParentChange *epc = new QQuickParentChange; epc->setObject(static_cast<QQuickParentChange*>(action.event)->object()); epc->setParent(d->newParent); myAction.event = epc; data->pc << epc; data->actions << myAction; pc = epc; } else { action.actionDone = true; data->actions << myAction; } if (d->via) { viaData->reverse = false; QQuickAction myAction; QQuickParentChange *vpc = new QQuickParentChange; vpc->setObject(pc->object()); vpc->setParent(d->via); myAction.event = vpc; viaData->pc << vpc; viaData->actions << myAction; QQuickAction dummyAction; QQuickAction &xAction = pc->xIsSet() && i < actions.size()-1 ? actions[++i] : dummyAction; QQuickAction &yAction = pc->yIsSet() && i < actions.size()-1 ? actions[++i] : dummyAction; QQuickAction &sAction = pc->scaleIsSet() && i < actions.size()-1 ? actions[++i] : dummyAction; QQuickAction &rAction = pc->rotationIsSet() && i < actions.size()-1 ? actions[++i] : dummyAction; QQuickItem *target = pc->object(); QQuickItem *targetParent = action.reverseEvent ? pc->originalParent() : pc->parent(); //### this mirrors the logic in QQuickParentChange. bool ok; const QTransform &transform = targetParent->itemTransform(d->via, &ok); if (transform.type() >= QTransform::TxShear || !ok) { qmlInfo(this) << QQuickParentAnimation::tr("Unable to preserve appearance under complex transform"); ok = false; } qreal scale = 1; qreal rotation = 0; bool isRotate = (transform.type() == QTransform::TxRotate) || (transform.m11() < 0); if (ok && !isRotate) { if (transform.m11() == transform.m22()) scale = transform.m11(); else { qmlInfo(this) << QQuickParentAnimation::tr("Unable to preserve appearance under non-uniform scale"); ok = false; } } else if (ok && isRotate) { if (transform.m11() == transform.m22()) scale = qSqrt(transform.m11()*transform.m11() + transform.m12()*transform.m12()); else { qmlInfo(this) << QQuickParentAnimation::tr("Unable to preserve appearance under non-uniform scale"); ok = false; } if (scale != 0) rotation = atan2(transform.m12()/scale, transform.m11()/scale) * 180/M_PI; else { qmlInfo(this) << QQuickParentAnimation::tr("Unable to preserve appearance under scale of 0"); ok = false; } } const QPointF &point = transform.map(QPointF(xAction.toValue.toReal(),yAction.toValue.toReal())); qreal x = point.x(); qreal y = point.y(); if (ok && target->transformOrigin() != QQuickItem::TopLeft) { qreal w = target->width(); qreal h = target->height(); if (pc->widthIsSet() && i < actions.size() - 1) w = actions[++i].toValue.toReal(); if (pc->heightIsSet() && i < actions.size() - 1) h = actions[++i].toValue.toReal(); const QPointF &transformOrigin = d->computeTransformOrigin(target->transformOrigin(), w,h); qreal tempxt = transformOrigin.x(); qreal tempyt = transformOrigin.y(); QTransform t; t.translate(-tempxt, -tempyt); t.rotate(rotation); t.scale(scale, scale); t.translate(tempxt, tempyt); const QPointF &offset = t.map(QPointF(0,0)); x += offset.x(); y += offset.y(); } if (ok) { //qDebug() << x << y << rotation << scale; xAction.toValue = x; yAction.toValue = y; sAction.toValue = sAction.toValue.toReal() * scale; rAction.toValue = rAction.toValue.toReal() + rotation; } } } } if (data->actions.count()) { QSequentialAnimationGroupJob *topLevelGroup = new QSequentialAnimationGroupJob; QActionAnimation *viaAction = d->via ? new QActionAnimation : 0; QActionAnimation *targetAction = new QActionAnimation; //we'll assume the common case by far is to have children, and always create ag QParallelAnimationGroupJob *ag = new QParallelAnimationGroupJob; if (d->via) viaAction->setAnimAction(viaData); targetAction->setAnimAction(data); //take care of any child animations bool valid = d->defaultProperty.isValid(); QAbstractAnimationJob* anim; for (int ii = 0; ii < d->animations.count(); ++ii) { if (valid) d->animations.at(ii)->setDefaultTarget(d->defaultProperty); anim = d->animations.at(ii)->transition(actions, modified, direction, defaultTarget); if (anim) ag->appendAnimation(anim); } //TODO: simplify/clarify logic bool forwards = direction == QQuickAbstractAnimation::Forward; if (forwards) { topLevelGroup->appendAnimation(d->via ? viaAction : targetAction); topLevelGroup->appendAnimation(ag); if (d->via) topLevelGroup->appendAnimation(targetAction); } else { if (d->via) topLevelGroup->appendAnimation(targetAction); topLevelGroup->appendAnimation(ag); topLevelGroup->appendAnimation(d->via ? viaAction : targetAction); } return initInstance(topLevelGroup); } else { delete data; delete viaData; } return 0; }
void tst_qquickwidget::resizemodeitem() { QWidget window; window.setGeometry(0, 0, 400, 400); QScopedPointer<QQuickWidget> view(new QQuickWidget); view->setParent(&window); view->setResizeMode(QQuickWidget::SizeRootObjectToView); QCOMPARE(QSize(0,0), view->initialSize()); view->setSource(testFileUrl("resizemodeitem.qml")); QQuickItem* item = qobject_cast<QQuickItem*>(view->rootObject()); QVERIFY(item); window.show(); view->showNormal(); // initial size from root object QCOMPARE(item->width(), 200.0); QCOMPARE(item->height(), 200.0); QCOMPARE(view->size(), QSize(200, 200)); QCOMPARE(view->size(), view->sizeHint()); QCOMPARE(view->size(), view->initialSize()); // size update from view view->resize(QSize(80,100)); QTRY_COMPARE(item->width(), 80.0); QCOMPARE(item->height(), 100.0); QCOMPARE(view->size(), QSize(80, 100)); QCOMPARE(view->size(), view->sizeHint()); view->setResizeMode(QQuickWidget::SizeViewToRootObject); // size update from view disabled view->resize(QSize(60,80)); QCOMPARE(item->width(), 80.0); QCOMPARE(item->height(), 100.0); QTRY_COMPARE(view->size(), QSize(60, 80)); // size update from root object item->setWidth(250); item->setHeight(350); QCOMPARE(item->width(), 250.0); QCOMPARE(item->height(), 350.0); QTRY_COMPARE(view->size(), QSize(250, 350)); QCOMPARE(view->size(), QSize(250, 350)); QCOMPARE(view->size(), view->sizeHint()); // reset window window.hide(); view.reset(new QQuickWidget(&window)); view->setResizeMode(QQuickWidget::SizeViewToRootObject); view->setSource(testFileUrl("resizemodeitem.qml")); item = qobject_cast<QQuickItem*>(view->rootObject()); QVERIFY(item); window.show(); view->showNormal(); // initial size for root object QCOMPARE(item->width(), 200.0); QCOMPARE(item->height(), 200.0); QCOMPARE(view->size(), view->sizeHint()); QCOMPARE(view->size(), view->initialSize()); // size update from root object item->setWidth(80); item->setHeight(100); QCOMPARE(item->width(), 80.0); QCOMPARE(item->height(), 100.0); QTRY_COMPARE(view->size(), QSize(80, 100)); QCOMPARE(view->size(), view->sizeHint()); // size update from root object disabled view->setResizeMode(QQuickWidget::SizeRootObjectToView); item->setWidth(60); item->setHeight(80); QCOMPARE(view->width(), 80); QCOMPARE(view->height(), 100); QCOMPARE(QSize(item->width(), item->height()), view->sizeHint()); // size update from view view->resize(QSize(200,300)); QTRY_COMPARE(item->width(), 200.0); QCOMPARE(item->height(), 300.0); QCOMPARE(view->size(), QSize(200, 300)); QCOMPARE(view->size(), view->sizeHint()); window.hide(); // if we set a specific size for the view then it should keep that size // for SizeRootObjectToView mode. view.reset(new QQuickWidget(&window)); view->resize(300, 300); view->setResizeMode(QQuickWidget::SizeRootObjectToView); QCOMPARE(QSize(0,0), view->initialSize()); view->setSource(testFileUrl("resizemodeitem.qml")); view->resize(300, 300); item = qobject_cast<QQuickItem*>(view->rootObject()); QVERIFY(item); window.show(); view->showNormal(); // initial size from root object QCOMPARE(item->width(), 300.0); QCOMPARE(item->height(), 300.0); QTRY_COMPARE(view->size(), QSize(300, 300)); QCOMPARE(view->size(), view->sizeHint()); QCOMPARE(view->initialSize(), QSize(200, 200)); // initial object size }
QSGNode* NodeConnectionLines::updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData*) { if (!m_nodeObject) return nullptr; const QVector<QPointer<NodeBase>>& connectedNodes = m_nodeObject->getConnectedNodes(); int connectionCount = connectedNodes.size(); // -------------------- Prepare QSG Nodes: QSGNode* parentNode = oldNode; if (!oldNode) { parentNode = new QSGNode(); } else { // update color in case it changed: // FIXME: is there a more efficient way to do this? for (int i=0; i<parentNode->childCount(); ++i) { QSGGeometryNode* childNode = static_cast<QSGGeometryNode*>(parentNode->childAtIndex(i)); if (!childNode) continue; QSGFlatColorMaterial* material = static_cast<QSGFlatColorMaterial*>(childNode->material()); if (!material) continue; material->setColor(m_color); } } // adapt child count: int childCount = parentNode->childCount(); if (childCount < connectionCount) { for (int i=0; i<(connectionCount - childCount); ++i) { QSGGeometryNode* node = new QSGGeometryNode; QSGGeometry* geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 3); geometry->setDrawingMode(GL_TRIANGLE_STRIP); node->setGeometry(geometry); node->setFlag(QSGNode::OwnsGeometry); QSGFlatColorMaterial* material = new QSGFlatColorMaterial; material->setColor(m_color); node->setMaterial(material); node->setFlag(QSGNode::OwnsMaterial); parentNode->appendChildNode(node); } } else if (childCount > connectionCount) { for (int i=0; i<(childCount - connectionCount); ++i) { parentNode->removeChildNode(parentNode->childAtIndex(0)); } } Q_ASSERT(parentNode->childCount() == connectionCount); // calculate common start point: const QPointF p0(width(), height() / 2); double widthOffset = m_lineWidth / 2; //const QPointF posInScene = mapToScene(QPointF(0, 0)); for (int i=0; i<connectionCount; ++i) { NodeBase* otherNode = connectedNodes[i]; if (!otherNode) continue; QQuickItem* otherGuiItem = otherNode->getGuiItem(); if (!otherGuiItem) continue; const QPointF p3 = mapFromItem(otherGuiItem, QPointF(-otherGuiItem->width() / 2, otherGuiItem->height() / 2)); int handleLength = std::max(50, std::min(int(p3.x() - p0.x()), 80)); const QPointF p1(p0.x() + handleLength, p0.y()); const QPointF p2(p3.x() - handleLength, p3.y()); // calculate reasonable segment count: int segmentCount = qMax(16.0, qMin(qAbs(p3.y() - p0.y()) / 25, 50.0)); int verticesCount = segmentCount * 2; QSGGeometryNode* qsgNode = static_cast<QSGGeometryNode*>(parentNode->childAtIndex(i)); if (!qsgNode) continue; QSGGeometry* geometry = qsgNode->geometry(); if (!geometry) continue; geometry->allocate(verticesCount); QSGGeometry::Point2D* vertices = geometry->vertexDataAsPoint2D(); // triangulate cubic bezier curve: for (int i = 0; i < segmentCount; ++i) { // t is the position on the line: const qreal t = i / qreal(segmentCount - 1); // pos is the point on the curve at "t": const QPointF pos = calculateBezierPoint(t, p0, p1, p2, p3); // normal is the normal vector at that point const QPointF normal = normalFromTangent(calculateBezierTangent(t, p0, p1, p2, p3)); // first is a point offsetted in the normal direction by lineWidth / 2 from pos const QPointF first = pos - normal * widthOffset; // ssecond is a point offsetted in the negative normal direction by lineWidth / 2 from pos const QPointF second = pos + normal * widthOffset; // add first and second as vertices to this geometry: vertices[i*2].set(first.x(), first.y()); vertices[i*2+1].set(second.x(), second.y()); } // tell Scene Graph that this items needs to be drawn: qsgNode->markDirty(QSGNode::DirtyGeometry); } return parentNode; }