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 QQuickStretchColumnContainer::updatePolish (void) { const QList<QQuickItem *> childrenList = childItems (); /// find items and stretchers qreal tmpW = 0; qreal tmpH = 0; int nbItems = 0; int nbStretch = 0; for (QList<QQuickItem *>::const_iterator it = childrenList.constBegin (); it != childrenList.constEnd (); it++) { QQuickItem * child = (* it); if (child != Q_NULLPTR && !child->inherits ("QQuickRepeater") && child->isVisible ()) { if (child->implicitWidth () > tmpW) { tmpW = child->implicitWidth (); } if (child->implicitHeight () >= 0) { tmpH += child->implicitHeight (); } else { nbStretch++; } nbItems++; } } /// resize layout if (nbItems > 1) { tmpH += (m_spacing * (nbItems -1)); } setImplicitWidth (tmpW); setImplicitHeight (tmpH); const qreal layoutWidth = width (); const qreal layoutHeight = height (); const qreal autoSize = (nbStretch > 0 ? (layoutHeight - tmpH) / qreal (nbStretch) : 0); /// position children int currY = 0; for (QList<QQuickItem *>::const_iterator it = childrenList.constBegin (); it != childrenList.constEnd (); it++) { QQuickItem * child = (* it); if (child != Q_NULLPTR && !child->inherits ("QQuickRepeater") && child->isVisible ()) { if (currY) { currY += m_spacing; } child->setY (currY); child->setWidth (layoutWidth); child->setHeight (child->implicitHeight () >= 0 ? child->implicitHeight () : autoSize); currY += child->height (); } } }
bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *item,const QPointF &sp, PropagateType sig) { //Based off of QQuickWindow::deliverInitialMousePressEvent //But specific to MouseArea, so doesn't belong in window Q_Q(const QQuickMouseArea); QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) { QPointF p = item->mapFromScene(sp); if (!item->contains(p)) return false; } QList<QQuickItem *> children = itemPrivate->paintOrderChildItems(); for (int ii = children.count() - 1; ii >= 0; --ii) { QQuickItem *child = children.at(ii); if (!child->isVisible() || !child->isEnabled()) continue; if (propagateHelper(ev, child, sp, sig)) return true; } QQuickMouseArea* ma = qobject_cast<QQuickMouseArea*>(item); if (ma && ma != q && ma->isEnabled() && itemPrivate->acceptedMouseButtons() & ev->button()) { switch (sig) { case Click: if (!ma->d_func()->isClickConnected()) return false; break; case DoubleClick: if (!ma->d_func()->isDoubleClickConnected()) return false; break; case PressAndHold: if (!ma->d_func()->isPressAndHoldConnected()) return false; break; } QPointF p = item->mapFromScene(sp); if (item->contains(p)) { ev->setX(p.x()); ev->setY(p.y()); ev->setAccepted(true);//It is connected, they have to explicitly ignore to let it slide switch (sig) { case Click: emit ma->clicked(ev); break; case DoubleClick: emit ma->doubleClicked(ev); break; case PressAndHold: emit ma->pressAndHold(ev); break; } if (ev->isAccepted()) return true; } } return false; }
QVariant QuickItemModel::data(const QModelIndex& index, int role) const { if (!index.isValid()) return QVariant(); QQuickItem *item = reinterpret_cast<QQuickItem*>(index.internalPointer()); if (role == QuickItemModelRole::Visibility) return item->isVisible(); return dataForObject(item, index, role); }
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 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 TouchDispatcher::dispatchTouchBegin( QTouchDevice *device, Qt::KeyboardModifiers modifiers, const QList<QTouchEvent::TouchPoint> &touchPoints, QWindow *window, ulong timestamp) { Q_ASSERT(m_status == NoActiveTouch); QQuickItem *targetItem = m_targetItem.data(); if (!targetItem->isEnabled() || !targetItem->isVisible()) { ugDebug("Cannot dispatch touch event to " << targetItem << " because it's disabled or invisible."); return; } // Map touch points to targetItem coordinates QList<QTouchEvent::TouchPoint> targetTouchPoints = touchPoints; transformTouchPoints(targetTouchPoints, QQuickItemPrivate::get(targetItem)->windowToItemTransform()); QScopedPointer<QTouchEvent> touchEvent( createQTouchEvent(QEvent::TouchBegin, device, modifiers, targetTouchPoints, window, timestamp)); ugDebug("dispatching " << qPrintable(touchEventToString(touchEvent.data())) << " to " << targetItem); QCoreApplication::sendEvent(targetItem, touchEvent.data()); if (touchEvent->isAccepted()) { ugDebug("Item accepted the touch event."); setStatus(DeliveringTouchEvents); } else if (targetItem->acceptedMouseButtons() & Qt::LeftButton) { ugDebug("Item rejected the touch event. Trying a QMouseEvent"); // NB: Arbitrarily chose the first touch point to emulate the mouse pointer QScopedPointer<QMouseEvent> mouseEvent( touchToMouseEvent(QEvent::MouseButtonPress, targetTouchPoints.at(0), timestamp, modifiers, false /* transformNeeded */)); Q_ASSERT(targetTouchPoints.at(0).state() == Qt::TouchPointPressed); ugDebug("dispatching " << qPrintable(mouseEventToString(mouseEvent.data())) << " to " << m_targetItem.data()); QCoreApplication::sendEvent(targetItem, mouseEvent.data()); if (mouseEvent->isAccepted()) { ugDebug("Item accepted the QMouseEvent."); setStatus(DeliveringMouseEvents); m_touchMouseId = targetTouchPoints.at(0).id(); if (checkIfDoubleClicked(timestamp)) { QScopedPointer<QMouseEvent> doubleClickEvent( touchToMouseEvent(QEvent::MouseButtonDblClick, targetTouchPoints.at(0), timestamp, modifiers, false /* transformNeeded */)); ugDebug("dispatching " << qPrintable(mouseEventToString(doubleClickEvent.data())) << " to " << m_targetItem.data()); QCoreApplication::sendEvent(targetItem, doubleClickEvent.data()); } } else { ugDebug("Item rejected the QMouseEvent."); setStatus(TargetRejectedTouches); } } else { ugDebug("Item rejected the touch event and does not accept mouse buttons."); setStatus(TargetRejectedTouches); } }
void Stats::updateStats(bool force) { QQuickItem* parent = parentItem(); if (!force) { if (!Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { if (parent->isVisible()) { parent->setVisible(false); } return; } else if (!parent->isVisible()) { parent->setVisible(true); } } auto nodeList = DependencyManager::get<NodeList>(); auto avatarManager = DependencyManager::get<AvatarManager>(); // we need to take one avatar out so we don't include ourselves STAT_UPDATE(avatarCount, avatarManager->size() - 1); STAT_UPDATE(updatedAvatarCount, avatarManager->getNumAvatarsUpdated()); STAT_UPDATE(notUpdatedAvatarCount, avatarManager->getNumAvatarsNotUpdated()); STAT_UPDATE(serverCount, (int)nodeList->size()); STAT_UPDATE_FLOAT(renderrate, qApp->getRenderLoopRate(), 0.1f); if (qApp->getActiveDisplayPlugin()) { auto displayPlugin = qApp->getActiveDisplayPlugin(); auto stats = displayPlugin->getHardwareStats(); STAT_UPDATE(appdropped, stats["app_dropped_frame_count"].toInt()); STAT_UPDATE(longrenders, stats["long_render_count"].toInt()); STAT_UPDATE(longsubmits, stats["long_submit_count"].toInt()); STAT_UPDATE(longframes, stats["long_frame_count"].toInt()); STAT_UPDATE_FLOAT(presentrate, displayPlugin->presentRate(), 0.1f); STAT_UPDATE_FLOAT(presentnewrate, displayPlugin->newFramePresentRate(), 0.1f); STAT_UPDATE_FLOAT(presentdroprate, displayPlugin->droppedFrameRate(), 0.1f); STAT_UPDATE_FLOAT(stutterrate, displayPlugin->stutterRate(), 0.1f); } else { STAT_UPDATE(appdropped, -1); STAT_UPDATE(longrenders, -1); STAT_UPDATE(longsubmits, -1); STAT_UPDATE(presentrate, -1); STAT_UPDATE(presentnewrate, -1); STAT_UPDATE(presentdroprate, -1); } STAT_UPDATE(gameLoopRate, (int)qApp->getGameLoopRate()); auto bandwidthRecorder = DependencyManager::get<BandwidthRecorder>(); STAT_UPDATE(packetInCount, (int)bandwidthRecorder->getCachedTotalAverageInputPacketsPerSecond()); STAT_UPDATE(packetOutCount, (int)bandwidthRecorder->getCachedTotalAverageOutputPacketsPerSecond()); STAT_UPDATE_FLOAT(mbpsIn, (float)bandwidthRecorder->getCachedTotalAverageInputKilobitsPerSecond() / 1000.0f, 0.01f); STAT_UPDATE_FLOAT(mbpsOut, (float)bandwidthRecorder->getCachedTotalAverageOutputKilobitsPerSecond() / 1000.0f, 0.01f); STAT_UPDATE_FLOAT(assetMbpsIn, (float)bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AssetServer) / 1000.0f, 0.01f); STAT_UPDATE_FLOAT(assetMbpsOut, (float)bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AssetServer) / 1000.0f, 0.01f); // Second column: ping SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer); SharedNodePointer avatarMixerNode = nodeList->soloNodeOfType(NodeType::AvatarMixer); SharedNodePointer assetServerNode = nodeList->soloNodeOfType(NodeType::AssetServer); SharedNodePointer messageMixerNode = nodeList->soloNodeOfType(NodeType::MessagesMixer); STAT_UPDATE(audioPing, audioMixerNode ? audioMixerNode->getPingMs() : -1); const int mixerLossRate = (int)roundf(_audioStats->data()->getMixerStream()->lossRateWindow() * 100.0f); const int clientLossRate = (int)roundf(_audioStats->data()->getClientStream()->lossRateWindow() * 100.0f); const int largestLossRate = mixerLossRate > clientLossRate ? mixerLossRate : clientLossRate; STAT_UPDATE(audioPacketLoss, audioMixerNode ? largestLossRate : -1); STAT_UPDATE(avatarPing, avatarMixerNode ? avatarMixerNode->getPingMs() : -1); STAT_UPDATE(assetPing, assetServerNode ? assetServerNode->getPingMs() : -1); STAT_UPDATE(messagePing, messageMixerNode ? messageMixerNode->getPingMs() : -1); //// Now handle entity servers, since there could be more than one, we average their ping times int totalPingOctree = 0; int octreeServerCount = 0; int pingOctreeMax = 0; int totalEntityKbps = 0; nodeList->eachNode([&](const SharedNodePointer& node) { // TODO: this should also support entities if (node->getType() == NodeType::EntityServer) { totalPingOctree += node->getPingMs(); totalEntityKbps += node->getInboundBandwidth(); octreeServerCount++; if (pingOctreeMax < node->getPingMs()) { pingOctreeMax = node->getPingMs(); } } }); // update the entities ping with the average for all connected entity servers STAT_UPDATE(entitiesPing, octreeServerCount ? totalPingOctree / octreeServerCount : -1); // Third column, avatar stats auto myAvatar = avatarManager->getMyAvatar(); glm::vec3 avatarPos = myAvatar->getWorldPosition(); STAT_UPDATE(position, QVector3D(avatarPos.x, avatarPos.y, avatarPos.z)); STAT_UPDATE_FLOAT(speed, glm::length(myAvatar->getWorldVelocity()), 0.01f); STAT_UPDATE_FLOAT(yaw, myAvatar->getBodyYaw(), 0.1f); if (_expanded || force) { SharedNodePointer avatarMixer = nodeList->soloNodeOfType(NodeType::AvatarMixer); if (avatarMixer) { STAT_UPDATE(avatarMixerInKbps, (int)roundf(bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AvatarMixer))); STAT_UPDATE(avatarMixerInPps, (int)roundf(bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AvatarMixer))); STAT_UPDATE(avatarMixerOutKbps, (int)roundf(bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AvatarMixer))); STAT_UPDATE(avatarMixerOutPps, (int)roundf(bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AvatarMixer))); } else { STAT_UPDATE(avatarMixerInKbps, -1); STAT_UPDATE(avatarMixerInPps, -1); STAT_UPDATE(avatarMixerOutKbps, -1); STAT_UPDATE(avatarMixerOutPps, -1); } STAT_UPDATE_FLOAT(myAvatarSendRate, avatarManager->getMyAvatarSendRate(), 0.1f); SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer); auto audioClient = DependencyManager::get<AudioClient>(); if (audioMixerNode || force) { STAT_UPDATE(audioMixerKbps, (int)roundf( bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AudioMixer) + bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AudioMixer))); STAT_UPDATE(audioMixerPps, (int)roundf( bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AudioMixer) + bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AudioMixer))); STAT_UPDATE(audioMixerInKbps, (int)roundf(bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AudioMixer))); STAT_UPDATE(audioMixerInPps, (int)roundf(bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AudioMixer))); STAT_UPDATE(audioMixerOutKbps, (int)roundf(bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AudioMixer))); STAT_UPDATE(audioMixerOutPps, (int)roundf(bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AudioMixer))); STAT_UPDATE(audioAudioInboundPPS, (int)audioClient->getAudioInboundPPS()); STAT_UPDATE(audioSilentInboundPPS, (int)audioClient->getSilentInboundPPS()); STAT_UPDATE(audioOutboundPPS, (int)audioClient->getAudioOutboundPPS()); STAT_UPDATE(audioSilentOutboundPPS, (int)audioClient->getSilentOutboundPPS()); } else { STAT_UPDATE(audioMixerKbps, -1); STAT_UPDATE(audioMixerPps, -1); STAT_UPDATE(audioMixerInKbps, -1); STAT_UPDATE(audioMixerInPps, -1); STAT_UPDATE(audioMixerOutKbps, -1); STAT_UPDATE(audioMixerOutPps, -1); STAT_UPDATE(audioOutboundPPS, -1); STAT_UPDATE(audioSilentOutboundPPS, -1); STAT_UPDATE(audioAudioInboundPPS, -1); STAT_UPDATE(audioSilentInboundPPS, -1); } STAT_UPDATE(audioCodec, audioClient->getSelectedAudioFormat()); STAT_UPDATE(audioNoiseGate, audioClient->getNoiseGateOpen() ? "Open" : "Closed"); STAT_UPDATE(entityPacketsInKbps, octreeServerCount ? totalEntityKbps / octreeServerCount : -1); auto loadingRequests = ResourceCache::getLoadingRequests(); STAT_UPDATE(downloads, loadingRequests.size()); STAT_UPDATE(downloadLimit, ResourceCache::getRequestLimit()) STAT_UPDATE(downloadsPending, ResourceCache::getPendingRequestCount()); STAT_UPDATE(processing, DependencyManager::get<StatTracker>()->getStat("Processing").toInt()); STAT_UPDATE(processingPending, DependencyManager::get<StatTracker>()->getStat("PendingProcessing").toInt()); // See if the active download urls have changed bool shouldUpdateUrls = _downloads != _downloadUrls.size(); if (!shouldUpdateUrls) { for (int i = 0; i < _downloads; i++) { if (loadingRequests[i]->getURL().toString() != _downloadUrls[i]) { shouldUpdateUrls = true; break; } } } // If the urls have changed, update the list if (shouldUpdateUrls) { _downloadUrls.clear(); foreach (const auto& resource, loadingRequests) { _downloadUrls << resource->getURL().toString(); } emit downloadUrlsChanged(); } // TODO fix to match original behavior //stringstream downloads; //downloads << "Downloads: "; //foreach(Resource* resource, ) { // downloads << (int)(resource->getProgress() * 100.0f) << "% "; //} //downloads << "(" << << " pending)"; } // expanded avatar column
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); } } }
void QmlProfilerTraceView::setZoomSliderVisible(bool visible) { QQuickItem *zoomSlider = d->m_mainView->rootObject()->findChild<QQuickItem*>(QLatin1String("zoomSliderToolBar")); if (zoomSlider->isVisible() != visible) zoomSlider->setVisible(visible); }