Files
omarchy/plugins/omaplug/panel/plugin/Row.qml
T
asepharyana 1cdb82a76f Sync config from arch
- hypr/apps.lua
- hypr/autostart.lua
- hypr/envs.lua
- hypr/hyprland.lua
- hypr/hyprsunset.conf
- hypr/input.lua
- hypr/looknfeel.lua
- hypr/omasettings.lua
- hypr/xdph.conf
- omarchy/branding/about.txt
- omarchy/branding/screensaver.txt
- omarchy/extensions/omarchy-menu.jsonc
- omarchy/hooks/battery-low.d/play-warning-sound.sample
- omarchy/hooks/font-set.d/show-font-notification.sample
- omarchy/hooks/post-boot.d/weather.sample
- omarchy/hooks/post-update.d/install-voxtype.hook
- omarchy/hooks/post-update.d/setup-agent.hook
- omarchy/hooks/post-update.d/setup-fingerprint.hook
- omarchy/hooks/post-update.d/show-update-notification.sample
- omarchy/hooks/pre-refresh-pacman.d/add-custom-repo.sample
- omarchy/hooks/theme-set.d/show-theme-notification.sample
- omarchy/shell.json
- omarchy/shell.toml
- omarchy/theme.name
- omarchy/themes/azure-glow/README.md
- omarchy/themes/azure-glow/alacritty.toml
- omarchy/themes/azure-glow/btop.theme
- omarchy/themes/azure-glow/hyprland.conf
- omarchy/themes/azure-glow/hyprlock.conf
- omarchy/themes/azure-glow/icons.theme
- … 269 more
2026-09-23 15:19:12 +07:00

383 lines
13 KiB
QML

pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import qs.Commons
import qs.Ui
import "../Presentation.js" as Presentation
Item {
id: pluginRow
required property var modelData
required property int index
required property int rowCount
required property var marketplaceEntry
required property string localCommit
required property string repoUrl
required property bool repoKnown
required property string updateState
required property bool removeSelectMode
required property bool selectedForRemoval
required property bool removingPlugin
required property bool pluginEnabled
required property bool updateRunning
required property string updatingId
required property string icon
required property var knownKinds
required property color foreground
required property string fontFamily
signal removalSelectionRequested(string pluginId)
signal enabledChangeRequested(string pluginId, bool enabled)
signal openUrlRequested(string url)
signal sourceRequested(string sourceKey)
signal updateRequested(string sourceKey)
signal menuRequested(string pluginId, var sourceItem, real x, real y)
readonly property bool listed: marketplaceEntry !== null
readonly property bool verified: listed && marketplaceEntry.verified === true
readonly property bool updateUnverified: listed && !verified
&& marketplaceEntry.snapshotStatus === "update-unverified"
readonly property string authorUrl: modelData.firstParty ? "" : Presentation.authorUrl(repoUrl)
readonly property string kindLabel: Presentation.kindLabel(modelData.kinds, knownKinds)
height: card.height + Style.space(9)
Rectangle {
id: card
width: parent.width
height: Math.max(Style.space(72), content.implicitHeight + Style.space(24))
clip: true
radius: Style.cornerRadius > 0 ? Style.cornerRadius : 4
color: hover.hovered
? Style.hoverFillFor(pluginRow.foreground, Color.accent)
: "transparent"
RowLayout {
id: content
anchors.fill: parent
anchors.leftMargin: Style.space(10)
anchors.topMargin: Style.space(10)
anchors.rightMargin: Style.space(10)
anchors.bottomMargin: Style.space(10)
spacing: Style.space(10)
Button {
visible: pluginRow.removeSelectMode
text: pluginRow.selectedForRemoval ? "\uf14a" : "\uf0c8"
tooltipText: "Select plugin for removal"
enabled: !pluginRow.removingPlugin
Layout.alignment: Qt.AlignVCenter
foreground: pluginRow.foreground
accent: Color.accent
fontFamily: pluginRow.fontFamily
fontSize: Style.font.bodySmall
horizontalPadding: Style.space(6)
verticalPadding: Style.space(3)
onClicked: pluginRow.removalSelectionRequested(pluginRow.modelData.id)
}
Item {
Layout.preferredWidth: Style.space(28)
Layout.preferredHeight: Style.space(28)
Rectangle {
x: 0
y: 0
width: Style.space(28)
height: Style.space(28)
radius: 6
clip: true
color: Presentation.iconColor(pluginRow.modelData.name)
Text {
anchors.centerIn: parent
width: parent.width - 4
horizontalAlignment: Text.AlignHCenter
elide: Text.ElideRight
maximumLineCount: 1
text: pluginRow.icon || pluginRow.modelData.name.trim().charAt(0).toUpperCase()
textFormat: Text.PlainText
color: "white"
font.family: pluginRow.fontFamily
font.pixelSize: Style.font.bodySmall
font.bold: true
}
}
Rectangle {
visible: pluginRow.updateState === "UPDATE"
x: -2
y: -2
width: 8
height: 8
radius: 4
color: Color.accent
border.color: pluginRow.foreground
border.width: 1
z: 1
}
}
ColumnLayout {
// preferredWidth 0 + fillWidth: take leftover row space instead of the
// description's single-line implicitWidth (otherwise Wrap/Elide never
// bind and card.clip cuts mid-word with no ellipsis).
Layout.fillWidth: true
Layout.preferredWidth: 0
Layout.minimumWidth: 0
Layout.alignment: Qt.AlignVCenter
spacing: Style.space(2)
Item {
id: nameRow
Layout.fillWidth: true
implicitHeight: Math.max(nameLabel.implicitHeight,
verificationBadge.visible ? verificationBadge.implicitHeight : 0,
versionLabel.visible ? versionLabel.implicitHeight : 0)
readonly property real spacing: Style.space(8)
Label {
id: nameLabel
text: pluginRow.modelData.name
textFormat: Text.PlainText
color: pluginRow.foreground
font.family: pluginRow.fontFamily
font.pixelSize: Style.font.body
font.bold: true
// Keep short names adjacent to their metadata. Long names use
// only the space left after the badge/version, then elide.
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
width: Math.min(implicitWidth, Math.max(0, nameRow.width
- (verificationBadge.visible ? verificationBadge.implicitWidth + nameRow.spacing : 0)
- (versionLabel.visible ? versionLabel.implicitWidth + nameRow.spacing : 0)))
elide: Label.ElideRight
// Full name only when elided · matches author/ListingLinks ToolTip style.
ToolTip.text: truncated ? text : ""
ToolTip.visible: nameHover.hovered && truncated
ToolTip.delay: 400
HoverHandler {
id: nameHover
}
}
Rectangle {
id: verificationBadge
visible: pluginRow.listed
anchors.left: nameLabel.right
anchors.leftMargin: nameRow.spacing
anchors.verticalCenter: parent.verticalCenter
radius: height / 2
implicitWidth: badgeContent.implicitWidth + Style.space(10)
implicitHeight: Style.space(16)
color: pluginRow.updateUnverified
? Qt.rgba(0.85, 0.65, 0.13, 0.18)
: pluginRow.verified
? Util.alpha(Color.accent, 0.18)
: Qt.rgba(pluginRow.foreground.r, pluginRow.foreground.g, pluginRow.foreground.b, 0.08)
Row {
id: badgeContent
anchors.centerIn: parent
spacing: Style.space(3)
Text {
visible: pluginRow.verified && !pluginRow.updateUnverified
text: "\uf058"
textFormat: Text.PlainText
color: Color.accent
font.family: pluginRow.fontFamily
font.pixelSize: Style.font.caption - 1
anchors.verticalCenter: parent.verticalCenter
}
Text {
visible: pluginRow.updateUnverified
text: "\uf071"
textFormat: Text.PlainText
color: Qt.hsla(0.12, 0.75, 0.55, 1)
font.family: pluginRow.fontFamily
font.pixelSize: Style.font.caption - 1
anchors.verticalCenter: parent.verticalCenter
}
Text {
text: pluginRow.updateUnverified ? "Update Unverified" : pluginRow.verified ? "Verified" : "Unverified"
textFormat: Text.PlainText
color: pluginRow.updateUnverified ? Qt.hsla(0.12, 0.75, 0.55, 1)
: pluginRow.verified ? Color.accent
: Qt.darker(pluginRow.foreground, 2.0)
font.family: pluginRow.fontFamily
font.pixelSize: Style.font.caption - 1
anchors.verticalCenter: parent.verticalCenter
}
}
}
Label {
id: versionLabel
visible: pluginRow.modelData.version !== "unknown"
anchors.left: verificationBadge.visible ? verificationBadge.right : nameLabel.right
anchors.leftMargin: nameRow.spacing
anchors.verticalCenter: parent.verticalCenter
text: "v" + pluginRow.modelData.version
textFormat: Text.PlainText
color: Qt.darker(pluginRow.foreground, 2.0)
font.family: pluginRow.fontFamily
font.pixelSize: Style.font.caption
}
}
Label {
id: descriptionLabel
text: pluginRow.modelData.description !== "" ? pluginRow.modelData.description : "No description"
textFormat: Text.PlainText
color: Qt.darker(pluginRow.foreground, 1.6)
font.family: pluginRow.fontFamily
font.pixelSize: Style.font.bodySmall
Layout.fillWidth: true
Layout.preferredWidth: 0
Layout.minimumWidth: 0
wrapMode: Label.Wrap
maximumLineCount: 2
elide: Label.ElideRight
ToolTip.text: truncated ? text : ""
ToolTip.visible: descriptionHover.hovered && truncated
ToolTip.delay: 400
HoverHandler {
id: descriptionHover
}
}
RowLayout {
visible: pluginRow.modelData.author !== ""
spacing: Style.space(6)
Layout.fillWidth: true
Text {
text: "by " + pluginRow.modelData.author + (pluginRow.authorUrl !== "" ? " ↗" : "")
Layout.minimumWidth: 0
elide: Text.ElideRight
textFormat: Text.PlainText
color: pluginRow.authorUrl !== "" ? Color.accent : Qt.darker(pluginRow.foreground, 2.0)
font.family: pluginRow.fontFamily
font.pixelSize: Style.font.caption
font.underline: authorHover.hovered && pluginRow.authorUrl !== ""
ToolTip.text: pluginRow.authorUrl !== "" ? pluginRow.authorUrl : ("by " + pluginRow.modelData.author)
ToolTip.visible: authorHover.hovered
ToolTip.delay: 400
HoverHandler {
id: authorHover
cursorShape: pluginRow.authorUrl !== "" ? Qt.PointingHandCursor : Qt.ArrowCursor
}
MouseArea {
anchors.fill: parent
enabled: pluginRow.authorUrl !== ""
cursorShape: Qt.PointingHandCursor
onClicked: pluginRow.openUrlRequested(pluginRow.authorUrl)
}
}
Text {
visible: pluginRow.kindLabel !== ""
text: "·"
textFormat: Text.PlainText
color: Qt.darker(pluginRow.foreground, 2.0)
font.family: pluginRow.fontFamily
font.pixelSize: Style.font.caption
}
Label {
visible: pluginRow.kindLabel !== ""
text: pluginRow.kindLabel
textFormat: Text.PlainText
color: Qt.darker(pluginRow.foreground, 2.0)
font.family: pluginRow.fontFamily
font.pixelSize: Style.font.caption
elide: Label.ElideRight
Layout.minimumWidth: 0
Layout.alignment: Qt.AlignRight
}
Item {
Layout.fillWidth: true
Layout.preferredHeight: 1
}
}
ListingLinks {
visible: pluginRow.listed
pluginId: pluginRow.modelData.id
entry: pluginRow.marketplaceEntry
localCommit: pluginRow.localCommit
repoUrl: pluginRow.repoUrl
foreground: pluginRow.foreground
fontFamily: pluginRow.fontFamily
onOpenUrlRequested: function(url) { pluginRow.openUrlRequested(url) }
}
}
Actions {
plugin: pluginRow.modelData
pluginEnabled: pluginRow.pluginEnabled
repoKnown: pluginRow.repoKnown
updateState: pluginRow.updateState
updateRunning: pluginRow.updateRunning
updatingId: pluginRow.updatingId
foreground: pluginRow.foreground
fontFamily: pluginRow.fontFamily
onEnabledChangeRequested: function(enabled) {
pluginRow.enabledChangeRequested(pluginRow.modelData.id, enabled)
}
onSourceRequested: function(sourceKey) { pluginRow.sourceRequested(sourceKey) }
onUpdateRequested: function(sourceKey) { pluginRow.updateRequested(sourceKey) }
onMenuRequested: function(sourceItem, x, y) {
pluginRow.menuRequested(pluginRow.modelData.id, sourceItem, x, y)
}
}
}
HoverHandler {
id: hover
}
TapHandler {
id: contextTap
acceptedButtons: Qt.RightButton
onTapped: function(eventPoint) {
pluginRow.menuRequested(
pluginRow.modelData.id,
card,
eventPoint.position.x,
eventPoint.position.y
)
}
}
}
Rectangle {
visible: pluginRow.index < pluginRow.rowCount - 1
anchors.top: card.bottom
anchors.topMargin: Style.space(4)
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Style.space(10)
anchors.rightMargin: Style.space(10)
height: 1
color: Qt.rgba(pluginRow.foreground.r, pluginRow.foreground.g, pluginRow.foreground.b, 0.12)
}
}