mirror of
https://github.com/zoriya/noctalia-shell.git
synced 2026-08-15 18:43:59 +00:00
Tray: hide all non pinned entries, reactive chevron
i18n: translation changes for tray
This commit is contained in:
@@ -16,7 +16,7 @@ NPanel {
|
||||
// Widget info for menu functionality
|
||||
property string widgetSection: ""
|
||||
property int widgetIndex: -1
|
||||
|
||||
|
||||
// Trigger refresh when settings change
|
||||
property int settingsVersion: 0
|
||||
|
||||
@@ -24,26 +24,36 @@ NPanel {
|
||||
readonly property var favoritesList: {
|
||||
// Reference settingsVersion to force recalculation when it changes
|
||||
var _ = root.settingsVersion
|
||||
if (widgetSection === "" || widgetIndex < 0) return []
|
||||
if (widgetSection === "" || widgetIndex < 0)
|
||||
return []
|
||||
var widgets = Settings.data.bar.widgets[widgetSection]
|
||||
if (!widgets || widgetIndex >= widgets.length) return []
|
||||
if (!widgets || widgetIndex >= widgets.length)
|
||||
return []
|
||||
var widgetSettings = widgets[widgetIndex]
|
||||
if (!widgetSettings || widgetSettings.id !== "Tray") return []
|
||||
if (!widgetSettings || widgetSettings.id !== "Tray")
|
||||
return []
|
||||
return widgetSettings.favorites || []
|
||||
}
|
||||
|
||||
function wildCardMatch(str, rule) {
|
||||
if (!str || !rule) return false
|
||||
if (!str || !rule)
|
||||
return false
|
||||
let escaped = rule.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
||||
let pattern = '^' + escaped.replace(/\\\*/g, '.*') + '$'
|
||||
try { return new RegExp(pattern, 'i').test(str) } catch(e) { return false }
|
||||
try {
|
||||
return new RegExp(pattern, 'i').test(str)
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
function isFavorite(item) {
|
||||
if (!favoritesList || favoritesList.length === 0) return false
|
||||
if (!favoritesList || favoritesList.length === 0)
|
||||
return false
|
||||
const title = item?.tooltipTitle || item?.name || item?.id || ""
|
||||
for (var i = 0; i < favoritesList.length; i++) {
|
||||
if (wildCardMatch(title, favoritesList[i])) return true
|
||||
if (wildCardMatch(title, favoritesList[i]))
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -51,7 +61,9 @@ NPanel {
|
||||
// Dynamic sizing based on item count
|
||||
// Show items that are NOT favorites (non-favorites go to dropdown)
|
||||
readonly property var trayValuesAll: (SystemTray.items && SystemTray.items.values) ? SystemTray.items.values : []
|
||||
readonly property var trayValues: trayValuesAll.filter(function(it){ return !root.isFavorite(it) })
|
||||
readonly property var trayValues: trayValuesAll.filter(function (it) {
|
||||
return !root.isFavorite(it)
|
||||
})
|
||||
readonly property int itemCount: trayValues.length
|
||||
readonly property int maxColumns: 8
|
||||
readonly property real cellSize: Math.round(Style.capsuleHeight * 0.65)
|
||||
@@ -126,32 +138,34 @@ NPanel {
|
||||
hoverEnabled: true
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
||||
|
||||
onClicked: (mouse) => {
|
||||
if (!modelData)
|
||||
return
|
||||
if (mouse.button === Qt.RightButton && modelData.hasMenu && modelData.menu && trayMenu.item) {
|
||||
trayMenu.item.menu = modelData.menu
|
||||
trayMenu.item.screen = root.screen
|
||||
trayMenu.item.trayItem = modelData
|
||||
trayMenu.item.widgetSection = root.widgetSection
|
||||
trayMenu.item.widgetIndex = root.widgetIndex
|
||||
const menuX = (root.columns > 1) ? (trayIcon.width / 2) : 0
|
||||
const menuY = trayIcon.height
|
||||
trayMenu.item.showAt(trayIcon, menuX, menuY)
|
||||
} else if (mouse.button === Qt.LeftButton) {
|
||||
modelData.activate?.()
|
||||
// Close the dropdown after activation
|
||||
PanelService.getPanel("trayDropdownPanel", root.screen)?.close()
|
||||
} else if (mouse.button === Qt.MiddleButton) {
|
||||
modelData.secondaryActivate?.()
|
||||
PanelService.getPanel("trayDropdownPanel", root.screen)?.close()
|
||||
}
|
||||
}
|
||||
onClicked: mouse => {
|
||||
if (!modelData)
|
||||
return
|
||||
if (mouse.button === Qt.RightButton && modelData.hasMenu && modelData.menu && trayMenu.item) {
|
||||
trayMenu.item.menu = modelData.menu
|
||||
trayMenu.item.screen = root.screen
|
||||
trayMenu.item.trayItem = modelData
|
||||
trayMenu.item.widgetSection = root.widgetSection
|
||||
trayMenu.item.widgetIndex = root.widgetIndex
|
||||
const menuX = (root.columns > 1) ? (trayIcon.width / 2) : 0
|
||||
const menuY = trayIcon.height
|
||||
trayMenu.item.showAt(trayIcon, menuX, menuY)
|
||||
} else if (mouse.button === Qt.LeftButton) {
|
||||
modelData.activate()
|
||||
// Close the dropdown after activation
|
||||
PanelService.getPanel("trayDropdownPanel", root.screen)?.close()
|
||||
} else if (mouse.button === Qt.MiddleButton) {
|
||||
modelData.secondaryActivate()
|
||||
PanelService.getPanel("trayDropdownPanel", root.screen)?.close()
|
||||
}
|
||||
}
|
||||
|
||||
onWheel: (wheel) => {
|
||||
if (wheel.angleDelta.y > 0) modelData?.scrollUp?.()
|
||||
else if (wheel.angleDelta.y < 0) modelData?.scrollDown?.()
|
||||
}
|
||||
onWheel: wheel => {
|
||||
if (wheel.angleDelta.y > 0)
|
||||
modelData?.scrollUp()
|
||||
else if (wheel.angleDelta.y < 0)
|
||||
modelData?.scrollDown()
|
||||
}
|
||||
|
||||
onEntered: TooltipService.show(Screen, trayIcon, modelData.tooltipTitle || modelData.name || modelData.id || "Tray Item", BarService.getTooltipDirection())
|
||||
onExited: TooltipService.hide()
|
||||
@@ -169,4 +183,4 @@ NPanel {
|
||||
source: "TrayMenu.qml"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,18 +303,23 @@ PopupWindow {
|
||||
|
||||
// Check if item is already a favorite
|
||||
readonly property bool isFavorite: {
|
||||
if (!root.trayItem || root.widgetSection === "" || root.widgetIndex < 0) return false
|
||||
if (!root.trayItem || root.widgetSection === "" || root.widgetIndex < 0)
|
||||
return false
|
||||
const itemName = root.trayItem.tooltipTitle || root.trayItem.name || root.trayItem.id || ""
|
||||
if (!itemName) return false
|
||||
|
||||
if (!itemName)
|
||||
return false
|
||||
|
||||
var widgets = Settings.data.bar.widgets[root.widgetSection]
|
||||
if (!widgets || root.widgetIndex >= widgets.length) return false
|
||||
if (!widgets || root.widgetIndex >= widgets.length)
|
||||
return false
|
||||
var widgetSettings = widgets[root.widgetIndex]
|
||||
if (!widgetSettings || widgetSettings.id !== "Tray") return false
|
||||
|
||||
if (!widgetSettings || widgetSettings.id !== "Tray")
|
||||
return false
|
||||
|
||||
var favorites = widgetSettings.favorites || []
|
||||
for (var i = 0; i < favorites.length; i++) {
|
||||
if (favorites[i] === itemName) return true
|
||||
if (favorites[i] === itemName)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -343,7 +348,7 @@ PopupWindow {
|
||||
NText {
|
||||
Layout.fillWidth: true
|
||||
color: Color.mPrimary
|
||||
text: addToFavoriteEntry.isFavorite ? I18n.tr("settings.bar.tray.remove-from-favorites") : I18n.tr("settings.bar.tray.add-as-favorite")
|
||||
text: addToFavoriteEntry.isFavorite ? I18n.tr("settings.bar.tray.unpin-application") : I18n.tr("settings.bar.tray.pin-application")
|
||||
pointSize: Style.fontSizeS
|
||||
font.weight: Font.Medium
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
@@ -414,6 +419,14 @@ PopupWindow {
|
||||
Settings.saveImmediate()
|
||||
|
||||
Logger.i("TrayMenu", "Added", itemName, "as favorite")
|
||||
|
||||
// Close the tray dropdown panel after pinning
|
||||
if (root.screen) {
|
||||
const panel = PanelService.getPanel("trayDropdownPanel", root.screen)
|
||||
if (panel) {
|
||||
panel.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function removeFromFavorites() {
|
||||
|
||||
@@ -109,7 +109,7 @@ Rectangle {
|
||||
}
|
||||
|
||||
// Build inline (favorites) and dropdown (non-favorites) lists
|
||||
// If favorites list is empty, all items are inline
|
||||
// If favorites list is empty, all items go to dropdown (none inline)
|
||||
// If favorites list has items, favorites are inline, rest go to dropdown
|
||||
if (favorites && favorites.length > 0) {
|
||||
let fav = []
|
||||
@@ -132,15 +132,19 @@ Rectangle {
|
||||
const cand = newItems[v]
|
||||
let isFavorite = false
|
||||
for (var f = 0; f < filteredItems.length; f++) {
|
||||
if (filteredItems[f] === cand) { isFavorite = true; break }
|
||||
if (filteredItems[f] === cand) {
|
||||
isFavorite = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!isFavorite) nonFav.push(cand)
|
||||
if (!isFavorite)
|
||||
nonFav.push(cand)
|
||||
}
|
||||
dropdownItems = nonFav
|
||||
} else {
|
||||
// No favorites: all items are inline
|
||||
filteredItems = newItems
|
||||
dropdownItems = []
|
||||
// No favorites: all items go to dropdown (none inline)
|
||||
filteredItems = []
|
||||
dropdownItems = newItems
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,9 +307,20 @@ Rectangle {
|
||||
NIconButton {
|
||||
id: dropdownButton
|
||||
visible: dropdownItems.length > 0
|
||||
width: itemSize
|
||||
height: itemSize
|
||||
icon: isVertical ? (barPosition === "left" ? "chevron-right" : "chevron-left") : "chevron-down"
|
||||
width: Math.round(itemSize * 1.4)
|
||||
height: Math.round(itemSize * 1.4)
|
||||
icon: {
|
||||
if (barPosition === "top")
|
||||
return "chevron-down"
|
||||
else if (barPosition === "bottom")
|
||||
return "chevron-up"
|
||||
else if (barPosition === "left")
|
||||
return "chevron-right"
|
||||
else if (barPosition === "right")
|
||||
return "chevron-left"
|
||||
else
|
||||
return "chevron-down" // default fallback
|
||||
}
|
||||
tooltipText: I18n.tr("open-control-center") // reuse generic tooltip text
|
||||
onClicked: {
|
||||
const panel = PanelService.getPanel("trayDropdownPanel", root.screen)
|
||||
|
||||
Reference in New Issue
Block a user