import QtQuick import QtQuick.Window import QtQuick.Templates as QQCT import Weave.Controls import Weave.Templates as T import "internal" T.Breadcrumb { id: root leftPadding: !mirrored ? 0 : root.isLastDelegate ? 0 : (Theme.component.breadcrumb.divider.marginLeft + _triangleWidth + Theme.component.breadcrumb.divider.marginRight) rightPadding: mirrored ? 0 : root.isLastDelegate ? 0 : (Theme.component.breadcrumb.divider.marginLeft + _triangleWidth + Theme.component.breadcrumb.divider.marginRight) leftInset: !mirrored ? 0 : Theme.component.breadcrumb.divider.marginRight rightInset: mirrored ? 0 : Theme.component.breadcrumb.divider.marginRight implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, implicitContentHeight + topPadding + bottomPadding, overflowItem ? overflowItem.implicitHeight : 0) implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, implicitContentWidth + leftPadding + rightPadding, overflowItem ? overflowItem.implicitWidth : 0) height: overflowItem ? overflowItem.implicitHeight : implicitHeight width: overflowItem ? overflowItem.implicitWidth : compressed ? 0 : implicitWidth font.family: Theme.component.breadcrumb.fontFamily font.pixelSize: Theme.component.breadcrumb.fontSize font.weight: (_isLastDelegate || root.pressed) ? Theme.component.breadcrumb.fontWeight.pressed : Theme.component.breadcrumb.fontWeight.default font.underline: hovered && !_isLastDelegate icon.color: Theme.component.breadcrumb.icon.fill.default icon.width: Theme.component.breadcrumb.icon.height icon.height: Theme.component.breadcrumb.icon.height hoverEnabled: root.enabled onClicked: { if (multilevelEntities.length === 0) { root.selectedMultilevelEntity = -1 root.breadcrumbSelected() } } menu: DropdownPopup { id: dropdownPopup control: root model: root.multilevelEntities currentIndex: root.selectedMultilevelEntity fixedWidth: true width: Theme.component.breadcrumb.flyout.width closePolicy: QQCT.Popup.CloseOnEscape | QQCT.Popup.CloseOnPressOutsideParent // avoid causing togglePopup() to reopen it. y: root.height + Theme.component.flyout.positionTop.arrowContainer.height x: root.indicator.visible ? (root.mirrored ? 0 : (root.width - width)) // dropdown case: right aligned. : (root.mirrored ? (root.width - width) : 0) // overflow case: left aligned. background: FlyoutBackground { id: flyoutBackground flyoutItem: dropdownPopup nubAlignment: T.Flyout.TopCenter nubX: (root.indicator.visible ? root.mirrored // center on the dropdown indicator ? (root.leftPadding + root._indicatorWidth/2) : (flyoutBackground.width - root.rightPadding - root.indicator.width/2) : root.mirrored // center on the overflow button ? (flyoutBackground.width - Theme.component.iconbutton.width.default/2) : Theme.component.iconbutton.width.default/2) - flyoutBackground.nubSize // nubSize is the smaller axis, i.e. half of nub width already. } delegate: DropdownDelegate { id: dropdownDelegate required property int index required property string modelData width: dropdownPopup.width checked: root.selectedMultilevelEntity === index text: modelData onClicked: { dropdownPopup.close() root.selectedMultilevelEntity = index root.breadcrumbSelected() } ToolTip.visible: dropdownDelegate.textTruncated && (dropdownDelegate.hovered || (ToolTip.toolTip.parent === dropdownDelegate && ToolTip.toolTip.hovered)) ToolTip.text: dropdownDelegate.text ToolTip.preferredAlignment: Flyout.PreferBottom ToolTip.content: ToolTipContent {} } } property int _repeaterIndex: -1 property int _repeaterCount: -1 property bool _isFirstDelegate: _repeaterIndex === 0 property bool _isLastDelegate: _repeaterIndex === (_repeaterCount-1) property bool _isOverflow: root.text.length === 0 && root.icon.name.length === 0 && root.icon.source.toString().length === 0 property real _triangleWidth: Math.round(Theme.component.tablist.divider.height * Theme.autodeskAngleTan) property int _indicatorWidth: indicator.visible ? implicitIndicatorWidth : 0 contentItem: Item { id: contentItem visible: !root.compressed // The source size token doesn't match the required item bounds, so we cannot use the implicitWidth. readonly property real iconPadding: iconImage.status === Image.Ready ? (Theme.component.breadcrumb.icon.marginLeft + iconImage.width + (root.text.length > 0 ? Theme.component.breadcrumb.icon.marginRight : 0)) : 0 implicitWidth: overflowButton.visible ? overflowButton.width : (iconPadding + label.implicitWidth + (root.indicator.visible ? Theme.component.breadcrumb.dropdown.icon.marginLeft + root._indicatorWidth : 0)) implicitHeight: overflowButton.visible ? overflowButton.height : Math.max(Theme.component.breadcrumb.lineHeight, // Similarily here, we cannot use the implicitHeight. iconImage.height) T.IconImage { id: iconImage visible: !overflowButton.visible x: root.mirrored ? label.x + label.width + (root.text.length ? Theme.component.breadcrumb.icon.marginRight : 0) : Theme.component.breadcrumb.icon.marginLeft y: Theme.component.breadcrumb.icon.marginTop width: Theme.component.breadcrumb.icon.width height: Theme.component.breadcrumb.icon.height color: root.icon.color name: root.icon.name url: root.icon.source sourceSize: Qt.size(root.icon.width, root.icon.height) } Text { id: label visible: !overflowButton.visible x: root.mirrored ? (root.indicator.visible ? root._indicatorWidth + Theme.component.breadcrumb.dropdown.icon.marginLeft : 0) : contentItem.iconPadding y: (contentItem.height-label.height)/2 text: root.text font: root.font color: Theme.component.breadcrumb.textColor lineHeight: Theme.component.breadcrumb.lineHeight lineHeightMode: Text.FixedHeight horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter } IconButton { id: overflowButton visible: root._isOverflow icon.name: "more" dynamicColor: true swellOnPress: false popupIndicatorVisible: false popupOpened: dropdownPopup.opened onClicked: root.clicked() } } indicator: T.IconImage { // dropdown indicator x: root.mirrored ? root.leftPadding : root.width - root.rightPadding - width y: root.topPadding + ((root.availableHeight - height) / 2) visible: !root.compressed && root.multilevelEntities.length > 0 && root.menu && !root._isOverflow name: Theme.icon.medium("caret-down") // TODO: these tokens are wrongly named, they should be: // Theme.component.breadcrumb.dropdown.icon.fill.active and // Theme.component.breadcrumb.dropdown.icon.fill.default color: root.menu && root.menu.opened ? Theme.component.breadcrumb.icon.fill.active : Theme.component.breadcrumb.icon.fill.default Behavior on color { enabled: colorAnim.duration > 0 ColorAnimation { id: colorAnim duration: Theme.component.breadcrumb.dropdown.icon.transitionDuration easing.type: Theme.component.breadcrumb.dropdown.icon.transitionTimingFunction } } // TODO: the token we'd like to use is not valid for us: // component.breadcrumb.dropdown.icon.transform = {generic.transform.rotate.180} = rotate(180deg) // which is a CSS specific rotation function, not valid in QML. rotation: root.menu && root.menu.opened ? 180 : 0 Behavior on rotation { enabled: rotatAnim.duration > 0 RotationAnimation { id: rotatAnim duration: Theme.component.breadcrumb.dropdown.icon.transitionDuration easing.type: Theme.component.breadcrumb.dropdown.icon.transitionTimingFunction } } } background: Item { visible: !root.compressed implicitHeight: dividerRect.visible ? dividerRect.height : 1 implicitWidth: dividerRect.visible ? dividerRect.width : 1 Image { id: dividerRect anchors.verticalCenter: parent.verticalCenter x: root.implicitWidth - width - Theme.component.breadcrumb.divider.marginRight visible: !root._isLastDelegate // Because the image provider returns a texture which is scaled properly // for the device pixel ratio (in order to ensure smooth rendering), // we CANNOT use the implicit width and height (because it won't be // in device-independent-pixels but rather in device-dependent-pixels). // Thus, specify width and height in device-independent-pixels directly. // TODO: remove these three lines for Qt 6.5 - see QTBUG-100355. height: sourceSize.height width: sourceSize.width fillMode: Image.PreserveAspectFit // Add one stroke-width of padding on each edge of the texture for antialiasing. // Specify all of these values in device independent pixels. property real strokeWidth: Theme.component.divider.borderWidth // TODO: Breadcrumb-specific theme constant sourceSize.height: (Theme.autodeskAngleCos * Theme.component.tablist.divider.height) + 2*strokeWidth sourceSize.width: (Theme.autodeskAngleTan * Theme.autodeskAngleCos * Theme.component.tablist.divider.height) + 2*strokeWidth source: "image://weave-angledivider/slash?color=" + Theme.component.breadcrumb.divider.backgroundColor + "&strokeWidth=" + strokeWidth * Screen.devicePixelRatio // Provide the prescaled device dependent value + "&scale=" + Screen.devicePixelRatio } } }