import QtQuick import QtQuick.Controls import GeneralBiz import FusionUI import Purchase import VECreator import FunctionPanel import GeneralBizUI import VipBiz PanelDeepLinkItem { id: root property bool alignKeyFrame: false // Align the buttons (when there are other buttons with keyframes in the panel and it does not, set it to true to let the other buttons a little left property bool applytoAllEnable: true // Is all applications available property string applytoAllTitle: i18n.tr("pc_all_apply") property bool checked: true // Whether it is checked property bool collapsed: false // Is it folded? property bool collapsible: true // Whether folding is allowed property bool reverseVisible: false // Is it supported inversion? property bool reverseEnable: false // Is the inversion available property bool collapseAfterDisable: false // Is it automatically folded when disable property int dataHeight: 0 // When using it, you need to bind the height of the content to dataHeight property int dataY: titleHeight + 16 // When using it, you need to specify the height of the content to be dataY property string disableCheckHint: i18n.tr("pc_not_currently_supported") // Prompt when the control is disabled property bool enableReset: true // Whether to enable reset is available property real totalHeight: (collapseAfterDisable && !enabled) ? titleHeight : ((collapsible && collapsed) ? (titleHeight) : (dataHeight == 0 ? titleHeight : dataY + dataHeight)) property Component extraComponent: null // Customizable controls in the upper right corner property alias helpHint: helpLogo.tipText // Help Tips property Component iconComponent: null // Customizable icon in the upper left corner property Component expandComponent: null // 展开内容控件 property alias expandComponentLoader: expandLoader // 展开内容控件Loader property alias expandComponentLoadAsync: expandLoader.asynchronous // 是否异步加载 property bool forceLoad: false // 是否强制加载 property alias inEditingSet: keyFrameBtn.inEditingSet property alias inPanelKeyBtn: keyFrameBtn.inSetKeyBtn property bool isMix: false // Is the check state during multiple selection? property alias keyFrameAddedPoint: keyFrameBtn.addedPoint property alias keyFrameEnabled: keyFrameBtn.keyFrameEnabled property alias keyFrameLeftBtnActived: keyFrameBtn.leftBtnActived property alias keyFrameRightBtnActived: keyFrameBtn.rightBtnActived property alias materialID: keyFrameBtn.materialID property alias category : keyFrameBtn.category property bool limitSummaryWidth: false property alias parentViewModel: keyFrameBtn.parentViewModel property alias propertyTypeGroup: keyFrameBtn.propertyTypeGroup property string standaloneUnderSummary: "" property string summary: "summary" property bool summaryUnder: false // Whether to display summary on the next line property bool summaryUnderRight: false property bool tipOnAll: false // Whether to display the prompts in the overall property bool useTitle: true property string title: "SettingsGroup" // Group name property int titleHeight: titleBar.height + underSummaryText.height + standaloneUnderSummaryText.height + standaloneUnderSummaryText.anchors.topMargin property string titleTips: "" // Auxiliary tips on the right side of the group name property bool useApplytoAll: false // Whether to enable the App All Buttons property bool applyAllButtonFocusable: false property bool useCheck: true // Whether to enable the check button property bool useHelp: false // Whether to enable help property alias useHelpToolTip: helpLogo.useToolTip // Whether to enable help prompts (help can be tooltip, bubble, etc.) property alias helpBtn: helpLogo property bool useKeyFrame: true // Whether to enable keyframes property bool useReset: false // Whether to enable the reset button property bool useSummary: false // Whether to enable subtext (display a line of words to the right of the title bar) property bool useTitleOpacity: false // When unchcked, whether to enable title font graying property real titleTextLeftMargin: 8 property bool vipFeature: false // Is it a VIP function? property bool showDisableTips: true property bool limitFreeFeature: false // Is it limited to free functions? Ion is preferred to display more than VIP property Component vipLimitIcon: null property string vipIdentifier: "" property alias vipSceneType: vipLogo.sceneType property alias vipIconVisible: vipLogo.visible property alias vipIconWidth: vipLogo.width property string ccLimitFreeIcon: "qrc:/FunctionPanel/resources/ic_free_cc_512w.png" property string proLimitFreeIcon: "qrc:/FunctionPanel/resources/ic_free.svg" property int limitFreeIconWidth: CAPCUT ? 25 : 24 property int limitFreeIconHeight: 10 property bool useTips: false property string tipsImage: "" property string tipsText: "" property bool isComponentComplete: false property bool showGroupTips : true property bool useProgress: false property real progressVal: -1 property string progressTips: "" property var maskWindow: null property bool needShowMask: false property bool enableTotalHeightBehavior: false property string resetTip: (VECContext.copywritingABTest() ? i18n.tr("pc_new_reset"):i18n.tr("reset")) property bool limitSvgSourceSize: AbTestConfigSettings.enableSvgSourceSizeLimit signal applyAllClicked // Apply all button press signals signal checkBtnClicked // The difference between the signal pressed by the checkbox, onCheckedChanged and it is that it may be triggered by the viewModel signal collapsedClicked signal inEditingSet(var state) signal nextKeyFrame signal prevKeyFrame signal resetBtnClicked // Reset the signal pressed by the button signal setKeyFrame signal vipIconClicked signal reverseBtnClicked // Help button event (non-tooltip scenario) signal helpEntered signal helpExited signal helpClicked function onContentYChanged() { if (needShowMask) { showMask(true) } } function onCollapsedRealClicked() { enableTotalHeightBehavior = true } onSigDeepLinkBefore: function(querys) { if (root.collapsed) { root.collapsed = false; root.collapsedClicked() root.onCollapsedRealClicked(); } let clickCheckBtn = querys?.check ?? true if (clickCheckBtn !== undefined && root.enabled) { console.info("[DeepLink] clickCheckBtn", clickCheckBtn, " root.checked", root.checked); if (clickCheckBtn !== root.checked) { root.checkBtnClicked(); } } } function showMask(disconnect) { Qt.callLater(() => { if (maskWindow === null) { maskWindow = maskWindowComponent.createObject(null, {parentWindow: root}) } const globalPos = root.mapToGlobal(0, 0) maskWindow.x = globalPos.x - 8 maskWindow.y = globalPos.y - 5 maskWindow.width = width + 16 maskWindow.height = 32 maskWindow.visible = true needShowMask = false }) if (disconnect) { let flickableItem = getFlickableItem() if (flickableItem) { flickableItem.contentYChanged.disconnect(onContentYChanged) } } } function scrollPosY(yHeight) { let flickableItem = undefined; let p = parent; while (p) { if (p instanceof Flickable) { flickableItem = p; break; } else { p = p.parent; } } console.log("[DeepLink] flickableItem: " + flickableItem); if (!flickableItem) { console.warn("[DeepLink] flickableItem not found!"); return; } flickableItem.contentY += yHeight; } function isPositionInVipLogo(mouseX, mouseY) { if (!vipLogo.visible) return false let vipLogoPoint = vipLogo.mapToGlobal(0, 0) let vipLogoX = vipLogoPoint.x let vipLogoY = vipLogoPoint.y return mouseX >= vipLogoX && mouseX < (vipLogoX + vipLogo.width) && mouseY >= vipLogoY && mouseY < (vipLogoY + vipLogo.height) } Accessible.name: { return VEQmlHelper.GetAutomationIDName(this); } clip: true height: visible ? totalHeight : 0 width: parent.width property bool enableAnimation: true Behavior on totalHeight { enabled: enableAnimation && enableTotalHeightBehavior PropertyAnimation { duration: 100 easing.type: Easing.OutQuart onRunningChanged: { if (!running) { root.enableTotalHeightBehavior = false } } } } function evalExpandComponentActive() { if (!isComponentComplete) return if (!collapsed && expandComponent !== null) { expandLoader.active = true } } onCollapsedChanged: { evalExpandComponentActive() } Component.onCompleted: { isComponentComplete = true evalExpandComponentActive() } onExpandComponentChanged: { evalExpandComponentActive() } onCheckedChanged: { if (checked) { // Force refresh if dataHeight is 0 to avoid displaying wrong height when Column does not specify a height. if (dataHeight === 0 && collapsible) { collapsed = true; collapsed = false; root.height = Qt.binding(() => visible ? totalHeight : 0) } else { collapsed = false; } } } onInEditingSet: state => { keyFrameBtn.inEditingSet = state; } Text { Accessible.description: parent.Accessible.name } Item { id: titleBar property real spacing: 8 function checkSummaryWidth() { if (root.limitSummaryWidth) { // Solve the problem of overlapping information copywriting on overseas destroying, custom keying and other prompts let limitWidth = titleBar.width - check.width - titleText.implicitWidth - vipLogo.width - arrow.width - alignKeyFrameBtn.width - titleBar.spacing * 3; summaryText.width = summaryText.implicitWidth < limitWidth ? summaryText.implicitWidth : limitWidth; } } visible: root.useTitle enabled: root.enabled height: 22 width: parent.width onWidthChanged: { checkSummaryWidth(); } Loader { id: iconCom anchors.verticalCenter: parent.verticalCenter sourceComponent: root.iconComponent visible: sourceComponent != null } GroupCheckbox { id: check anchors.left: iconCom.right anchors.verticalCenter: parent.verticalCenter enabled: root.enabled opacity: root.enabled ? 1 : 0.3 visible: root.useCheck width: root.useCheck ? 12 : 0 Accessible.name: VEQmlHelper.GetAutomationIDName(this) + root.title } Text { id: titleText anchors.left: check.right anchors.leftMargin: (check.visible || iconCom.visible) ? root.titleTextLeftMargin : 0 anchors.verticalCenter: parent.verticalCenter color: LVColor.White0_Text_Primary font: LVFont.ButtonSemibold11 opacity: !useTitleOpacity ? 1 : root.checked ? 1 : 0.3 text: root.title } Item { id: showTipsItem visible: root.useTips anchors.left: titleText.right anchors.leftMargin: 10 height: parent.height Image { id: tips_Image width: 16 height: 16 source: root.tipsImage sourceSize: Qt.size(width, height) anchors.verticalCenter: parent.verticalCenter anchors.left: parent.left } Text { id: tips_Text text: root.tipsText color: LVColor.State_Warning_Default font: LVFont.ButtonRegular11 anchors.verticalCenter: parent.verticalCenter anchors.left: tips_Image.right anchors.leftMargin: 4 visible: root.useTips } } PanelSettingsGroupVipFeatureIcon { id: vipLogo vipFeature: root.vipFeature limitFreeFeature: root.limitFreeFeature vipLimitIcon: root.vipLimitIcon vipIdentifier: root.vipIdentifier anchors { left: helpLogo.right leftMargin: 4 verticalCenter: parent.verticalCenter } onVipIconClicked: { root.vipIconClicked(); } } Text { id: titleTipsText color: LVColor.White0_Text_Primary font: LVFont.SubtitleRegular11 text: root.titleTips visible: root.titleTips.length > 0 anchors { left: vipLogo.visible ? vipLogo.right : (useHelp ? helpLogo.right : titleText.right) leftMargin: 2 verticalCenter: parent.verticalCenter } } Image { property bool __focusable: true anchors.left: titleTipsText.visible ? titleTipsText.right : vipLogo.visible ? vipLogo.right : (useHelp ? helpLogo.right : titleText.right) anchors.verticalCenter: parent.verticalCenter height: 16 rotation: root.collapsed ? 180 : 0 source: LVColor.Enable_New_Color_Table ? "qrc:/FunctionPanel/resources/new_color_table_collapseArrow.svg" : "qrc:/FunctionPanel/resources/collapseArrow.svg" sourceSize: Qt.size(width, height) visible: root.collapsible width: 16 } Row { id: rightBtns anchors.right: parent.right anchors.topMargin: root.summaryUnder && root.summary ? 30 : 0 anchors.verticalCenter: parent.verticalCenter enabled: root.checked layoutDirection: Qt.RightToLeft spacing: titleBar.spacing Item { id: alignKeyFrameBtn height: 22 visible: root.alignKeyFrame && !root.useKeyFrame width: 32 } VEKeyFrame { id: keyFrameBtn visible: root.useKeyFrame } VETextButton { id: applyAllBtn property bool __focusable: root.applyAllButtonFocusable enabled: root.applytoAllEnable height: 22 title: applytoAllTitle type: VECType.VETextButton_secondary1 visible: root.useApplytoAll width: 72 onClicked: { root.applyAllClicked(); } } TitleButton { disabledIconSource: LVColor.Enable_New_Color_Table ? "qrc:/FunctionPanel/resources/new_color_table_reset.svg" : "qrc:/FunctionPanel/resources/reset.svg" enabled: rightBtns.enabled && root.enableReset iconSource: LVColor.Enable_New_Color_Table ? "qrc:/FunctionPanel/resources/new_color_table_reset.svg" : "qrc:/FunctionPanel/resources/reset.svg" tips: root.resetTip visible: root.useReset opacity: enabled ? 1 : 0.3 onClicked: { root.resetBtnClicked(); } } TitleButton { enabled: rightBtns.enabled && root.reverseEnable iconSource: LVColor.Enable_New_Color_Table ? "qrc:/FunctionPanel/resources/new_color_reverse.svg" : "qrc:/FunctionPanel/resources/reverse.svg" disabledIconSource: LVColor.Enable_New_Color_Table ? "qrc:/FunctionPanel/resources/new_color_reverse.svg" : "qrc:/FunctionPanel/resources/reverse.svg" tips: i18n.tr("reverse") visible: root.reverseVisible opacity: enabled ? 1 : 0.3 onClicked: { root.reverseBtnClicked(); } } Loader { sourceComponent: root.extraComponent visible: sourceComponent != null } Text { id: summaryText color: LVColor.Text_Tertiary elide: limitSummaryWidth ? Text.ElideRight : Text.ElideNone font: LVFont.SubtitleRegular11 height: 22 horizontalAlignment: Text.AlignRight lineHeight: 11 lineHeightMode: Text.FixedHeight text: root.summary verticalAlignment: Text.AlignVCenter visible: root.useSummary && !root.summaryUnder wrapMode: limitSummaryWidth ? Text.NoWrap : Text.Wrap LVToolTip { anchors.fill: parent text: summaryText.text visible: summaryText.truncated } } TaskProgress { visible: root.useProgress progress: root.progressVal LVToolTip { anchors.fill: parent text: root.progressTips } } } ToolTipMouseArea { id: titleBarHotArea disableTips: root.disableCheckHint tips: root.collapsed ? (VECContext.copywritingABTest() ? i18n.tr("pc_new_show"):i18n.tr("spread")) : i18n.tr("put_away") visible: (root.collapsible || root.tipOnAll && !root.enabled ) && (showDisableTips || root.enabled) onClicked: mouse => { let mouseGlobalPoint = titleBarHotArea.mapToGlobal(mouse.x, mouse.y) if (vipLogo.visible && isPositionInVipLogo(mouseGlobalPoint.x, mouseGlobalPoint.y)) { return vipLogo.iconClick() } root.onCollapsedRealClicked(); root.collapsed = !root.collapsed; root.collapsedClicked(); } anchors { bottom: titleBar.bottom left: titleText.left right: rightBtns.left rightMargin: 4 top: titleBar.top } } VEHelpButton { id: helpLogo visible: useHelp width: visible ? 10 : 0 anchors { left: titleText.right leftMargin: visible ? 4 : 0 verticalCenter: parent.verticalCenter } onEntered: { root.helpEntered() } onExited: { root.helpExited() } onClicked: { root.helpClicked() } } Connections { target: root function onSummaryChanged() { titleBar.checkSummaryWidth(); } } } Text { id: underSummaryText color: LVColor.Text_Tertiary font: LVFont.SubtitleRegular11 height: visible ? (contentHeight + 4) : 0 text: root.summary visible: root.useSummary && root.summaryUnder && root.summary wrapMode: Text.Wrap anchors { left: root.summaryUnderRight ? undefined : titleBar.left right: root.summaryUnderRight ? titleBar.right : undefined top: titleBar.bottom topMargin: visible ? 4 : 0 } } Text { id: standaloneUnderSummaryText color: LVColor.Text_Tertiary font: LVFont.SubtitleRegular11 height: root.standaloneUnderSummary ? contentHeight : 0 text: root.standaloneUnderSummary width: titleBar.width wrapMode: Text.Wrap anchors { left: titleBar.left top: titleBar.bottom topMargin: root.standaloneUnderSummary ? 4 : 0 } } Component { id: maskWindowComponent Window { id: maskWindow flags: Qt.WA_TranslucentBackground | Qt.FramelessWindowHint | Qt.WindowTransparentForInput color: "transparent" visible: false onVisibleChanged:{ if (visible) { maskRectOpacityAnimator.start() } } Rectangle { id: maskRect visible: true anchors.left: parent.left anchors.top: parent.top width: parent.width height: parent.height radius: 4 color: LVColor.Transparency_Brand_012 border.color: LVColor.Transparency_Brand_040 border.width: 1 opacity: 1 SequentialAnimation { id: maskRectOpacityAnimator NumberAnimation { target: maskRect; property: "opacity"; to: 1; duration: 500 } NumberAnimation { target: maskRect; property: "opacity"; to: 0; duration: 1000 } onFinished: { maskWindow.visible = false } } MouseArea { anchors.fill: parent enabled: false } } } } Loader { id: expandLoader active: forceLoad || !AppPerformanceGlobalConfig.functionPanelOptimizeEnable visible: active width: parent.width y: parent.dataY sourceComponent: expandComponent asynchronous: AppPerformanceGlobalConfig.functionPanelOptimizeEnable onLoaded: { console.log("expandLoader loaded", collapsed) } } component GroupCheckbox: Item { property bool __focusable: true property url checkedIconSource: "qrc:/GeneralBizUI/resources/controls/check_button/CheckButtonOn.svg" property url defaultIconSource: LVColor.Enable_New_Color_Table ? "qrc:/GeneralBizUI/resources/controls/check_button/new_color_table_CheckButtonOff.svg" : "qrc:/GeneralBizUI/resources/controls/check_button/CheckButtonOff.svg" property url mixIconSource: "qrc:/GeneralBizUI/resources/controls/check_button/CheckButtonMix.svg" property bool __accept_vague_touch: true height: 12 width: 12 Image { anchors.fill: parent source: root.isMix ? mixIconSource : (root.checked ? checkedIconSource : defaultIconSource) sourceSize: limitSvgSourceSize ? Qt.size(width * 2, height * 2) : Qt.size(root.width, root.height) } ToolTipMouseArea { anchors.fill: parent disableTips: disableCheckHint tips: root.checked ? (VECContext.copywritingABTest() ? i18n.tr("pc_new_hide"):i18n.tr("pc_turn_off")) : (VECContext.copywritingABTest() ? i18n.tr("pc_new_show"):i18n.tr("pc_turn_on")) visible : (showDisableTips || root.enabled) && root.showGroupTips onClicked: { if (!root.checked && root.collapsed) { root.onCollapsedRealClicked(); } root.checkBtnClicked(); } } MouseArea { anchors.fill: parent visible: !root.showGroupTips cursorShape: Qt.PointingHandCursor onClicked: (mouse) => { if (!root.checked && root.collapsed) { root.onCollapsedRealClicked(); } root.checkBtnClicked(); } } } component Spliter: Rectangle { color: LVColor.Line_Level2 height: 1 width: parent.width } component TitleButton: Item { property bool __focusable: true property url disabledIconSource: "" property url iconSource: "" property alias tips: hotArea.tips signal clicked height: 22 width: 22 Image { id: img source: enabled ? parent.iconSource : parent.disabledIconSource sourceSize: Qt.size(parent.width, parent.height) } ToolTipMouseArea { id: hotArea anchors.fill: parent onClicked: { parent.clicked(); } } } component ToolTipMouseArea: LVToolTip { property string disableTips: i18n.tr("pc_not_currently_supported") property string tips: "" cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor needClickEvent: true needFollowMouse: true offsetY: 5 text: parent.enabled ? tips : disableTips } component TaskProgress: Item { property real progress : -1 width: 16 height: 16 anchors { verticalCenter: parent.verticalCenter } Image { visible: taskPro.visible === false anchors.fill: parent source: "qrc:/FunctionPanel/resources/task_wait_filled.svg" sourceSize: Qt.size(width * 2, height * 2) } Progress { id: taskPro anchors.fill: parent visible: parent.progress >= 0 progress: parent.progress } } component Progress: Item { id: progressItem property real progress : 0 onProgressChanged: { if (progress < 0 || progress > 1) { return; } canvas.requestPaint(); } Canvas { id: canvas anchors.fill: parent onPaint: { let centerX = canvas.width / 2 let centerY = canvas.height / 2 let radius = canvas.width / 2 - 2 var ctx = getContext("2d"); ctx.save(); ctx.clearRect(0, 0, canvas.width, canvas.height) ctx.beginPath(); ctx.lineWidth = 2; ctx.strokeStyle = "#33FFFFFF"; ctx.arc(centerX, centerY, radius, 0, Math.PI*2); ctx.stroke(); ctx.beginPath(); ctx.lineWidth = 2; ctx.lineCap = "round"; ctx.strokeStyle = "#FFFFFF" let current = -Math.PI/2 + (Math.PI * 2) * progressItem.progress; ctx.arc(centerX, centerY, radius, -Math.PI/2, current); ctx.stroke(); ctx.restore(); } } } }