Add .config/DankMaterialShell/firefox.css
Add .config/DankMaterialShell/plugin_settings.json Add .config/DankMaterialShell/plugins/calculator/CalculatorLauncher.qml Add .config/DankMaterialShell/plugins/calculator/CalculatorSettings.qml Add .config/DankMaterialShell/plugins/calculator/README.md Add .config/DankMaterialShell/plugins/calculator/calculator.js Add .config/DankMaterialShell/plugins/calculator/.git/HEAD Add .config/DankMaterialShell/plugins/calculator/.git/config Add .config/DankMaterialShell/plugins/calculator/.git/index Add .config/DankMaterialShell/plugins/calculator/.git/objects/info/.keep Add .config/DankMaterialShell/plugins/calculator/.git/objects/pack/pack-67f644835e660794f65c9273e46788b0c3da57cf.idx Add .config/DankMaterialShell/plugins/calculator/.git/objects/pack/pack-67f644835e660794f65c9273e46788b0c3da57cf.rev Add .config/DankMaterialShell/plugins/calculator/.git/objects/pack/pack-67f644835e660794f65c9273e46788b0c3da57cf.pack Add .config/DankMaterialShell/plugins/calculator/.git/refs/heads/main Add .config/DankMaterialShell/plugins/calculator/.git/refs/remotes/origin/main Add .config/DankMaterialShell/plugins/calculator/.git/refs/remotes/origin/qalc Add .config/DankMaterialShell/plugins/calculator/.git/refs/tags/.keep Add .config/DankMaterialShell/plugins/calculator/plugin.json Add .config/DankMaterialShell/plugins/calculator/screenshot.png Add .config/DankMaterialShell/plugins/calculator/test_precision.js Add .config/DankMaterialShell/plugins/calculator/test_single.js Add .config/DankMaterialShell/plugins/commandRunner/CommandRunner.qml Add .config/DankMaterialShell/plugins/commandRunner/CommandRunnerSettings.qml Add .config/DankMaterialShell/plugins/commandRunner/LICENSE Add .config/DankMaterialShell/plugins/commandRunner/README.md Add .config/DankMaterialShell/plugins/commandRunner/.git/HEAD Add .config/DankMaterialShell/plugins/commandRunner/.git/config Add .config/DankMaterialShell/plugins/commandRunner/.git/index Add .config/DankMaterialShell/plugins/commandRunner/.git/objects/info/.keep Add .config/DankMaterialShell/plugins/commandRunner/.git/objects/pack/pack-5a720f795fd2994ef506cd867d86ca7df8a25a31.idx Add .config/DankMaterialShell/plugins/commandRunner/.git/objects/pack/pack-5a720f795fd2994ef506cd867d86ca7df8a25a31.rev Add .config/DankMaterialShell/plugins/commandRunner/.git/objects/pack/pack-5a720f795fd2994ef506cd867d86ca7df8a25a31.pack Add .config/DankMaterialShell/plugins/commandRunner/.git/refs/heads/main Add .config/DankMaterialShell/plugins/commandRunner/.git/refs/remotes/origin/main Add .config/DankMaterialShell/plugins/commandRunner/.git/refs/tags/.keep Add .config/DankMaterialShell/plugins/commandRunner/plugin.json Add .config/DankMaterialShell/plugins/commandRunner/screenshot.png Add .config/DankMaterialShell/plugins/dankActions.meta Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankActions/DankActionsSettings.qml Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankActions/DankActionsWidget.qml Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankActions/plugin.json Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankBatteryAlerts/DankBatteryAlerts.qml Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankBatteryAlerts/DankBatteryAlertsSettings.qml Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankBatteryAlerts/plugin.json Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankHooks/DankHooks.qml Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankHooks/DankHooksSettings.qml Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankHooks/README.md Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankHooks/plugin.json Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankPomodoroTimer/DankPomodoroSettings.qml Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankPomodoroTimer/DankPomodoroWidget.qml Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/DankPomodoroTimer/plugin.json Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/LICENSE Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/README.md Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/HEAD Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/config Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/index Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/objects/info/.keep Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/objects/pack/pack-3221a15c022ef4a7bb6bf2c47e40068b66b3588b.idx Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/objects/pack/pack-3221a15c022ef4a7bb6bf2c47e40068b66b3588b.rev Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/objects/pack/pack-3221a15c022ef4a7bb6bf2c47e40068b66b3588b.pack Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/refs/heads/master Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/refs/remotes/origin/master Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.git/refs/tags/.keep Add .config/DankMaterialShell/plugins/.repos/0026f1eba8dedaec/.gitignore Add .config/DankMaterialShell/plugins/emojiLauncher/EmojiLauncher.qml Add .config/DankMaterialShell/plugins/emojiLauncher/EmojiLauncherSettings.qml Add .config/DankMaterialShell/plugins/emojiLauncher/LICENSE Add .config/DankMaterialShell/plugins/emojiLauncher/README.md Add .config/DankMaterialShell/plugins/emojiLauncher/catalog.js Add .config/DankMaterialShell/plugins/emojiLauncher/data/emojis.txt Add .config/DankMaterialShell/plugins/emojiLauncher/data/math.txt Add .config/DankMaterialShell/plugins/emojiLauncher/data/nerdfont.txt Add .config/DankMaterialShell/plugins/emojiLauncher/.git/HEAD Add .config/DankMaterialShell/plugins/emojiLauncher/.git/config Add .config/DankMaterialShell/plugins/emojiLauncher/.git/index Add .config/DankMaterialShell/plugins/emojiLauncher/.git/objects/info/.keep Add .config/DankMaterialShell/plugins/emojiLauncher/.git/objects/pack/pack-e04a5b1ea381dc3a792b8bf08cf70e735b195c0d.idx Add .config/DankMaterialShell/plugins/emojiLauncher/.git/objects/pack/pack-e04a5b1ea381dc3a792b8bf08cf70e735b195c0d.rev Add .config/DankMaterialShell/plugins/emojiLauncher/.git/objects/pack/pack-e04a5b1ea381dc3a792b8bf08cf70e735b195c0d.pack Add .config/DankMaterialShell/plugins/emojiLauncher/.git/refs/heads/main Add .config/DankMaterialShell/plugins/emojiLauncher/.git/refs/remotes/origin/main Add .config/DankMaterialShell/plugins/emojiLauncher/.git/refs/tags/.keep Add .config/DankMaterialShell/plugins/emojiLauncher/plugin.json Add .config/DankMaterialShell/plugins/emojiLauncher/screenshot.png Add .config/DankMaterialShell/plugins/emojiLauncher/scripts/generate_catalog.py Add .config/DankMaterialShell/plugins/dankActions Add .config/DankMaterialShell/plugins/webSearch/LICENSE Add .config/DankMaterialShell/plugins/webSearch/README.md Add .config/DankMaterialShell/plugins/webSearch/WebSearch.qml Add .config/DankMaterialShell/plugins/webSearch/WebSearchSettings.qml Add .config/DankMaterialShell/plugins/webSearch/.git/HEAD Add .config/DankMaterialShell/plugins/webSearch/.git/config Add .config/DankMaterialShell/plugins/webSearch/.git/index Add .config/DankMaterialShell/plugins/webSearch/.git/objects/info/.keep Add .config/DankMaterialShell/plugins/webSearch/.git/objects/pack/pack-6a60c736f418e5b4b1f0505f66c1e2a371d46fed.idx Add .config/DankMaterialShell/plugins/webSearch/.git/objects/pack/pack-6a60c736f418e5b4b1f0505f66c1e2a371d46fed.rev Add .config/DankMaterialShell/plugins/webSearch/.git/objects/pack/pack-6a60c736f418e5b4b1f0505f66c1e2a371d46fed.pack Add .config/DankMaterialShell/plugins/webSearch/.git/refs/heads/main Add .config/DankMaterialShell/plugins/webSearch/.git/refs/remotes/origin/main Add .config/DankMaterialShell/plugins/webSearch/.git/refs/tags/.keep Add .config/DankMaterialShell/plugins/webSearch/plugin.json Add .config/DankMaterialShell/plugins/webSearch/screenshot.png Add .config/DankMaterialShell/settings.json
This commit is contained in:
parent
b22161e0ca
commit
809b12203c
103 changed files with 25020 additions and 0 deletions
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2025 DankMaterialShell Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
237
private_dot_config/DankMaterialShell/plugins/webSearch/README.md
Normal file
237
private_dot_config/DankMaterialShell/plugins/webSearch/README.md
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
# Web Search
|
||||
|
||||
A DankMaterialShell launcher plugin for searching the web with 23+ built-in search engines and support for custom search engines.
|
||||
|
||||

|
||||
|
||||
## Features
|
||||
|
||||
- **23+ Built-in Search Engines** - Google, DuckDuckGo, GitHub, Stack Overflow, and more
|
||||
- **Custom Search Engines** - Add your own search engines with URL templates
|
||||
- **Keyword-Based Selection** - Type keywords to use specific engines (e.g., `github rust`)
|
||||
- **Configurable Default Engine** - Set your preferred search engine
|
||||
- **One-Click Search** - Select and press Enter to open browser
|
||||
- **Toast Notifications** - Visual feedback for every search
|
||||
- **Configurable Trigger** - Default `?` or set your own trigger
|
||||
|
||||
## Installation
|
||||
|
||||
### From Plugin Registry (Recommended)
|
||||
|
||||
```bash
|
||||
# Coming soon - will be available via DMS plugin manager
|
||||
```
|
||||
|
||||
### Manual Installation
|
||||
|
||||
```bash
|
||||
# Copy plugin to DMS plugins directory
|
||||
cp -r WebSearch ~/.config/DankMaterialShell/plugins/
|
||||
|
||||
# Enable in DMS
|
||||
# 1. Open Settings (Ctrl+,)
|
||||
# 2. Go to Plugins tab
|
||||
# 3. Click "Scan for Plugins"
|
||||
# 4. Toggle "Web Search" to enable
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Search
|
||||
|
||||
1. Open launcher (Ctrl+Space)
|
||||
2. Type `?` followed by search query
|
||||
3. Examples:
|
||||
- `? rust tutorials` - Search with default engine
|
||||
- `? linux kernel` - General search
|
||||
4. Select engine and press Enter to open browser
|
||||
|
||||
### Engine-Specific Search
|
||||
|
||||
Use keywords to search specific engines directly:
|
||||
|
||||
- `? github awesome-linux` - Search GitHub
|
||||
- `? youtube music video` - Search YouTube
|
||||
- `? wiki quantum physics` - Search Wikipedia
|
||||
- `? stackoverflow async rust` - Search Stack Overflow
|
||||
|
||||
## Built-in Search Engines
|
||||
|
||||
### General Search
|
||||
|
||||
- **Google** - Keywords: `google`, `search`
|
||||
- **DuckDuckGo** - Keywords: `ddg`, `duckduckgo`, `privacy`
|
||||
- **Brave Search** - Keywords: `brave`, `privacy`
|
||||
- **Bing** - Keywords: `bing`, `microsoft`
|
||||
|
||||
### Development
|
||||
|
||||
- **GitHub** - Keywords: `github`, `code`, `git`
|
||||
- **Stack Overflow** - Keywords: `stackoverflow`, `stack`, `coding`
|
||||
- **npm** - Keywords: `npm`, `node`, `javascript`
|
||||
- **PyPI** - Keywords: `pypi`, `python`, `pip`
|
||||
- **crates.io** - Keywords: `crates`, `rust`, `cargo`
|
||||
- **MDN Web Docs** - Keywords: `mdn`, `mozilla`, `web`, `docs`
|
||||
|
||||
### Linux & Packages
|
||||
|
||||
- **Arch Linux Wiki** - Keywords: `arch`, `linux`, `packages`
|
||||
- **AUR** - Keywords: `aur`, `arch`, `packages`
|
||||
|
||||
### Social & Media
|
||||
|
||||
- **YouTube** - Keywords: `youtube`, `video`, `yt`
|
||||
- **Reddit** - Keywords: `reddit`
|
||||
- **Twitter/X** - Keywords: `twitter`, `x`, `social`
|
||||
- **LinkedIn** - Keywords: `linkedin`, `job`, `professional`
|
||||
|
||||
### Reference
|
||||
|
||||
- **Wikipedia** - Keywords: `wikipedia`, `wiki`
|
||||
- **Google Translate** - Keywords: `translate`, `translation`
|
||||
- **IMDb** - Keywords: `imdb`, `movies`, `tv`
|
||||
|
||||
### Shopping
|
||||
|
||||
- **Amazon** - Keywords: `amazon`, `shop`, `shopping`
|
||||
- **eBay** - Keywords: `ebay`, `shop`, `auction`
|
||||
|
||||
### Utilities
|
||||
|
||||
- **Google Maps** - Keywords: `maps`, `location`, `directions`
|
||||
- **Google Images** - Keywords: `images`, `pictures`, `photos`
|
||||
|
||||
## Custom Search Engines
|
||||
|
||||
Add your own search engines via Settings:
|
||||
|
||||
1. Open Settings → Plugins → Web Search
|
||||
2. Scroll to "Custom Search Engines"
|
||||
3. Fill in the form:
|
||||
- **ID**: Unique identifier (e.g., `myengine`)
|
||||
- **Name**: Display name (e.g., `My Search Engine`)
|
||||
- **Icon**: Material icon name (e.g., `search`), prefix with `material:` to pull a Material Symbol (e.g., `material:travel_explore`), or prefix with `unicode:` to use emoji/Nerd Font glyphs (e.g., `unicode:`)
|
||||
- **URL**: Search URL with `%s` placeholder
|
||||
- **Keywords**: Comma-separated keywords for quick access
|
||||
|
||||
### Example Custom Engines
|
||||
|
||||
**Rust Documentation:**
|
||||
|
||||
```
|
||||
ID: rustdoc
|
||||
Name: Rust Docs
|
||||
Icon: unicode:🦀
|
||||
URL: https://doc.rust-lang.org/std/?search=%s
|
||||
Keywords: rust,docs,documentation
|
||||
```
|
||||
|
||||
**Arch Wiki:**
|
||||
|
||||
```
|
||||
ID: archwiki
|
||||
Name: Arch Wiki
|
||||
Icon: material:menu_book
|
||||
URL: https://wiki.archlinux.org/index.php?search=%s
|
||||
Keywords: arch,wiki,documentation
|
||||
```
|
||||
|
||||
**GitLab:**
|
||||
|
||||
```
|
||||
ID: gitlab
|
||||
Name: GitLab
|
||||
Icon: material:code
|
||||
URL: https://gitlab.com/search?search=%s
|
||||
Keywords: gitlab,code
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Access settings via DMS Settings → Plugins → Web Search:
|
||||
|
||||
- **Trigger**: Set custom trigger (`?`, `/`, `/search`, etc.) or disable for always-on mode
|
||||
- **Default Search Engine**: Choose your preferred engine (Google, DuckDuckGo, Brave, Bing)
|
||||
- **Custom Search Engines**: Add/manage your own search engines
|
||||
|
||||
## Search Examples
|
||||
|
||||
### General Queries
|
||||
|
||||
```
|
||||
? rust programming # Search with default engine
|
||||
? how to install arch # General search
|
||||
```
|
||||
|
||||
### Development
|
||||
|
||||
```
|
||||
? github awesome-linux # Search GitHub
|
||||
? stackoverflow async rust # Search Stack Overflow
|
||||
? npm react hooks # Search npm packages
|
||||
? pypi requests # Search Python packages
|
||||
```
|
||||
|
||||
### Linux
|
||||
|
||||
```
|
||||
? arch firefox # Search Arch packages
|
||||
? aur brave-bin # Search AUR
|
||||
? wiki systemd # Search Wikipedia
|
||||
```
|
||||
|
||||
### Media
|
||||
|
||||
```
|
||||
? youtube rust tutorial # Search YouTube
|
||||
? reddit linux gaming # Search Reddit
|
||||
? imdb inception # Search IMDb
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
- DankMaterialShell >= 0.1.0
|
||||
- Web browser (default system browser via `xdg-open`)
|
||||
- Wayland compositor
|
||||
|
||||
## Compatibility
|
||||
|
||||
- **Compositors**: Niri and Hyprland
|
||||
- **Distros**: Universal - works on any Linux distribution
|
||||
- **Browsers**: Works with any default browser
|
||||
|
||||
## Technical Details
|
||||
|
||||
- **Type**: Launcher plugin
|
||||
- **Trigger**: `?` (configurable)
|
||||
- **Language**: QML (Qt Modeling Language)
|
||||
- **Browser Launch**: Uses `xdg-open` for system default browser
|
||||
|
||||
## Tips & Tricks
|
||||
|
||||
1. **Keyword Shortcuts**: Type engine keywords first for direct search
|
||||
- `github rust` instead of `? github rust`
|
||||
|
||||
2. **Combine Keywords**: Use multiple keywords to narrow results
|
||||
- `stackoverflow rust async await`
|
||||
|
||||
3. **Custom Engines**: Add frequently-used sites for quick access
|
||||
- Add your company's internal documentation
|
||||
- Add specialized search engines for your workflow
|
||||
|
||||
## Contributing
|
||||
|
||||
Want to add more built-in search engines? Open an issue or submit a pull request!
|
||||
|
||||
## License
|
||||
|
||||
MIT License - See LICENSE file for details
|
||||
|
||||
## Author
|
||||
|
||||
Created for the DankMaterialShell community
|
||||
|
||||
## Links
|
||||
|
||||
- [DankMaterialShell](https://github.com/AvengeMedia/DankMaterialShell)
|
||||
- [Plugin Registry](https://github.com/AvengeMedia/dms-plugin-registry)
|
||||
|
|
@ -0,0 +1,352 @@
|
|||
import QtQuick
|
||||
import Quickshell
|
||||
import qs.Services
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property var pluginService: null
|
||||
property string trigger: "?"
|
||||
property var searchEngines: []
|
||||
property string defaultEngine: "google"
|
||||
|
||||
signal itemsChanged()
|
||||
|
||||
property var builtInEngines: [
|
||||
{
|
||||
id: "google",
|
||||
name: "Google",
|
||||
icon: "material:travel_explore",
|
||||
url: "https://www.google.com/search?q=%s",
|
||||
keywords: ["google", "search"]
|
||||
},
|
||||
{
|
||||
id: "duckduckgo",
|
||||
name: "DuckDuckGo",
|
||||
icon: "material:shield",
|
||||
url: "https://duckduckgo.com/?q=%s",
|
||||
keywords: ["ddg", "duckduckgo", "privacy"]
|
||||
},
|
||||
{
|
||||
id: "brave",
|
||||
name: "Brave Search",
|
||||
icon: "material:security",
|
||||
url: "https://search.brave.com/search?q=%s",
|
||||
keywords: ["brave", "privacy"]
|
||||
},
|
||||
{
|
||||
id: "bing",
|
||||
name: "Bing",
|
||||
icon: "material:language",
|
||||
url: "https://www.bing.com/search?q=%s",
|
||||
keywords: ["bing", "microsoft"]
|
||||
},
|
||||
{
|
||||
id: "youtube",
|
||||
name: "YouTube",
|
||||
icon: "material:youtube_activity",
|
||||
url: "https://www.youtube.com/results?search_query=%s",
|
||||
keywords: ["youtube", "video", "yt"]
|
||||
},
|
||||
{
|
||||
id: "github",
|
||||
name: "GitHub",
|
||||
icon: "unicode:",
|
||||
url: "https://github.com/search?q=%s",
|
||||
keywords: ["github", "code", "git"]
|
||||
},
|
||||
{
|
||||
id: "stackoverflow",
|
||||
name: "Stack Overflow",
|
||||
icon: "unicode:",
|
||||
url: "https://stackoverflow.com/search?q=%s",
|
||||
keywords: ["stackoverflow", "stack", "coding"]
|
||||
},
|
||||
{
|
||||
id: "reddit",
|
||||
name: "Reddit",
|
||||
icon: "unicode:",
|
||||
url: "https://www.reddit.com/search?q=%s",
|
||||
keywords: ["reddit"]
|
||||
},
|
||||
{
|
||||
id: "wikipedia",
|
||||
name: "Wikipedia",
|
||||
icon: "material:menu_book",
|
||||
url: "https://en.wikipedia.org/wiki/Special:Search?search=%s",
|
||||
keywords: ["wikipedia", "wiki"]
|
||||
},
|
||||
{
|
||||
id: "amazon",
|
||||
name: "Amazon",
|
||||
icon: "material:shopping_cart",
|
||||
url: "https://www.amazon.com/s?k=%s",
|
||||
keywords: ["amazon", "shop", "shopping"]
|
||||
},
|
||||
{
|
||||
id: "ebay",
|
||||
name: "eBay",
|
||||
icon: "material:local_mall",
|
||||
url: "https://www.ebay.com/sch/i.html?_nkw=%s",
|
||||
keywords: ["ebay", "shop", "auction"]
|
||||
},
|
||||
{
|
||||
id: "maps",
|
||||
name: "Google Maps",
|
||||
icon: "material:map",
|
||||
url: "https://www.google.com/maps/search/%s",
|
||||
keywords: ["maps", "location", "directions"]
|
||||
},
|
||||
{
|
||||
id: "images",
|
||||
name: "Google Images",
|
||||
icon: "material:photo_library",
|
||||
url: "https://www.google.com/search?tbm=isch&q=%s",
|
||||
keywords: ["images", "pictures", "photos"]
|
||||
},
|
||||
{
|
||||
id: "twitter",
|
||||
name: "Twitter/X",
|
||||
icon: "unicode:",
|
||||
url: "https://twitter.com/search?q=%s",
|
||||
keywords: ["twitter", "x", "social"]
|
||||
},
|
||||
{
|
||||
id: "linkedin",
|
||||
name: "LinkedIn",
|
||||
icon: "unicode:",
|
||||
url: "https://www.linkedin.com/search/results/all/?keywords=%s",
|
||||
keywords: ["linkedin", "job", "professional"]
|
||||
},
|
||||
{
|
||||
id: "imdb",
|
||||
name: "IMDb",
|
||||
icon: "unicode:",
|
||||
url: "https://www.imdb.com/find?q=%s",
|
||||
keywords: ["imdb", "movies", "tv"]
|
||||
},
|
||||
{
|
||||
id: "translate",
|
||||
name: "Google Translate",
|
||||
icon: "material:g_translate",
|
||||
url: "https://translate.google.com/?text=%s",
|
||||
keywords: ["translate", "translation"]
|
||||
},
|
||||
{
|
||||
id: "archlinux",
|
||||
name: "Arch Linux Wiki",
|
||||
icon: "material:terminal",
|
||||
url: "https://wiki.archlinux.org/index.php?search=%s",
|
||||
keywords: ["arch", "linux", "packages"]
|
||||
},
|
||||
{
|
||||
id: "aur",
|
||||
name: "AUR",
|
||||
icon: "unicode:",
|
||||
url: "https://aur.archlinux.org/packages?K=%s",
|
||||
keywords: ["aur", "arch", "packages"]
|
||||
},
|
||||
{
|
||||
id: "npmjs",
|
||||
name: "npm",
|
||||
icon: "unicode:",
|
||||
url: "https://www.npmjs.com/search?q=%s",
|
||||
keywords: ["npm", "node", "javascript"]
|
||||
},
|
||||
{
|
||||
id: "pypi",
|
||||
name: "PyPI",
|
||||
icon: "unicode:",
|
||||
url: "https://pypi.org/search/?q=%s",
|
||||
keywords: ["pypi", "python", "pip"]
|
||||
},
|
||||
{
|
||||
id: "crates",
|
||||
name: "crates.io",
|
||||
icon: "material:inventory_2",
|
||||
url: "https://crates.io/search?q=%s",
|
||||
keywords: ["crates", "rust", "cargo"]
|
||||
},
|
||||
{
|
||||
id: "mdn",
|
||||
name: "MDN Web Docs",
|
||||
icon: "material:code_blocks",
|
||||
url: "https://developer.mozilla.org/en-US/search?q=%s",
|
||||
keywords: ["mdn", "mozilla", "web", "docs"]
|
||||
}
|
||||
]
|
||||
|
||||
Component.onCompleted: {
|
||||
loadSettings()
|
||||
}
|
||||
|
||||
onPluginServiceChanged: {
|
||||
if (pluginService) {
|
||||
loadSettings()
|
||||
}
|
||||
}
|
||||
|
||||
function loadSettings() {
|
||||
if (pluginService) {
|
||||
trigger = pluginService.loadPluginData("webSearch", "trigger", "?")
|
||||
defaultEngine = pluginService.loadPluginData("webSearch", "defaultEngine", "google")
|
||||
searchEngines = pluginService.loadPluginData("webSearch", "searchEngines", [])
|
||||
}
|
||||
}
|
||||
|
||||
function getItems(query) {
|
||||
const items = []
|
||||
const allEngines = builtInEngines.concat(searchEngines)
|
||||
|
||||
if (!query || query.trim().length === 0) {
|
||||
items.push({
|
||||
name: "Type a search query",
|
||||
icon: "unicode:🔍",
|
||||
comment: "Search the web with your default engine (" + getEngineName(defaultEngine) + ")",
|
||||
action: "noop",
|
||||
categories: ["Web Search"]
|
||||
})
|
||||
|
||||
for (let i = 0; i < allEngines.length; i++) {
|
||||
const engine = allEngines[i]
|
||||
items.push({
|
||||
name: engine.name,
|
||||
icon: engine.icon || "unicode:🔍",
|
||||
comment: engine.keywords ? engine.keywords.join(", ") : "Search engine",
|
||||
action: "noop",
|
||||
categories: ["Web Search"]
|
||||
})
|
||||
}
|
||||
|
||||
return items
|
||||
}
|
||||
|
||||
let matchedEngineId = null
|
||||
let searchQuery = query.trim()
|
||||
let fallbackQuery = query.trim()
|
||||
|
||||
for (let i = 0; i < allEngines.length; i++) {
|
||||
const engine = allEngines[i]
|
||||
if (engine.keywords) {
|
||||
for (let k = 0; k < engine.keywords.length; k++) {
|
||||
const keyword = engine.keywords[k]
|
||||
if (searchQuery.toLowerCase().startsWith(keyword + " ")) {
|
||||
matchedEngineId = engine.id
|
||||
searchQuery = searchQuery.substring(keyword.length + 1).trim()
|
||||
break
|
||||
}
|
||||
}
|
||||
if (matchedEngineId) break
|
||||
}
|
||||
}
|
||||
|
||||
const primaryEngineId = matchedEngineId || defaultEngine
|
||||
const primaryEngineObj = allEngines.find(e => e.id === primaryEngineId)
|
||||
|
||||
if (primaryEngineObj) {
|
||||
items.push({
|
||||
name: "Search with " + primaryEngineObj.name + ": " + searchQuery,
|
||||
icon: primaryEngineObj.icon || "unicode:🔍",
|
||||
comment: "Open in browser",
|
||||
action: "search:" + primaryEngineId + ":" + searchQuery,
|
||||
categories: ["Web Search"]
|
||||
})
|
||||
}
|
||||
|
||||
for (let i = 0; i < allEngines.length; i++) {
|
||||
const engine = allEngines[i]
|
||||
if (engine.id !== primaryEngineId) {
|
||||
items.push({
|
||||
name: "Search with " + engine.name + ": " + (matchedEngineId ? fallbackQuery : searchQuery),
|
||||
icon: engine.icon || "material:search",
|
||||
comment: "Open in browser",
|
||||
action: "search:" + engine.id + ":" + (matchedEngineId ? fallbackQuery : searchQuery),
|
||||
categories: ["Web Search"]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return items
|
||||
}
|
||||
|
||||
function executeItem(item) {
|
||||
if (!item || !item.action) {
|
||||
console.warn("WebSearch: Invalid item or action")
|
||||
return
|
||||
}
|
||||
|
||||
console.log("WebSearch: Executing item:", item.name, "with action:", item.action)
|
||||
|
||||
const actionParts = item.action.split(":")
|
||||
const actionType = actionParts[0]
|
||||
|
||||
switch (actionType) {
|
||||
case "noop":
|
||||
return
|
||||
case "search":
|
||||
performSearch(actionParts)
|
||||
break
|
||||
default:
|
||||
console.warn("WebSearch: Unknown action type:", actionType)
|
||||
showToast("Unknown action: " + actionType)
|
||||
}
|
||||
}
|
||||
|
||||
function performSearch(actionParts) {
|
||||
const engineId = actionParts[1]
|
||||
const query = actionParts.slice(2).join(":")
|
||||
|
||||
const allEngines = builtInEngines.concat(searchEngines)
|
||||
const engine = allEngines.find(e => e.id === engineId)
|
||||
|
||||
if (engine) {
|
||||
const encodedQuery = encodeQuery(query)
|
||||
const url = engine.url.replace("%s", encodedQuery)
|
||||
|
||||
Quickshell.execDetached(["xdg-open", url])
|
||||
showToast("Searching " + engine.name + " for: " + query)
|
||||
} else {
|
||||
console.warn("WebSearch: Engine not found:", engineId)
|
||||
showToast("Search engine not found: " + engineId)
|
||||
}
|
||||
}
|
||||
|
||||
function showToast(message) {
|
||||
if (typeof ToastService !== "undefined") {
|
||||
ToastService.showInfo("Web Search", message)
|
||||
} else {
|
||||
console.log("WebSearch Toast:", message)
|
||||
}
|
||||
}
|
||||
|
||||
function getEngineName(engineId) {
|
||||
const allEngines = builtInEngines.concat(searchEngines)
|
||||
const engine = allEngines.find(e => e.id === engineId)
|
||||
return engine ? engine.name : "Unknown"
|
||||
}
|
||||
|
||||
function encodeQuery(str) {
|
||||
return str.replace(/ /g, "+")
|
||||
}
|
||||
|
||||
onTriggerChanged: {
|
||||
if (pluginService) {
|
||||
pluginService.savePluginData("webSearch", "trigger", trigger)
|
||||
}
|
||||
itemsChanged()
|
||||
}
|
||||
|
||||
onDefaultEngineChanged: {
|
||||
if (pluginService) {
|
||||
pluginService.savePluginData("webSearch", "defaultEngine", defaultEngine)
|
||||
}
|
||||
itemsChanged()
|
||||
}
|
||||
|
||||
onSearchEnginesChanged: {
|
||||
if (pluginService) {
|
||||
pluginService.savePluginData("webSearch", "searchEngines", searchEngines)
|
||||
}
|
||||
itemsChanged()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,727 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import qs.Common
|
||||
import qs.Widgets
|
||||
import qs.Modules.Plugins
|
||||
|
||||
PluginSettings {
|
||||
id: root
|
||||
pluginId: "webSearch"
|
||||
|
||||
property int editingIndex: -1
|
||||
|
||||
StyledText {
|
||||
width: parent.width
|
||||
text: "Web Search Settings"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
font.weight: Font.Bold
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
StyledText {
|
||||
width: parent.width
|
||||
text: "Search the web with built-in and custom search engines directly from the launcher."
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceVariantText
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
height: 1
|
||||
color: Theme.outlineVariant
|
||||
}
|
||||
|
||||
Column {
|
||||
spacing: 12
|
||||
width: parent.width
|
||||
|
||||
StyledText {
|
||||
text: "Trigger Configuration"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: noTriggerToggle.checked ? "Items will always show in the launcher (no trigger needed)." : "Set the trigger text to activate web search. Type the trigger in the launcher followed by your search query."
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
wrapMode: Text.WordWrap
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
Row {
|
||||
spacing: 12
|
||||
|
||||
CheckBox {
|
||||
id: noTriggerToggle
|
||||
text: "No trigger (always show)"
|
||||
checked: root.loadValue("noTrigger", false)
|
||||
|
||||
contentItem: StyledText {
|
||||
text: noTriggerToggle.text
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceText
|
||||
leftPadding: noTriggerToggle.indicator.width + 8
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
indicator: StyledRect {
|
||||
implicitWidth: 20
|
||||
implicitHeight: 20
|
||||
radius: Theme.cornerRadiusSmall
|
||||
border.color: noTriggerToggle.checked ? Theme.primary : Theme.outline
|
||||
border.width: 2
|
||||
color: noTriggerToggle.checked ? Theme.primary : "transparent"
|
||||
|
||||
StyledRect {
|
||||
width: 12
|
||||
height: 12
|
||||
anchors.centerIn: parent
|
||||
radius: 2
|
||||
color: Theme.onPrimary
|
||||
visible: noTriggerToggle.checked
|
||||
}
|
||||
}
|
||||
|
||||
onCheckedChanged: {
|
||||
root.saveValue("noTrigger", checked)
|
||||
if (checked) {
|
||||
root.saveValue("trigger", "")
|
||||
} else {
|
||||
root.saveValue("trigger", triggerField.text || "?")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
spacing: 12
|
||||
width: parent.width
|
||||
visible: !noTriggerToggle.checked
|
||||
|
||||
StyledText {
|
||||
text: "Trigger:"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
DankTextField {
|
||||
id: triggerField
|
||||
width: 100
|
||||
height: 40
|
||||
text: root.loadValue("trigger", "?")
|
||||
placeholderText: "?"
|
||||
backgroundColor: Theme.surfaceContainer
|
||||
textColor: Theme.surfaceText
|
||||
|
||||
onTextEdited: {
|
||||
const newTrigger = text.trim()
|
||||
root.saveValue("trigger", newTrigger || "?")
|
||||
root.saveValue("noTrigger", newTrigger === "")
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "Examples: ?, /, /search, etc."
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
height: 1
|
||||
color: Theme.outlineVariant
|
||||
}
|
||||
|
||||
SelectionSetting {
|
||||
settingKey: "defaultEngine"
|
||||
label: "Default Search Engine"
|
||||
description: "The search engine used when no keyword is specified"
|
||||
options: [
|
||||
{label: "Google", value: "google"},
|
||||
{label: "DuckDuckGo", value: "duckduckgo"},
|
||||
{label: "Brave Search", value: "brave"},
|
||||
{label: "Bing", value: "bing"}
|
||||
]
|
||||
defaultValue: "google"
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
height: 1
|
||||
color: Theme.outlineVariant
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
height: addEngineColumn.implicitHeight + Theme.spacingL * 2
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.surfaceContainerHigh
|
||||
|
||||
Column {
|
||||
id: addEngineColumn
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
StyledText {
|
||||
text: root.editingIndex === -1 ? "Create Custom Search Engine" : "Edit Custom Search Engine"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Column {
|
||||
width: (parent.width - Theme.spacingM) / 2
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
StyledText {
|
||||
text: "Engine ID *"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
|
||||
DankTextField {
|
||||
id: idField
|
||||
width: parent.width
|
||||
placeholderText: "e.g., myengine"
|
||||
keyNavigationTab: nameField
|
||||
onFocusStateChanged: hasFocus => {
|
||||
if (hasFocus) root.ensureItemVisible(idField)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
width: (parent.width - Theme.spacingM) / 2
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
StyledText {
|
||||
text: "Display Name *"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
|
||||
DankTextField {
|
||||
id: nameField
|
||||
width: parent.width
|
||||
placeholderText: "e.g., My Engine"
|
||||
keyNavigationBacktab: idField
|
||||
keyNavigationTab: iconField
|
||||
onFocusStateChanged: hasFocus => {
|
||||
if (hasFocus) root.ensureItemVisible(nameField)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Column {
|
||||
width: (parent.width - Theme.spacingM) / 2
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
StyledText {
|
||||
text: "Icon"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
|
||||
DankTextField {
|
||||
id: iconField
|
||||
width: parent.width
|
||||
placeholderText: "e.g., unicode:🔍"
|
||||
keyNavigationBacktab: nameField
|
||||
keyNavigationTab: urlField
|
||||
onFocusStateChanged: hasFocus => {
|
||||
if (hasFocus) root.ensureItemVisible(iconField)
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "Prefix with 'material:' for Material Symbols or 'unicode:' for emoji/Nerd Font glyphs."
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
wrapMode: Text.WordWrap
|
||||
width: parent.width
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
width: (parent.width - Theme.spacingM) / 2
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
StyledText {
|
||||
text: "Search URL *"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
|
||||
DankTextField {
|
||||
id: urlField
|
||||
width: parent.width
|
||||
placeholderText: "e.g., https://example.com/search?q=%s"
|
||||
keyNavigationBacktab: iconField
|
||||
keyNavigationTab: keywordsField
|
||||
onFocusStateChanged: hasFocus => {
|
||||
if (hasFocus) root.ensureItemVisible(urlField)
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "Use %s as placeholder for search query"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
wrapMode: Text.WordWrap
|
||||
width: parent.width
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
StyledText {
|
||||
text: "Keywords (comma separated)"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
|
||||
DankTextField {
|
||||
id: keywordsField
|
||||
width: parent.width
|
||||
placeholderText: "e.g., my,engine,search"
|
||||
keyNavigationBacktab: urlField
|
||||
onFocusStateChanged: hasFocus => {
|
||||
if (hasFocus) root.ensureItemVisible(keywordsField)
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "Use these keywords to trigger this engine (e.g., '? keyword query')"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
wrapMode: Text.WordWrap
|
||||
width: parent.width
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
spacing: Theme.spacingM
|
||||
|
||||
DankButton {
|
||||
id: addButton
|
||||
text: root.editingIndex === -1 ? "Create Engine" : "Update Engine"
|
||||
iconName: root.editingIndex === -1 ? "add" : "save"
|
||||
|
||||
onClicked: {
|
||||
const id = idField.text.trim()
|
||||
const name = nameField.text.trim()
|
||||
const url = urlField.text.trim()
|
||||
|
||||
if (!id || !name || !url) {
|
||||
if (typeof ToastService !== "undefined") {
|
||||
ToastService.showError("Please fill in required fields (ID, Name, URL)")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const keywordsText = keywordsField.text.trim()
|
||||
const keywords = keywordsText ? keywordsText.split(",").map(k => k.trim()).filter(k => k.length > 0) : []
|
||||
|
||||
const engine = {
|
||||
id: id,
|
||||
name: name,
|
||||
icon: iconField.text.trim() || "unicode:🔍",
|
||||
url: url,
|
||||
keywords: keywords
|
||||
}
|
||||
|
||||
const currentEngines = root.loadValue("searchEngines", [])
|
||||
if (root.editingIndex === -1) {
|
||||
const updatedEngines = currentEngines.concat([engine])
|
||||
root.saveValue("searchEngines", updatedEngines)
|
||||
} else {
|
||||
currentEngines[root.editingIndex] = engine
|
||||
root.saveValue("searchEngines", currentEngines)
|
||||
root.editingIndex = -1
|
||||
}
|
||||
|
||||
idField.text = ""
|
||||
nameField.text = ""
|
||||
iconField.text = ""
|
||||
urlField.text = ""
|
||||
keywordsField.text = ""
|
||||
|
||||
idField.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
DankButton {
|
||||
text: "Cancel"
|
||||
iconName: "close"
|
||||
visible: root.editingIndex !== -1
|
||||
onClicked: {
|
||||
root.editingIndex = -1
|
||||
idField.text = ""
|
||||
nameField.text = ""
|
||||
iconField.text = ""
|
||||
urlField.text = ""
|
||||
keywordsField.text = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
height: Math.max(200, enginesColumn.implicitHeight + Theme.spacingL * 2)
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.surfaceContainerHigh
|
||||
|
||||
Column {
|
||||
id: enginesColumn
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingM
|
||||
|
||||
StyledText {
|
||||
text: "Existing Custom Engines"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
ListView {
|
||||
width: parent.width
|
||||
height: Math.max(100, contentHeight)
|
||||
clip: true
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
model: root.variantsModel.count > 0 ? root.variantsModel : root.loadValue("searchEngines", [])
|
||||
|
||||
delegate: StyledRect {
|
||||
required property var model
|
||||
required property int index
|
||||
|
||||
width: ListView.view.width
|
||||
height: engineColumn.implicitHeight + Theme.spacingM * 2
|
||||
radius: Theme.cornerRadius
|
||||
color: engineMouseArea.containsMouse ? Theme.surfaceContainerHighest : Theme.surfaceContainer
|
||||
|
||||
Column {
|
||||
id: engineColumn
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingM
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Item {
|
||||
width: Theme.iconSize
|
||||
height: Theme.iconSize
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: false // Workaround for DankMaterialShell bug with unicode/material icons
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: model.icon || "unicode:🔍"
|
||||
size: Theme.iconSize
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: 2
|
||||
width: parent.width - editButton.width - deleteButton.width - Theme.spacingM * 3
|
||||
|
||||
StyledText {
|
||||
text: model.name || "Unnamed"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "ID: " + (model.id || "") + " | URL: " + (model.url || "")
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
const kw = model.keywords
|
||||
if (kw && kw.length > 0) {
|
||||
let result = []
|
||||
for (let i = 0; i < kw.length; i++) {
|
||||
result.push(kw[i])
|
||||
}
|
||||
return "Keywords: " + result.join(", ")
|
||||
}
|
||||
return "No keywords"
|
||||
}
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: editButton
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 32
|
||||
height: 32
|
||||
radius: 16
|
||||
color: editArea.containsMouse ? Theme.primary : "transparent"
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: "edit"
|
||||
size: 16
|
||||
color: editArea.containsMouse ? Theme.onPrimary : Theme.surfaceVariantText
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: editArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
root.editingIndex = index
|
||||
const engine = root.loadValue("searchEngines", [])[index]
|
||||
idField.text = engine.id
|
||||
nameField.text = engine.name
|
||||
iconField.text = engine.icon
|
||||
urlField.text = engine.url
|
||||
keywordsField.text = Array.isArray(engine.keywords) ? engine.keywords.join(", ") : ""
|
||||
root.ensureItemVisible(idField)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: deleteButton
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 32
|
||||
height: 32
|
||||
radius: 16
|
||||
color: deleteArea.containsMouse ? Theme.error : "transparent"
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: "delete"
|
||||
size: 16
|
||||
color: deleteArea.containsMouse ? Theme.onError : Theme.surfaceVariantText
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: deleteArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
const currentEngines = root.loadValue("searchEngines", [])
|
||||
const updatedEngines = currentEngines.filter((_, i) => i !== index)
|
||||
root.saveValue("searchEngines", updatedEngines)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: engineMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
propagateComposedEvents: true
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
anchors.centerIn: parent
|
||||
text: "No custom engines created yet"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
visible: parent.count === 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
height: 1
|
||||
color: Theme.outlineVariant
|
||||
}
|
||||
|
||||
Column {
|
||||
spacing: 8
|
||||
width: parent.width
|
||||
|
||||
StyledText {
|
||||
text: "Built-in Search Engines:"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
Column {
|
||||
spacing: 4
|
||||
leftPadding: 16
|
||||
|
||||
StyledText {
|
||||
text: "• Google, DuckDuckGo, Brave Search, Bing"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "• YouTube, GitHub, Stack Overflow, Reddit, Wikipedia"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "• Amazon, eBay, Google Maps, Google Images"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "• Twitter/X, LinkedIn, IMDb, Google Translate"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "• Arch Linux, AUR, npm, PyPI, crates.io, MDN"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
height: 1
|
||||
color: Theme.outlineVariant
|
||||
}
|
||||
|
||||
Column {
|
||||
spacing: 8
|
||||
width: parent.width
|
||||
|
||||
StyledText {
|
||||
text: "Usage:"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
Column {
|
||||
spacing: 4
|
||||
leftPadding: 16
|
||||
bottomPadding: 24
|
||||
|
||||
StyledText {
|
||||
text: "1. Open Launcher (Ctrl+Space or click launcher button)"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: noTriggerToggle.checked ? "2. Type your search query directly" : "2. Type your trigger (default: ?) followed by search query"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: noTriggerToggle.checked ? "3. Example: 'linux kernel' or 'github rust'" : "3. Example: '? linux kernel' or '? github rust'"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "4. Use keywords for specific engines: 'youtube music', 'github project', 'wiki topic'"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "5. Select search engine and press Enter to open in browser"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
spacing: 8
|
||||
width: parent.width
|
||||
|
||||
StyledText {
|
||||
text: "Adding Custom Search Engines:"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
Column {
|
||||
spacing: 4
|
||||
leftPadding: 16
|
||||
bottomPadding: 24
|
||||
|
||||
StyledText {
|
||||
text: "1. Find the search URL for your desired website"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "2. Replace the search query with %s in the URL"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "3. Example: https://mysite.com/search?q=%s"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "4. Add it using the Custom Search Engines section above"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "5. Set keywords for quick access (e.g., 'mysite' or 'ms')"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
ref: refs/heads/main
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
[core]
|
||||
bare = false
|
||||
filemode = true
|
||||
[remote "origin"]
|
||||
url = https://github.com/devnullvoid/dms-web-search
|
||||
fetch = +refs/heads/*:refs/remotes/origin/*
|
||||
[branch "main"]
|
||||
remote = origin
|
||||
merge = refs/heads/main
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1 @@
|
|||
81ccd9fd8249b3c9ef40dde42549f807e36ae3e3
|
||||
|
|
@ -0,0 +1 @@
|
|||
81ccd9fd8249b3c9ef40dde42549f807e36ae3e3
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"id": "webSearch",
|
||||
"name": "Web Search",
|
||||
"description": "Search the web with custom search engines",
|
||||
"version": "1.2.0",
|
||||
"author": "devnullvoid",
|
||||
"icon": "search",
|
||||
"type": "launcher",
|
||||
"capabilities": [
|
||||
"web-search",
|
||||
"custom-engines"
|
||||
],
|
||||
"component": "./WebSearch.qml",
|
||||
"settings": "./WebSearchSettings.qml",
|
||||
"trigger": "?",
|
||||
"permissions": [
|
||||
"settings_read",
|
||||
"settings_write"
|
||||
]
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 119 KiB |
Loading…
Add table
Add a link
Reference in a new issue