summaryrefslogtreecommitdiff
path: root/raveos-hyprland-theme/theme-data/dms/Widgets/DankLocationSearch.qml
diff options
context:
space:
mode:
authorNippy <nippy@rp1.hu>2026-05-08 19:50:49 +0200
committerNippy <nippy@rp1.hu>2026-05-08 19:50:49 +0200
commit3462bcc46ecf74f576ea4397f16492c16bd75b10 (patch)
treec5ab7aef4498647e057bda8d49c11e5f9dda74c9 /raveos-hyprland-theme/theme-data/dms/Widgets/DankLocationSearch.qml
parent56616f693b4f263cbf0d47da43b67424efa6022d (diff)
downloadRaveOS-PKGBUILD-3462bcc46ecf74f576ea4397f16492c16bd75b10.tar.gz
RaveOS-PKGBUILD-3462bcc46ecf74f576ea4397f16492c16bd75b10.zip
raveos update
Diffstat (limited to 'raveos-hyprland-theme/theme-data/dms/Widgets/DankLocationSearch.qml')
-rw-r--r--raveos-hyprland-theme/theme-data/dms/Widgets/DankLocationSearch.qml266
1 files changed, 266 insertions, 0 deletions
diff --git a/raveos-hyprland-theme/theme-data/dms/Widgets/DankLocationSearch.qml b/raveos-hyprland-theme/theme-data/dms/Widgets/DankLocationSearch.qml
new file mode 100644
index 0000000..d58538a
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/dms/Widgets/DankLocationSearch.qml
@@ -0,0 +1,266 @@
+import QtQuick
+import qs.Common
+import qs.Widgets
+
+Item {
+ id: root
+
+ activeFocusOnTab: true
+
+ KeyNavigation.tab: keyNavigationTab
+ KeyNavigation.backtab: keyNavigationBacktab
+
+ onActiveFocusChanged: {
+ if (activeFocus) {
+ locationInput.forceActiveFocus();
+ }
+ }
+
+ property string currentLocation: ""
+ property string placeholderText: I18n.tr("Search for a location...")
+ property bool _internalChange: false
+ property bool isLoading: false
+ property string currentSearchText: ""
+ property Item keyNavigationTab: null
+ property Item keyNavigationBacktab: null
+
+ signal locationSelected(string displayName, string coordinates)
+
+ function resetSearchState() {
+ locationSearchTimer.stop();
+ dropdownHideTimer.stop();
+ isLoading = false;
+ searchResultsModel.clear();
+ }
+
+ width: parent.width
+ height: searchInputField.height + (searchDropdown.visible ? searchDropdown.height : 0)
+
+ ListModel {
+ id: searchResultsModel
+ }
+
+ Timer {
+ id: locationSearchTimer
+
+ interval: 500
+ running: false
+ repeat: false
+ onTriggered: {
+ if (locationInput.text.length > 2) {
+ searchResultsModel.clear();
+ root.isLoading = true;
+ const searchLocation = locationInput.text;
+ root.currentSearchText = searchLocation;
+ const encodedLocation = encodeURIComponent(searchLocation);
+ const searchUrl = "https://nominatim.openstreetmap.org/search?q=" + encodedLocation + "&format=json&limit=5&addressdetails=1";
+ Proc.runCommand("locationSearch", ["dms", "dl", "-4", "--timeout", "10", searchUrl], (output, exitCode) => {
+ root.isLoading = false;
+ if (exitCode !== 0) {
+ searchResultsModel.clear();
+ return;
+ }
+ if (root.currentSearchText !== locationInput.text)
+ return;
+ const raw = output.trim();
+ searchResultsModel.clear();
+ if (!raw || raw[0] !== "[") {
+ return;
+ }
+ try {
+ const data = JSON.parse(raw);
+ if (data.length === 0) {
+ return;
+ }
+ for (var i = 0; i < Math.min(data.length, 5); i++) {
+ const location = data[i];
+ if (location.display_name && location.lat && location.lon) {
+ const parts = location.display_name.split(', ');
+ let cleanName = parts[0];
+ if (parts.length > 1) {
+ const state = parts[parts.length - 2];
+ if (state && state !== cleanName)
+ cleanName += `, ${state}`;
+ }
+ const query = `${location.lat},${location.lon}`;
+ searchResultsModel.append({
+ "name": cleanName,
+ "query": query
+ });
+ }
+ }
+ } catch (e) {}
+ });
+ }
+ }
+ }
+
+ Timer {
+ id: dropdownHideTimer
+
+ interval: 200
+ running: false
+ repeat: false
+ onTriggered: {
+ if (!locationInput.getActiveFocus() && !searchDropdown.hovered)
+ root.resetSearchState();
+ }
+ }
+
+ Item {
+ id: searchInputField
+
+ width: parent.width
+ height: 48
+
+ DankTextField {
+ id: locationInput
+
+ width: parent.width
+ height: parent.height
+ leftIconName: "search"
+ placeholderText: root.placeholderText
+ text: ""
+ backgroundColor: Theme.surfaceVariant
+ normalBorderColor: Theme.primarySelected
+ focusedBorderColor: Theme.primary
+ keyNavigationTab: root.keyNavigationTab
+ keyNavigationBacktab: root.keyNavigationBacktab
+ onTextEdited: {
+ if (root._internalChange)
+ return;
+ if (getActiveFocus()) {
+ if (text.length > 2) {
+ root.isLoading = true;
+ locationSearchTimer.restart();
+ } else {
+ root.resetSearchState();
+ }
+ }
+ }
+ onFocusStateChanged: hasFocus => {
+ if (hasFocus) {
+ dropdownHideTimer.stop();
+ } else {
+ dropdownHideTimer.start();
+ }
+ }
+ }
+
+ DankIcon {
+ name: root.isLoading ? "hourglass_empty" : (searchResultsModel.count > 0 ? "check_circle" : "error")
+ size: Theme.iconSize - 4
+ color: root.isLoading ? Theme.surfaceVariantText : (searchResultsModel.count > 0 ? Theme.primary : Theme.error)
+ anchors.right: parent.right
+ anchors.rightMargin: Theme.spacingM
+ anchors.verticalCenter: parent.verticalCenter
+ opacity: (locationInput.getActiveFocus() && locationInput.text.length > 2) ? 1 : 0
+
+ Behavior on opacity {
+ NumberAnimation {
+ duration: Theme.shortDuration
+ easing.type: Theme.standardEasing
+ }
+ }
+ }
+ }
+
+ StyledRect {
+ id: searchDropdown
+
+ property bool hovered: false
+
+ width: parent.width
+ height: Math.min(Math.max(searchResultsModel.count * 38 + Theme.spacingS * 2, 50), 200)
+ y: searchInputField.height
+ radius: Theme.cornerRadius
+ color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
+ border.color: Theme.primarySelected
+ border.width: 1
+ visible: locationInput.getActiveFocus() && locationInput.text.length > 2 && (searchResultsModel.count > 0 || root.isLoading)
+
+ MouseArea {
+ anchors.fill: parent
+ hoverEnabled: true
+ onEntered: {
+ parent.hovered = true;
+ dropdownHideTimer.stop();
+ }
+ onExited: {
+ parent.hovered = false;
+ if (!locationInput.getActiveFocus())
+ dropdownHideTimer.start();
+ }
+ acceptedButtons: Qt.NoButton
+ }
+
+ Item {
+ anchors.fill: parent
+ anchors.margins: Theme.spacingS
+
+ DankListView {
+ id: searchResultsList
+
+ anchors.fill: parent
+ clip: true
+ model: searchResultsModel
+ spacing: 2
+
+ delegate: StyledRect {
+ width: searchResultsList.width
+ height: 36
+ radius: Theme.cornerRadius
+ color: resultMouseArea.containsMouse ? Theme.surfaceLight : "transparent"
+
+ Row {
+ anchors.fill: parent
+ anchors.margins: Theme.spacingM
+ spacing: Theme.spacingS
+
+ DankIcon {
+ name: "place"
+ size: Theme.iconSize - 6
+ color: Theme.surfaceVariantText
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ StyledText {
+ text: model.name || "Unknown"
+ font.pixelSize: Theme.fontSizeMedium
+ color: Theme.surfaceText
+ anchors.verticalCenter: parent.verticalCenter
+ elide: Text.ElideRight
+ width: parent.width - 30
+ }
+ }
+
+ MouseArea {
+ id: resultMouseArea
+
+ anchors.fill: parent
+ hoverEnabled: true
+ cursorShape: Qt.PointingHandCursor
+ onClicked: {
+ root._internalChange = true;
+ const selectedName = model.name;
+ const selectedQuery = model.query;
+ locationInput.text = selectedName;
+ root.locationSelected(selectedName, selectedQuery);
+ root.resetSearchState();
+ locationInput.setFocus(false);
+ root._internalChange = false;
+ }
+ }
+ }
+ }
+
+ StyledText {
+ anchors.centerIn: parent
+ text: root.isLoading ? "Searching..." : "No locations found"
+ font.pixelSize: Theme.fontSizeMedium
+ color: Theme.surfaceVariantText
+ visible: searchResultsList.count === 0 && locationInput.text.length > 2
+ }
+ }
+ }
+}