Working ui demo
This commit is contained in:
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
build/
|
||||||
|
locale/
|
||||||
|
gkeymapper
|
||||||
|
*.o
|
||||||
|
*.so
|
||||||
49
.vscode/tasks.json
vendored
Normal file
49
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "make: build",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make",
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"problemMatcher": "$gcc"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "make: clean",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make clean",
|
||||||
|
"problemMatcher": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "make: translations",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make translations",
|
||||||
|
"problemMatcher": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "make: run",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make run",
|
||||||
|
"dependsOn": [
|
||||||
|
"make: build",
|
||||||
|
"make: translations"
|
||||||
|
],
|
||||||
|
"problemMatcher": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "make: install",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make install",
|
||||||
|
"problemMatcher": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "make: clean build",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make clean && make",
|
||||||
|
"problemMatcher": "$gcc"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
65
Makefile
Normal file
65
Makefile
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
# gKeyMapper - Build
|
||||||
|
# Dependencies: g++, pkg-config, msgfmt, libgtk-4-dev
|
||||||
|
# Installation: sudo apt install build-essential gettext libgtk-4-dev
|
||||||
|
|
||||||
|
CXX ?= g++
|
||||||
|
CXXFLAGS ?= -std=c++17 -O2 -Wall -Wextra -Wpedantic
|
||||||
|
PKG_CONFIG ?= pkg-config
|
||||||
|
MSGFMT ?= msgfmt
|
||||||
|
|
||||||
|
GTK_CFLAGS := $(shell $(PKG_CONFIG) --cflags gtk4)
|
||||||
|
GTK_LIBS := $(shell $(PKG_CONFIG) --libs gtk4)
|
||||||
|
|
||||||
|
PACKAGE := gkeymapper
|
||||||
|
TARGET := gkeymapper
|
||||||
|
SRC_DIR := src
|
||||||
|
SOURCES := $(SRC_DIR)/main.cpp
|
||||||
|
PREFIX ?= /usr/local
|
||||||
|
LOCALEDIR := $(PREFIX)/share/locale
|
||||||
|
ASSETS_DIR := $(PREFIX)/share/$(PACKAGE)/assets
|
||||||
|
|
||||||
|
CXXFLAGS += -DPACKAGE=\"$(PACKAGE)\" -DLOCALEDIR=\"$(LOCALEDIR)\" -DASSETS_DIR=\"$(ASSETS_DIR)\"
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
PO_FILES := $(wildcard po/*.po)
|
||||||
|
LANGS := $(patsubst po/%.po,%,$(PO_FILES))
|
||||||
|
MO_FILES := $(patsubst %,locale/%/LC_MESSAGES/$(PACKAGE).mo,$(LANGS))
|
||||||
|
|
||||||
|
.PHONY: all clean run install translations
|
||||||
|
|
||||||
|
all: $(TARGET) translations
|
||||||
|
|
||||||
|
$(TARGET): $(SOURCES)
|
||||||
|
$(CXX) $(CXXFLAGS) $(GTK_CFLAGS) -o $@ $(SOURCES) $(GTK_LIBS)
|
||||||
|
|
||||||
|
translations: $(MO_FILES)
|
||||||
|
|
||||||
|
locale/%/LC_MESSAGES/$(PACKAGE).mo: po/%.po
|
||||||
|
@mkdir -p $(@D)
|
||||||
|
$(MSGFMT) -o $@ $<
|
||||||
|
|
||||||
|
run: $(TARGET) translations
|
||||||
|
GKEYMAPPER_LOCALEDIR=$(CURDIR)/locale GKEYMAPPER_ASSETS_DIR=$(CURDIR)/assets ./$(TARGET)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(TARGET)
|
||||||
|
rm -rf locale
|
||||||
|
|
||||||
|
install: $(TARGET) translations
|
||||||
|
install -d $(DESTDIR)$(PREFIX)/bin
|
||||||
|
install -m 755 $(TARGET) $(DESTDIR)$(PREFIX)/bin/$(TARGET)
|
||||||
|
install -d $(DESTDIR)$(ASSETS_DIR)
|
||||||
|
install -m 644 assets/* $(DESTDIR)$(ASSETS_DIR)/
|
||||||
|
install -d $(DESTDIR)$(PREFIX)/share/icons/hicolor/256x256/apps
|
||||||
|
install -m 644 assets/icon.png $(DESTDIR)$(PREFIX)/share/icons/hicolor/256x256/apps/$(PACKAGE).png
|
||||||
|
install -d $(DESTDIR)$(PREFIX)/share/icons/hicolor/scalable/apps
|
||||||
|
install -m 644 assets/icon.svg $(DESTDIR)$(PREFIX)/share/icons/hicolor/scalable/apps/$(PACKAGE).svg
|
||||||
|
-command -v gtk-update-icon-cache >/dev/null && gtk-update-icon-cache -q -t $(DESTDIR)$(PREFIX)/share/icons/hicolor 2>/dev/null || true
|
||||||
|
install -d $(DESTDIR)$(PREFIX)/share/applications
|
||||||
|
install -m 644 data/gkeymapper.desktop $(DESTDIR)$(PREFIX)/share/applications/$(PACKAGE).desktop
|
||||||
|
-command -v update-desktop-database >/dev/null && update-desktop-database $(DESTDIR)$(PREFIX)/share/applications 2>/dev/null || true
|
||||||
|
for lang in $(LANGS); do \
|
||||||
|
install -d $(DESTDIR)$(LOCALEDIR)/$$lang/LC_MESSAGES; \
|
||||||
|
install -m 644 locale/$$lang/LC_MESSAGES/$(PACKAGE).mo \
|
||||||
|
$(DESTDIR)$(LOCALEDIR)/$$lang/LC_MESSAGES/$(PACKAGE).mo; \
|
||||||
|
done
|
||||||
124
README.md
Normal file
124
README.md
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
# gKeyMapper
|
||||||
|
|
||||||
|
GTK4 application (C++) for remapping the G keys **G1–G9** of a Logitech **G910**
|
||||||
|
to other keys or commands (Linux Mint / Ubuntu).
|
||||||
|
|
||||||
|
The current focus is on the **GUI** only (no actual key capture/command execution yet).
|
||||||
|
|
||||||
|
Documentation and source comments are written in English.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Linux Mint / Ubuntu
|
||||||
|
- g++ (C++17)
|
||||||
|
- pkg-config
|
||||||
|
- gettext (for translations, `msgfmt`)
|
||||||
|
- GTK 4 development files
|
||||||
|
|
||||||
|
### Install dependencies
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y build-essential gettext libgtk-4-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Afterwards `pkg-config --modversion gtk4` should print a version (e.g. `4.6.x`).
|
||||||
|
|
||||||
|
## Setting up the project
|
||||||
|
|
||||||
|
Change to the project directory:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /home/trager/Nextcloud/Projekte/C++/gKeyMapper
|
||||||
|
```
|
||||||
|
|
||||||
|
(Alternatively clone the repository or copy the project folder to your own location.)
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
|
This produces the `gkeymapper` binary and the `.mo` translations under `locale/`.
|
||||||
|
|
||||||
|
## Rebuild translations
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make translations
|
||||||
|
```
|
||||||
|
|
||||||
|
## Run
|
||||||
|
|
||||||
|
Normal:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./gkeymapper
|
||||||
|
```
|
||||||
|
|
||||||
|
With explicit language files (useful for testing from the build directory):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
LANG=de_DE.UTF-8 GKEYMAPPER_LOCALEDIR=$PWD/locale ./gkeymapper
|
||||||
|
```
|
||||||
|
|
||||||
|
Supported languages: German, English, Spanish, French.
|
||||||
|
|
||||||
|
## Install (optional)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo make install
|
||||||
|
```
|
||||||
|
|
||||||
|
Installs `gkeymapper` to `/usr/local/bin` and the `.mo` files to
|
||||||
|
`/usr/local/share/locale`.
|
||||||
|
|
||||||
|
## Clean
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make clean
|
||||||
|
```
|
||||||
|
|
||||||
|
Removes the binary and the generated `locale/` directory.
|
||||||
|
|
||||||
|
## Project structure
|
||||||
|
|
||||||
|
```
|
||||||
|
src/main.cpp # GTK4 GUI
|
||||||
|
po/ # Translations (pot/po/mo targets)
|
||||||
|
Makefile # Build via pkg-config + gettext
|
||||||
|
.vscode/tasks.json # VS Code tasks for make
|
||||||
|
README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### `Package gtk4 was not found`
|
||||||
|
|
||||||
|
The GTK 4 development files are missing. Install them:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt install -y libgtk-4-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Then verify:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pkg-config --modversion gtk4
|
||||||
|
```
|
||||||
|
|
||||||
|
### `pkg-config` cannot find `.pc` files (wrong search path)
|
||||||
|
|
||||||
|
In some environments `PKG_CONFIG_PATH` must be set explicitly. Standard path on
|
||||||
|
Ubuntu/Mint:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export PKG_CONFIG_PATH=/usr/lib/x86_64-linux-gnu/pkgconfig:/usr/share/pkgconfig:/usr/lib/pkgconfig
|
||||||
|
```
|
||||||
|
|
||||||
|
## Planned next steps
|
||||||
|
|
||||||
|
- Real capture of key presses (evdev/uinput or libinput).
|
||||||
|
- Execution of commands when a G key is pressed.
|
||||||
|
- Loading and saving profiles.
|
||||||
|
- Autostart service / background daemon.
|
||||||
BIN
assets/icon.png
Normal file
BIN
assets/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.9 KiB |
13
assets/icon.svg
Normal file
13
assets/icon.svg
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg width="100%" height="100%" viewBox="0 0 2000 2000" version="1.1" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;">
|
||||||
|
<g id="Logo" transform="matrix(3.86383,0,0,3.86383,-2875.29,-2663.36)">
|
||||||
|
<g>
|
||||||
|
<g transform="matrix(1,0,0,1,198.741,171.259)">
|
||||||
|
<path d="M799,699L736,569L632,569L680,669L570,669L680,949L789,949L679,698L799,699Z" style="fill:#00ff66;"/>
|
||||||
|
</g>
|
||||||
|
<g id="Logo-Komponent" transform="matrix(-1,0,0,1,1807.19,171.259)">
|
||||||
|
<path d="M799,699L736,569L632,569L680,669L570,669L680,949L789,949L679,698L799,699Z" style="fill:#00ff66;"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 832 B |
11
data/gkeymapper.desktop
Normal file
11
data/gkeymapper.desktop
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Type=Application
|
||||||
|
Name=gKeyMapper
|
||||||
|
GenericName=G-Key Mapper
|
||||||
|
Comment=Remap the G keys (G1-G9) of a Logitech G910
|
||||||
|
Exec=gkeymapper
|
||||||
|
Icon=gkeymapper
|
||||||
|
Terminal=false
|
||||||
|
Categories=Utility;
|
||||||
|
StartupNotify=true
|
||||||
|
StartupWMClass=gkeymapper
|
||||||
138
po/de.po
Normal file
138
po/de.po
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
# German translation for gkeymapper.
|
||||||
|
# Copyright (C) 2026
|
||||||
|
# This file is distributed under the same license as the gkeymapper package.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: gkeymapper 0.1\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2026-10-16 21:53+0200\n"
|
||||||
|
"PO-Revision-Date: 2026-10-16 21:00+0000\n"
|
||||||
|
"Last-Translator: \n"
|
||||||
|
"Language-Team: German\n"
|
||||||
|
"Language: de\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: src/main.cpp:53
|
||||||
|
msgid "Choose file"
|
||||||
|
msgstr "Datei auswählen"
|
||||||
|
|
||||||
|
#: src/main.cpp:56 src/main.cpp:224 src/main.cpp:236
|
||||||
|
msgid "_Cancel"
|
||||||
|
msgstr "_Abbrechen"
|
||||||
|
|
||||||
|
#: src/main.cpp:57 src/main.cpp:237
|
||||||
|
msgid "_Open"
|
||||||
|
msgstr "_Öffnen"
|
||||||
|
|
||||||
|
#: src/main.cpp:75
|
||||||
|
msgid "<Press a key...>"
|
||||||
|
msgstr "<Taste drücken...>"
|
||||||
|
|
||||||
|
#: src/main.cpp:87
|
||||||
|
msgid "Choose file..."
|
||||||
|
msgstr "Datei auswählen..."
|
||||||
|
|
||||||
|
#: src/main.cpp:89 src/main.cpp:364
|
||||||
|
msgid "Capture"
|
||||||
|
msgstr "Aufnehmen"
|
||||||
|
|
||||||
|
#: src/main.cpp:125
|
||||||
|
#, c-format
|
||||||
|
msgid "Could not save %s.\n"
|
||||||
|
msgstr "Konnte %s nicht speichern.\n"
|
||||||
|
|
||||||
|
#: src/main.cpp:129
|
||||||
|
msgid "Mappings saved to "
|
||||||
|
msgstr "Mappings gespeichert nach "
|
||||||
|
|
||||||
|
#: src/main.cpp:135
|
||||||
|
#, c-format
|
||||||
|
msgid "Could not open %s.\n"
|
||||||
|
msgstr "Konnte %s nicht öffnen.\n"
|
||||||
|
|
||||||
|
#: src/main.cpp:187
|
||||||
|
msgid "Could not export mappings.\n"
|
||||||
|
msgstr "Mappings konnten nicht exportiert werden.\n"
|
||||||
|
|
||||||
|
#: src/main.cpp:210 src/main.cpp:273
|
||||||
|
msgid "gKeyMapper"
|
||||||
|
msgstr "gKeyMapper"
|
||||||
|
|
||||||
|
#: src/main.cpp:213
|
||||||
|
msgid "G-Key mapper for the Logitech G910 (GTK4)."
|
||||||
|
msgstr "G-Key-Mapper für die Logitech G910 (GTK4)."
|
||||||
|
|
||||||
|
#: src/main.cpp:221
|
||||||
|
msgid "Export configuration"
|
||||||
|
msgstr "Konfiguration exportieren"
|
||||||
|
|
||||||
|
#: src/main.cpp:225
|
||||||
|
msgid "_Save"
|
||||||
|
msgstr "_Speichern"
|
||||||
|
|
||||||
|
#: src/main.cpp:233
|
||||||
|
msgid "Import configuration"
|
||||||
|
msgstr "Konfiguration importieren"
|
||||||
|
|
||||||
|
#: src/main.cpp:269
|
||||||
|
msgid "gKeyMapper – Logitech G910"
|
||||||
|
msgstr "gKeyMapper – Logitech G910"
|
||||||
|
|
||||||
|
#: src/main.cpp:277
|
||||||
|
msgid "Export configuration..."
|
||||||
|
msgstr "Konfiguration exportieren..."
|
||||||
|
|
||||||
|
#: src/main.cpp:278
|
||||||
|
msgid "Import configuration..."
|
||||||
|
msgstr "Konfiguration importieren..."
|
||||||
|
|
||||||
|
#: src/main.cpp:281
|
||||||
|
msgid "About"
|
||||||
|
msgstr "Über"
|
||||||
|
|
||||||
|
#: src/main.cpp:305
|
||||||
|
msgid "G1 to G9 of the Logitech G910 remapped to keys or commands"
|
||||||
|
msgstr "G1 bis G9 der Logitech G910 auf Tasten oder Befehle ummappen"
|
||||||
|
|
||||||
|
#: src/main.cpp:327
|
||||||
|
msgid "G-Key"
|
||||||
|
msgstr "G-Taste"
|
||||||
|
|
||||||
|
#: src/main.cpp:327
|
||||||
|
msgid "Type"
|
||||||
|
msgstr "Typ"
|
||||||
|
|
||||||
|
#: src/main.cpp:327
|
||||||
|
msgid "Target (Key/Command)"
|
||||||
|
msgstr "Ziel (Taste/Befehl)"
|
||||||
|
|
||||||
|
#: src/main.cpp:327
|
||||||
|
msgid "Action"
|
||||||
|
msgstr "Aktion"
|
||||||
|
|
||||||
|
#: src/main.cpp:335
|
||||||
|
msgid "Key"
|
||||||
|
msgstr "Taste"
|
||||||
|
|
||||||
|
#: src/main.cpp:335
|
||||||
|
msgid "Command"
|
||||||
|
msgstr "Befehl"
|
||||||
|
|
||||||
|
#: src/main.cpp:335
|
||||||
|
msgid "Disabled"
|
||||||
|
msgstr "Deaktiviert"
|
||||||
|
|
||||||
|
#: src/main.cpp:358
|
||||||
|
msgid "e.g. ctrl+c or ls -la"
|
||||||
|
msgstr "z. B. Strg+C oder ls -la"
|
||||||
|
|
||||||
|
#: src/main.cpp:378
|
||||||
|
msgid "Save mappings"
|
||||||
|
msgstr "Mappings speichern"
|
||||||
|
|
||||||
|
#: src/main.cpp:383
|
||||||
|
msgid "Saved to ~/.config/gKeyMapper/mappings.conf"
|
||||||
|
msgstr "Gespeichert in ~/.config/gKeyMapper/mappings.conf"
|
||||||
102
po/de.po~
Normal file
102
po/de.po~
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
# German translation for gkeymapper.
|
||||||
|
# Copyright (C) 2026
|
||||||
|
# This file is distributed under the same license as the gkeymapper package.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: gkeymapper 0.1\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2026-10-16 21:00+0000\n"
|
||||||
|
"PO-Revision-Date: 2026-10-16 21:00+0000\n"
|
||||||
|
"Last-Translator: \n"
|
||||||
|
"Language-Team: German\n"
|
||||||
|
"Language: de\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
msgid "<Press a key...>"
|
||||||
|
msgstr "<Taste drücken...>"
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid "Could not save %s.\n"
|
||||||
|
msgstr "Konnte %s nicht speichern.\n"
|
||||||
|
|
||||||
|
msgid "Mappings saved to "
|
||||||
|
msgstr "Mappings gespeichert nach "
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid "Could not open %s.\n"
|
||||||
|
msgstr "Konnte %s nicht öffnen.\n"
|
||||||
|
|
||||||
|
msgid "Could not export mappings.\n"
|
||||||
|
msgstr "Mappings konnten nicht exportiert werden.\n"
|
||||||
|
|
||||||
|
msgid "gKeyMapper"
|
||||||
|
msgstr "gKeyMapper"
|
||||||
|
|
||||||
|
msgid "G-Key mapper for the Logitech G910 (GTK4)."
|
||||||
|
msgstr "G-Key-Mapper für die Logitech G910 (GTK4)."
|
||||||
|
|
||||||
|
msgid "Export configuration"
|
||||||
|
msgstr "Konfiguration exportieren"
|
||||||
|
|
||||||
|
msgid "_Cancel"
|
||||||
|
msgstr "_Abbrechen"
|
||||||
|
|
||||||
|
msgid "_Save"
|
||||||
|
msgstr "_Speichern"
|
||||||
|
|
||||||
|
msgid "Import configuration"
|
||||||
|
msgstr "Konfiguration importieren"
|
||||||
|
|
||||||
|
msgid "_Open"
|
||||||
|
msgstr "_Öffnen"
|
||||||
|
|
||||||
|
msgid "gKeyMapper – Logitech G910"
|
||||||
|
msgstr "gKeyMapper – Logitech G910"
|
||||||
|
|
||||||
|
msgid "Export configuration..."
|
||||||
|
msgstr "Konfiguration exportieren..."
|
||||||
|
|
||||||
|
msgid "Import configuration..."
|
||||||
|
msgstr "Konfiguration importieren..."
|
||||||
|
|
||||||
|
msgid "About"
|
||||||
|
msgstr "Über"
|
||||||
|
|
||||||
|
msgid "G1 to G9 of the Logitech G910 remapped to keys or commands"
|
||||||
|
msgstr "G1 bis G9 der Logitech G910 auf Tasten oder Befehle ummappen"
|
||||||
|
|
||||||
|
msgid "G-Key"
|
||||||
|
msgstr "G-Taste"
|
||||||
|
|
||||||
|
msgid "Type"
|
||||||
|
msgstr "Typ"
|
||||||
|
|
||||||
|
msgid "Target (Key/Command)"
|
||||||
|
msgstr "Ziel (Taste/Befehl)"
|
||||||
|
|
||||||
|
msgid "Action"
|
||||||
|
msgstr "Aktion"
|
||||||
|
|
||||||
|
msgid "Key"
|
||||||
|
msgstr "Taste"
|
||||||
|
|
||||||
|
msgid "Command"
|
||||||
|
msgstr "Befehl"
|
||||||
|
|
||||||
|
msgid "Disabled"
|
||||||
|
msgstr "Deaktiviert"
|
||||||
|
|
||||||
|
msgid "e.g. ctrl+c or ls -la"
|
||||||
|
msgstr "z. B. Strg+C oder ls -la"
|
||||||
|
|
||||||
|
msgid "Capture"
|
||||||
|
msgstr "Aufnehmen"
|
||||||
|
|
||||||
|
msgid "Save mappings"
|
||||||
|
msgstr "Mappings speichern"
|
||||||
|
|
||||||
|
msgid "Saved to ~/.config/gKeyMapper/mappings.conf"
|
||||||
|
msgstr "Gespeichert in ~/.config/gKeyMapper/mappings.conf"
|
||||||
136
po/es.po
Normal file
136
po/es.po
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
# Spanish translation for gkeymapper.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: gkeymapper 0.1\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2026-10-16 21:53+0200\n"
|
||||||
|
"PO-Revision-Date: 2026-10-16 21:00+0000\n"
|
||||||
|
"Last-Translator: \n"
|
||||||
|
"Language-Team: Spanish\n"
|
||||||
|
"Language: es\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: src/main.cpp:53
|
||||||
|
msgid "Choose file"
|
||||||
|
msgstr "Elegir archivo"
|
||||||
|
|
||||||
|
#: src/main.cpp:56 src/main.cpp:224 src/main.cpp:236
|
||||||
|
msgid "_Cancel"
|
||||||
|
msgstr "_Cancelar"
|
||||||
|
|
||||||
|
#: src/main.cpp:57 src/main.cpp:237
|
||||||
|
msgid "_Open"
|
||||||
|
msgstr "_Abrir"
|
||||||
|
|
||||||
|
#: src/main.cpp:75
|
||||||
|
msgid "<Press a key...>"
|
||||||
|
msgstr "<Pulsa una tecla...>"
|
||||||
|
|
||||||
|
#: src/main.cpp:87
|
||||||
|
msgid "Choose file..."
|
||||||
|
msgstr "Elegir archivo..."
|
||||||
|
|
||||||
|
#: src/main.cpp:89 src/main.cpp:364
|
||||||
|
msgid "Capture"
|
||||||
|
msgstr "Capturar"
|
||||||
|
|
||||||
|
#: src/main.cpp:125
|
||||||
|
#, c-format
|
||||||
|
msgid "Could not save %s.\n"
|
||||||
|
msgstr "No se pudo guardar %s.\n"
|
||||||
|
|
||||||
|
#: src/main.cpp:129
|
||||||
|
msgid "Mappings saved to "
|
||||||
|
msgstr "Asignaciones guardadas en "
|
||||||
|
|
||||||
|
#: src/main.cpp:135
|
||||||
|
#, c-format
|
||||||
|
msgid "Could not open %s.\n"
|
||||||
|
msgstr "No se pudo abrir %s.\n"
|
||||||
|
|
||||||
|
#: src/main.cpp:187
|
||||||
|
msgid "Could not export mappings.\n"
|
||||||
|
msgstr "No se pudieron exportar las asignaciones.\n"
|
||||||
|
|
||||||
|
#: src/main.cpp:210 src/main.cpp:273
|
||||||
|
msgid "gKeyMapper"
|
||||||
|
msgstr "gKeyMapper"
|
||||||
|
|
||||||
|
#: src/main.cpp:213
|
||||||
|
msgid "G-Key mapper for the Logitech G910 (GTK4)."
|
||||||
|
msgstr "Asignador de teclas G para el Logitech G910 (GTK4)."
|
||||||
|
|
||||||
|
#: src/main.cpp:221
|
||||||
|
msgid "Export configuration"
|
||||||
|
msgstr "Exportar configuración"
|
||||||
|
|
||||||
|
#: src/main.cpp:225
|
||||||
|
msgid "_Save"
|
||||||
|
msgstr "_Guardar"
|
||||||
|
|
||||||
|
#: src/main.cpp:233
|
||||||
|
msgid "Import configuration"
|
||||||
|
msgstr "Importar configuración"
|
||||||
|
|
||||||
|
#: src/main.cpp:269
|
||||||
|
msgid "gKeyMapper – Logitech G910"
|
||||||
|
msgstr "gKeyMapper – Logitech G910"
|
||||||
|
|
||||||
|
#: src/main.cpp:277
|
||||||
|
msgid "Export configuration..."
|
||||||
|
msgstr "Exportar configuración..."
|
||||||
|
|
||||||
|
#: src/main.cpp:278
|
||||||
|
msgid "Import configuration..."
|
||||||
|
msgstr "Importar configuración..."
|
||||||
|
|
||||||
|
#: src/main.cpp:281
|
||||||
|
msgid "About"
|
||||||
|
msgstr "Acerca de"
|
||||||
|
|
||||||
|
#: src/main.cpp:305
|
||||||
|
msgid "G1 to G9 of the Logitech G910 remapped to keys or commands"
|
||||||
|
msgstr "Reasigna las G1 a G9 del Logitech G910 a teclas o comandos"
|
||||||
|
|
||||||
|
#: src/main.cpp:327
|
||||||
|
msgid "G-Key"
|
||||||
|
msgstr "Tecla G"
|
||||||
|
|
||||||
|
#: src/main.cpp:327
|
||||||
|
msgid "Type"
|
||||||
|
msgstr "Tipo"
|
||||||
|
|
||||||
|
#: src/main.cpp:327
|
||||||
|
msgid "Target (Key/Command)"
|
||||||
|
msgstr "Destino (Tecla/Comando)"
|
||||||
|
|
||||||
|
#: src/main.cpp:327
|
||||||
|
msgid "Action"
|
||||||
|
msgstr "Acción"
|
||||||
|
|
||||||
|
#: src/main.cpp:335
|
||||||
|
msgid "Key"
|
||||||
|
msgstr "Tecla"
|
||||||
|
|
||||||
|
#: src/main.cpp:335
|
||||||
|
msgid "Command"
|
||||||
|
msgstr "Comando"
|
||||||
|
|
||||||
|
#: src/main.cpp:335
|
||||||
|
msgid "Disabled"
|
||||||
|
msgstr "Desactivado"
|
||||||
|
|
||||||
|
#: src/main.cpp:358
|
||||||
|
msgid "e.g. ctrl+c or ls -la"
|
||||||
|
msgstr "p. ej. ctrl+c o ls -la"
|
||||||
|
|
||||||
|
#: src/main.cpp:378
|
||||||
|
msgid "Save mappings"
|
||||||
|
msgstr "Guardar asignaciones"
|
||||||
|
|
||||||
|
#: src/main.cpp:383
|
||||||
|
msgid "Saved to ~/.config/gKeyMapper/mappings.conf"
|
||||||
|
msgstr "Guardado en ~/.config/gKeyMapper/mappings.conf"
|
||||||
100
po/es.po~
Normal file
100
po/es.po~
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
# Spanish translation for gkeymapper.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: gkeymapper 0.1\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2026-10-16 21:00+0000\n"
|
||||||
|
"PO-Revision-Date: 2026-10-16 21:00+0000\n"
|
||||||
|
"Last-Translator: \n"
|
||||||
|
"Language-Team: Spanish\n"
|
||||||
|
"Language: es\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
msgid "<Press a key...>"
|
||||||
|
msgstr "<Pulsa una tecla...>"
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid "Could not save %s.\n"
|
||||||
|
msgstr "No se pudo guardar %s.\n"
|
||||||
|
|
||||||
|
msgid "Mappings saved to "
|
||||||
|
msgstr "Asignaciones guardadas en "
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid "Could not open %s.\n"
|
||||||
|
msgstr "No se pudo abrir %s.\n"
|
||||||
|
|
||||||
|
msgid "Could not export mappings.\n"
|
||||||
|
msgstr "No se pudieron exportar las asignaciones.\n"
|
||||||
|
|
||||||
|
msgid "gKeyMapper"
|
||||||
|
msgstr "gKeyMapper"
|
||||||
|
|
||||||
|
msgid "G-Key mapper for the Logitech G910 (GTK4)."
|
||||||
|
msgstr "Asignador de teclas G para el Logitech G910 (GTK4)."
|
||||||
|
|
||||||
|
msgid "Export configuration"
|
||||||
|
msgstr "Exportar configuración"
|
||||||
|
|
||||||
|
msgid "_Cancel"
|
||||||
|
msgstr "_Cancelar"
|
||||||
|
|
||||||
|
msgid "_Save"
|
||||||
|
msgstr "_Guardar"
|
||||||
|
|
||||||
|
msgid "Import configuration"
|
||||||
|
msgstr "Importar configuración"
|
||||||
|
|
||||||
|
msgid "_Open"
|
||||||
|
msgstr "_Abrir"
|
||||||
|
|
||||||
|
msgid "gKeyMapper – Logitech G910"
|
||||||
|
msgstr "gKeyMapper – Logitech G910"
|
||||||
|
|
||||||
|
msgid "Export configuration..."
|
||||||
|
msgstr "Exportar configuración..."
|
||||||
|
|
||||||
|
msgid "Import configuration..."
|
||||||
|
msgstr "Importar configuración..."
|
||||||
|
|
||||||
|
msgid "About"
|
||||||
|
msgstr "Acerca de"
|
||||||
|
|
||||||
|
msgid "G1 to G9 of the Logitech G910 remapped to keys or commands"
|
||||||
|
msgstr "Reasigna las G1 a G9 del Logitech G910 a teclas o comandos"
|
||||||
|
|
||||||
|
msgid "G-Key"
|
||||||
|
msgstr "Tecla G"
|
||||||
|
|
||||||
|
msgid "Type"
|
||||||
|
msgstr "Tipo"
|
||||||
|
|
||||||
|
msgid "Target (Key/Command)"
|
||||||
|
msgstr "Destino (Tecla/Comando)"
|
||||||
|
|
||||||
|
msgid "Action"
|
||||||
|
msgstr "Acción"
|
||||||
|
|
||||||
|
msgid "Key"
|
||||||
|
msgstr "Tecla"
|
||||||
|
|
||||||
|
msgid "Command"
|
||||||
|
msgstr "Comando"
|
||||||
|
|
||||||
|
msgid "Disabled"
|
||||||
|
msgstr "Desactivado"
|
||||||
|
|
||||||
|
msgid "e.g. ctrl+c or ls -la"
|
||||||
|
msgstr "p. ej. ctrl+c o ls -la"
|
||||||
|
|
||||||
|
msgid "Capture"
|
||||||
|
msgstr "Capturar"
|
||||||
|
|
||||||
|
msgid "Save mappings"
|
||||||
|
msgstr "Guardar asignaciones"
|
||||||
|
|
||||||
|
msgid "Saved to ~/.config/gKeyMapper/mappings.conf"
|
||||||
|
msgstr "Guardado en ~/.config/gKeyMapper/mappings.conf"
|
||||||
138
po/fr.po
Normal file
138
po/fr.po
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
# French translation for gkeymapper.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: gkeymapper 0.1\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2026-10-16 21:53+0200\n"
|
||||||
|
"PO-Revision-Date: 2026-10-16 21:00+0000\n"
|
||||||
|
"Last-Translator: \n"
|
||||||
|
"Language-Team: French\n"
|
||||||
|
"Language: fr\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: src/main.cpp:53
|
||||||
|
msgid "Choose file"
|
||||||
|
msgstr "Choisir un fichier"
|
||||||
|
|
||||||
|
#: src/main.cpp:56 src/main.cpp:224 src/main.cpp:236
|
||||||
|
msgid "_Cancel"
|
||||||
|
msgstr "_Annuler"
|
||||||
|
|
||||||
|
#: src/main.cpp:57 src/main.cpp:237
|
||||||
|
msgid "_Open"
|
||||||
|
msgstr "_Ouvrir"
|
||||||
|
|
||||||
|
#: src/main.cpp:75
|
||||||
|
msgid "<Press a key...>"
|
||||||
|
msgstr "<Appuyez sur une touche...>"
|
||||||
|
|
||||||
|
#: src/main.cpp:87
|
||||||
|
msgid "Choose file..."
|
||||||
|
msgstr "Choisir un fichier..."
|
||||||
|
|
||||||
|
#: src/main.cpp:89 src/main.cpp:364
|
||||||
|
msgid "Capture"
|
||||||
|
msgstr "Capturer"
|
||||||
|
|
||||||
|
#: src/main.cpp:125
|
||||||
|
#, c-format
|
||||||
|
msgid "Could not save %s.\n"
|
||||||
|
msgstr "Impossible d'enregistrer %s.\n"
|
||||||
|
|
||||||
|
#: src/main.cpp:129
|
||||||
|
msgid "Mappings saved to "
|
||||||
|
msgstr "Attributions enregistrées dans "
|
||||||
|
|
||||||
|
#: src/main.cpp:135
|
||||||
|
#, c-format
|
||||||
|
msgid "Could not open %s.\n"
|
||||||
|
msgstr "Impossible d'ouvrir %s.\n"
|
||||||
|
|
||||||
|
#: src/main.cpp:187
|
||||||
|
msgid "Could not export mappings.\n"
|
||||||
|
msgstr "Impossible d'exporter les attributions.\n"
|
||||||
|
|
||||||
|
#: src/main.cpp:210 src/main.cpp:273
|
||||||
|
msgid "gKeyMapper"
|
||||||
|
msgstr "gKeyMapper"
|
||||||
|
|
||||||
|
#: src/main.cpp:213
|
||||||
|
msgid "G-Key mapper for the Logitech G910 (GTK4)."
|
||||||
|
msgstr "Assignateur de touches G pour le Logitech G910 (GTK4)."
|
||||||
|
|
||||||
|
#: src/main.cpp:221
|
||||||
|
msgid "Export configuration"
|
||||||
|
msgstr "Exporter la configuration"
|
||||||
|
|
||||||
|
#: src/main.cpp:225
|
||||||
|
msgid "_Save"
|
||||||
|
msgstr "_Enregistrer"
|
||||||
|
|
||||||
|
#: src/main.cpp:233
|
||||||
|
msgid "Import configuration"
|
||||||
|
msgstr "Importer la configuration"
|
||||||
|
|
||||||
|
#: src/main.cpp:269
|
||||||
|
msgid "gKeyMapper – Logitech G910"
|
||||||
|
msgstr "gKeyMapper – Logitech G910"
|
||||||
|
|
||||||
|
#: src/main.cpp:277
|
||||||
|
msgid "Export configuration..."
|
||||||
|
msgstr "Exporter la configuration..."
|
||||||
|
|
||||||
|
#: src/main.cpp:278
|
||||||
|
msgid "Import configuration..."
|
||||||
|
msgstr "Importer la configuration..."
|
||||||
|
|
||||||
|
#: src/main.cpp:281
|
||||||
|
msgid "About"
|
||||||
|
msgstr "À propos"
|
||||||
|
|
||||||
|
#: src/main.cpp:305
|
||||||
|
msgid "G1 to G9 of the Logitech G910 remapped to keys or commands"
|
||||||
|
msgstr ""
|
||||||
|
"Réassignation des touches G1 à G9 du Logitech G910 vers des touches ou des "
|
||||||
|
"commandes"
|
||||||
|
|
||||||
|
#: src/main.cpp:327
|
||||||
|
msgid "G-Key"
|
||||||
|
msgstr "Touche G"
|
||||||
|
|
||||||
|
#: src/main.cpp:327
|
||||||
|
msgid "Type"
|
||||||
|
msgstr "Type"
|
||||||
|
|
||||||
|
#: src/main.cpp:327
|
||||||
|
msgid "Target (Key/Command)"
|
||||||
|
msgstr "Cible (Touche/Commande)"
|
||||||
|
|
||||||
|
#: src/main.cpp:327
|
||||||
|
msgid "Action"
|
||||||
|
msgstr "Action"
|
||||||
|
|
||||||
|
#: src/main.cpp:335
|
||||||
|
msgid "Key"
|
||||||
|
msgstr "Touche"
|
||||||
|
|
||||||
|
#: src/main.cpp:335
|
||||||
|
msgid "Command"
|
||||||
|
msgstr "Commande"
|
||||||
|
|
||||||
|
#: src/main.cpp:335
|
||||||
|
msgid "Disabled"
|
||||||
|
msgstr "Désactivé"
|
||||||
|
|
||||||
|
#: src/main.cpp:358
|
||||||
|
msgid "e.g. ctrl+c or ls -la"
|
||||||
|
msgstr "ex. ctrl+c ou ls -la"
|
||||||
|
|
||||||
|
#: src/main.cpp:378
|
||||||
|
msgid "Save mappings"
|
||||||
|
msgstr "Enregistrer les attributions"
|
||||||
|
|
||||||
|
#: src/main.cpp:383
|
||||||
|
msgid "Saved to ~/.config/gKeyMapper/mappings.conf"
|
||||||
|
msgstr "Enregistré dans ~/.config/gKeyMapper/mappings.conf"
|
||||||
100
po/fr.po~
Normal file
100
po/fr.po~
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
# French translation for gkeymapper.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: gkeymapper 0.1\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2026-10-16 21:00+0000\n"
|
||||||
|
"PO-Revision-Date: 2026-10-16 21:00+0000\n"
|
||||||
|
"Last-Translator: \n"
|
||||||
|
"Language-Team: French\n"
|
||||||
|
"Language: fr\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
msgid "<Press a key...>"
|
||||||
|
msgstr "<Appuyez sur une touche...>"
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid "Could not save %s.\n"
|
||||||
|
msgstr "Impossible d'enregistrer %s.\n"
|
||||||
|
|
||||||
|
msgid "Mappings saved to "
|
||||||
|
msgstr "Attributions enregistrées dans "
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid "Could not open %s.\n"
|
||||||
|
msgstr "Impossible d'ouvrir %s.\n"
|
||||||
|
|
||||||
|
msgid "Could not export mappings.\n"
|
||||||
|
msgstr "Impossible d'exporter les attributions.\n"
|
||||||
|
|
||||||
|
msgid "gKeyMapper"
|
||||||
|
msgstr "gKeyMapper"
|
||||||
|
|
||||||
|
msgid "G-Key mapper for the Logitech G910 (GTK4)."
|
||||||
|
msgstr "Assignateur de touches G pour le Logitech G910 (GTK4)."
|
||||||
|
|
||||||
|
msgid "Export configuration"
|
||||||
|
msgstr "Exporter la configuration"
|
||||||
|
|
||||||
|
msgid "_Cancel"
|
||||||
|
msgstr "_Annuler"
|
||||||
|
|
||||||
|
msgid "_Save"
|
||||||
|
msgstr "_Enregistrer"
|
||||||
|
|
||||||
|
msgid "Import configuration"
|
||||||
|
msgstr "Importer la configuration"
|
||||||
|
|
||||||
|
msgid "_Open"
|
||||||
|
msgstr "_Ouvrir"
|
||||||
|
|
||||||
|
msgid "gKeyMapper – Logitech G910"
|
||||||
|
msgstr "gKeyMapper – Logitech G910"
|
||||||
|
|
||||||
|
msgid "Export configuration..."
|
||||||
|
msgstr "Exporter la configuration..."
|
||||||
|
|
||||||
|
msgid "Import configuration..."
|
||||||
|
msgstr "Importer la configuration..."
|
||||||
|
|
||||||
|
msgid "About"
|
||||||
|
msgstr "À propos"
|
||||||
|
|
||||||
|
msgid "G1 to G9 of the Logitech G910 remapped to keys or commands"
|
||||||
|
msgstr "Réassignation des touches G1 à G9 du Logitech G910 vers des touches ou des commandes"
|
||||||
|
|
||||||
|
msgid "G-Key"
|
||||||
|
msgstr "Touche G"
|
||||||
|
|
||||||
|
msgid "Type"
|
||||||
|
msgstr "Type"
|
||||||
|
|
||||||
|
msgid "Target (Key/Command)"
|
||||||
|
msgstr "Cible (Touche/Commande)"
|
||||||
|
|
||||||
|
msgid "Action"
|
||||||
|
msgstr "Action"
|
||||||
|
|
||||||
|
msgid "Key"
|
||||||
|
msgstr "Touche"
|
||||||
|
|
||||||
|
msgid "Command"
|
||||||
|
msgstr "Commande"
|
||||||
|
|
||||||
|
msgid "Disabled"
|
||||||
|
msgstr "Désactivé"
|
||||||
|
|
||||||
|
msgid "e.g. ctrl+c or ls -la"
|
||||||
|
msgstr "ex. ctrl+c ou ls -la"
|
||||||
|
|
||||||
|
msgid "Capture"
|
||||||
|
msgstr "Capturer"
|
||||||
|
|
||||||
|
msgid "Save mappings"
|
||||||
|
msgstr "Enregistrer les attributions"
|
||||||
|
|
||||||
|
msgid "Saved to ~/.config/gKeyMapper/mappings.conf"
|
||||||
|
msgstr "Enregistré dans ~/.config/gKeyMapper/mappings.conf"
|
||||||
140
po/gkeymapper.pot
Normal file
140
po/gkeymapper.pot
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2026-10-16 21:53+0200\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"Language: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: src/main.cpp:53
|
||||||
|
msgid "Choose file"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:56 src/main.cpp:224 src/main.cpp:236
|
||||||
|
msgid "_Cancel"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:57 src/main.cpp:237
|
||||||
|
msgid "_Open"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:75
|
||||||
|
msgid "<Press a key...>"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:87
|
||||||
|
msgid "Choose file..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:89 src/main.cpp:364
|
||||||
|
msgid "Capture"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:125
|
||||||
|
#, c-format
|
||||||
|
msgid "Could not save %s.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:129
|
||||||
|
msgid "Mappings saved to "
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:135
|
||||||
|
#, c-format
|
||||||
|
msgid "Could not open %s.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:187
|
||||||
|
msgid "Could not export mappings.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:210 src/main.cpp:273
|
||||||
|
msgid "gKeyMapper"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:213
|
||||||
|
msgid "G-Key mapper for the Logitech G910 (GTK4)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:221
|
||||||
|
msgid "Export configuration"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:225
|
||||||
|
msgid "_Save"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:233
|
||||||
|
msgid "Import configuration"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:269
|
||||||
|
msgid "gKeyMapper – Logitech G910"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:277
|
||||||
|
msgid "Export configuration..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:278
|
||||||
|
msgid "Import configuration..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:281
|
||||||
|
msgid "About"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:305
|
||||||
|
msgid "G1 to G9 of the Logitech G910 remapped to keys or commands"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:327
|
||||||
|
msgid "G-Key"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:327
|
||||||
|
msgid "Type"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:327
|
||||||
|
msgid "Target (Key/Command)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:327
|
||||||
|
msgid "Action"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:335
|
||||||
|
msgid "Key"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:335
|
||||||
|
msgid "Command"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:335
|
||||||
|
msgid "Disabled"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:358
|
||||||
|
msgid "e.g. ctrl+c or ls -la"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:378
|
||||||
|
msgid "Save mappings"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/main.cpp:383
|
||||||
|
msgid "Saved to ~/.config/gKeyMapper/mappings.conf"
|
||||||
|
msgstr ""
|
||||||
471
src/main.cpp
Normal file
471
src/main.cpp
Normal file
@@ -0,0 +1,471 @@
|
|||||||
|
// gKeyMapper - GTK4 GUI for remapping the G keys (G1-G9) of the Logitech G910
|
||||||
|
// GUI only for now. Mappings are stored as a simple text file.
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <locale.h>
|
||||||
|
#include <libintl.h>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#ifndef PACKAGE
|
||||||
|
#define PACKAGE "gkeymapper"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LOCALEDIR
|
||||||
|
#define LOCALEDIR "/usr/local/share/locale"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define _(s) gettext(s)
|
||||||
|
#define N_(s) (s)
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
constexpr int NUM_KEYS = 9;
|
||||||
|
|
||||||
|
struct KeyRow {
|
||||||
|
int index; // 0..8 -> G1..G9
|
||||||
|
GtkWidget* keyLabel = nullptr;
|
||||||
|
GtkWidget* typeDrop = nullptr;
|
||||||
|
GtkWidget* targetEntry = nullptr;
|
||||||
|
GtkWidget* captureButton = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<KeyRow> rows;
|
||||||
|
|
||||||
|
static void on_pick_file_response(GtkDialog* dialog, int response, gpointer userData) {
|
||||||
|
if (response == GTK_RESPONSE_ACCEPT) {
|
||||||
|
KeyRow* row = static_cast<KeyRow*>(userData);
|
||||||
|
GtkFileChooser* chooser = GTK_FILE_CHOOSER(dialog);
|
||||||
|
g_autoptr(GFile) file = gtk_file_chooser_get_file(chooser);
|
||||||
|
char* path = g_file_get_path(file);
|
||||||
|
if (path) {
|
||||||
|
gtk_editable_set_text(GTK_EDITABLE(row->targetEntry), path);
|
||||||
|
g_free(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gtk_window_destroy(GTK_WINDOW(dialog));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pick_command_file(KeyRow* row, GtkWindow* parent) {
|
||||||
|
GtkWidget* dialog = gtk_file_chooser_dialog_new(_("Choose file"),
|
||||||
|
parent,
|
||||||
|
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||||
|
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
||||||
|
_("_Open"), GTK_RESPONSE_ACCEPT,
|
||||||
|
NULL);
|
||||||
|
g_signal_connect(dialog, "response", G_CALLBACK(on_pick_file_response), row);
|
||||||
|
gtk_window_present(GTK_WINDOW(dialog));
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_capture_clicked(GtkButton* btn, gpointer userData) {
|
||||||
|
auto* row = static_cast<KeyRow*>(userData);
|
||||||
|
guint sel = gtk_drop_down_get_selected(GTK_DROP_DOWN(row->typeDrop));
|
||||||
|
|
||||||
|
if (sel == 1) {
|
||||||
|
GtkWindow* window = GTK_WINDOW(gtk_widget_get_root(GTK_WIDGET(btn)));
|
||||||
|
pick_command_file(row, window);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sel == 0) {
|
||||||
|
// Placeholder: real key capture will be added in a later version.
|
||||||
|
gtk_editable_set_text(GTK_EDITABLE(row->targetEntry), _("<Press a key...>"));
|
||||||
|
std::cout << "G" << (row->index + 1) << ": waiting for key...\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_row_state(KeyRow* row) {
|
||||||
|
guint sel = gtk_drop_down_get_selected(GTK_DROP_DOWN(row->typeDrop));
|
||||||
|
gboolean enabled = (sel != 2);
|
||||||
|
gtk_widget_set_sensitive(row->targetEntry, enabled);
|
||||||
|
gtk_widget_set_sensitive(row->captureButton, enabled);
|
||||||
|
|
||||||
|
if (sel == 1) {
|
||||||
|
gtk_button_set_label(GTK_BUTTON(row->captureButton), _("Choose file..."));
|
||||||
|
} else {
|
||||||
|
gtk_button_set_label(GTK_BUTTON(row->captureButton), _("Capture"));
|
||||||
|
}
|
||||||
|
gtk_widget_set_size_request(row->captureButton, 180, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_type_changed(GObject* /*object*/, GParamSpec* /*pspec*/, gpointer userData) {
|
||||||
|
update_row_state(static_cast<KeyRow*>(userData));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool write_mappings_to_file(const std::string& path) {
|
||||||
|
std::ofstream out(path);
|
||||||
|
if (!out) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
out << "# gKeyMapper mappings (G1..G9)\n";
|
||||||
|
for (const auto& row : rows) {
|
||||||
|
const char* type = "disabled";
|
||||||
|
switch (gtk_drop_down_get_selected(GTK_DROP_DOWN(row.typeDrop))) {
|
||||||
|
case 0: type = "key"; break;
|
||||||
|
case 1: type = "command"; break;
|
||||||
|
default: type = "disabled"; break;
|
||||||
|
}
|
||||||
|
const char* target = gtk_editable_get_text(GTK_EDITABLE(row.targetEntry));
|
||||||
|
out << "G" << (row.index + 1) << "=" << type << ":" << (target ? target : "") << "\n";
|
||||||
|
}
|
||||||
|
out.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_save_clicked(GtkButton* /*btn*/, gpointer /*userData*/) {
|
||||||
|
const char* home = g_get_home_dir();
|
||||||
|
std::string dir = std::string(home) + "/.config/gKeyMapper";
|
||||||
|
g_mkdir_with_parents(dir.c_str(), 0755);
|
||||||
|
std::string path = dir + "/mappings.conf";
|
||||||
|
|
||||||
|
if (!write_mappings_to_file(path)) {
|
||||||
|
g_printerr(_("Could not save %s.\n"), path.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << _("Mappings saved to ") << path << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void import_mappings_from_file(const std::string& path) {
|
||||||
|
std::ifstream in(path);
|
||||||
|
if (!in) {
|
||||||
|
g_printerr(_("Could not open %s.\n"), path.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(in, line)) {
|
||||||
|
if (line.empty() || line[0] == '#') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto eq = line.find('=');
|
||||||
|
if (eq == std::string::npos) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::string key = line.substr(0, eq);
|
||||||
|
if (key.size() < 2 || key[0] != 'G') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int n = 0;
|
||||||
|
try {
|
||||||
|
n = std::stoi(key.substr(1)) - 1;
|
||||||
|
} catch (...) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (n < 0 || n >= (int)rows.size()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string rest = line.substr(eq + 1);
|
||||||
|
auto col = rest.find(':');
|
||||||
|
std::string typeToken = (col == std::string::npos) ? rest : rest.substr(0, col);
|
||||||
|
std::string target = (col == std::string::npos) ? std::string() : rest.substr(col + 1);
|
||||||
|
|
||||||
|
guint idx = 2;
|
||||||
|
if (typeToken == "key") {
|
||||||
|
idx = 0;
|
||||||
|
} else if (typeToken == "command") {
|
||||||
|
idx = 1;
|
||||||
|
} else if (typeToken == "disabled") {
|
||||||
|
idx = 2;
|
||||||
|
}
|
||||||
|
gtk_drop_down_set_selected(GTK_DROP_DOWN(rows[n].typeDrop), idx);
|
||||||
|
gtk_editable_set_text(GTK_EDITABLE(rows[n].targetEntry), target.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_export_response(GtkDialog* dialog, int response, gpointer /*userData*/) {
|
||||||
|
if (response == GTK_RESPONSE_ACCEPT) {
|
||||||
|
GtkFileChooser* chooser = GTK_FILE_CHOOSER(dialog);
|
||||||
|
g_autoptr(GFile) file = gtk_file_chooser_get_file(chooser);
|
||||||
|
char* path = g_file_get_path(file);
|
||||||
|
if (path) {
|
||||||
|
if (!write_mappings_to_file(path)) {
|
||||||
|
g_printerr(_("Could not export mappings.\n"));
|
||||||
|
}
|
||||||
|
g_free(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gtk_window_destroy(GTK_WINDOW(dialog));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_import_response(GtkDialog* dialog, int response, gpointer /*userData*/) {
|
||||||
|
if (response == GTK_RESPONSE_ACCEPT) {
|
||||||
|
GtkFileChooser* chooser = GTK_FILE_CHOOSER(dialog);
|
||||||
|
g_autoptr(GFile) file = gtk_file_chooser_get_file(chooser);
|
||||||
|
char* path = g_file_get_path(file);
|
||||||
|
if (path) {
|
||||||
|
import_mappings_from_file(path);
|
||||||
|
g_free(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gtk_window_destroy(GTK_WINDOW(dialog));
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string find_asset(const std::string& name);
|
||||||
|
|
||||||
|
static void show_about_dialog(GtkWindow* parent) {
|
||||||
|
GtkWidget* dialog = gtk_about_dialog_new();
|
||||||
|
gtk_about_dialog_set_program_name(GTK_ABOUT_DIALOG(dialog), _("gKeyMapper"));
|
||||||
|
gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(dialog), "0.1.0");
|
||||||
|
gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(dialog),
|
||||||
|
_("G-Key mapper for the Logitech G910 (GTK4)."));
|
||||||
|
gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(dialog), "https://rager.dev");
|
||||||
|
gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(dialog), "rager.dev");
|
||||||
|
|
||||||
|
std::string iconPath = find_asset("icon.png");
|
||||||
|
GError* error = nullptr;
|
||||||
|
GdkTexture* texture = gdk_texture_new_from_filename(iconPath.c_str(), &error);
|
||||||
|
if (texture) {
|
||||||
|
gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(dialog), GDK_PAINTABLE(texture));
|
||||||
|
g_object_unref(texture);
|
||||||
|
} else if (error) {
|
||||||
|
g_printerr("Could not load icon: %s\n", error->message);
|
||||||
|
g_error_free(error);
|
||||||
|
}
|
||||||
|
gtk_window_set_transient_for(GTK_WINDOW(dialog), parent);
|
||||||
|
g_signal_connect(dialog, "response", G_CALLBACK(gtk_window_destroy), NULL);
|
||||||
|
gtk_window_present(GTK_WINDOW(dialog));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_export(GtkWindow* parent) {
|
||||||
|
GtkWidget* dialog = gtk_file_chooser_dialog_new(_("Export configuration"),
|
||||||
|
parent,
|
||||||
|
GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||||
|
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
||||||
|
_("_Save"), GTK_RESPONSE_ACCEPT,
|
||||||
|
NULL);
|
||||||
|
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), "gkeymapper.conf");
|
||||||
|
g_signal_connect(dialog, "response", G_CALLBACK(on_export_response), NULL);
|
||||||
|
gtk_window_present(GTK_WINDOW(dialog));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_import(GtkWindow* parent) {
|
||||||
|
GtkWidget* dialog = gtk_file_chooser_dialog_new(_("Import configuration"),
|
||||||
|
parent,
|
||||||
|
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||||
|
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
||||||
|
_("_Open"), GTK_RESPONSE_ACCEPT,
|
||||||
|
NULL);
|
||||||
|
g_signal_connect(dialog, "response", G_CALLBACK(on_import_response), NULL);
|
||||||
|
gtk_window_present(GTK_WINDOW(dialog));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void action_export(GSimpleAction* /*action*/, GVariant* /*parameter*/, gpointer userData) {
|
||||||
|
GtkApplication* app = GTK_APPLICATION(userData);
|
||||||
|
GtkWindow* window = gtk_application_get_active_window(app);
|
||||||
|
if (window) {
|
||||||
|
do_export(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void action_import(GSimpleAction* /*action*/, GVariant* /*parameter*/, gpointer userData) {
|
||||||
|
GtkApplication* app = GTK_APPLICATION(userData);
|
||||||
|
GtkWindow* window = gtk_application_get_active_window(app);
|
||||||
|
if (window) {
|
||||||
|
do_import(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void action_about(GSimpleAction* /*action*/, GVariant* /*parameter*/, gpointer userData) {
|
||||||
|
GtkApplication* app = GTK_APPLICATION(userData);
|
||||||
|
GtkWindow* window = gtk_application_get_active_window(app);
|
||||||
|
if (window) {
|
||||||
|
show_about_dialog(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string find_asset(const std::string& name) {
|
||||||
|
const char* env = g_getenv("GKEYMAPPER_ASSETS_DIR");
|
||||||
|
if (env && *env) {
|
||||||
|
std::string path = std::string(env) + "/" + name;
|
||||||
|
if (g_file_test(path.c_str(), G_FILE_TEST_EXISTS)) {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string local = std::string("./assets/") + name;
|
||||||
|
if (g_file_test(local.c_str(), G_FILE_TEST_EXISTS)) {
|
||||||
|
return local;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef ASSETS_DIR
|
||||||
|
#define ASSETS_DIR "/usr/local/share/gkeymapper/assets"
|
||||||
|
#endif
|
||||||
|
std::string installed = std::string(ASSETS_DIR) + "/" + name;
|
||||||
|
if (g_file_test(installed.c_str(), G_FILE_TEST_EXISTS)) {
|
||||||
|
return installed;
|
||||||
|
}
|
||||||
|
return local;
|
||||||
|
}
|
||||||
|
|
||||||
|
void build_ui(GtkApplication* app) {
|
||||||
|
GtkWidget* window = gtk_application_window_new(app);
|
||||||
|
gtk_window_set_title(GTK_WINDOW(window), _("gKeyMapper – Logitech G910"));
|
||||||
|
gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
|
||||||
|
|
||||||
|
GtkWidget* headerBar = gtk_header_bar_new();
|
||||||
|
gtk_window_set_titlebar(GTK_WINDOW(window), headerBar);
|
||||||
|
gtk_window_set_icon_name(GTK_WINDOW(window), "gkeymapper");
|
||||||
|
|
||||||
|
GtkWidget* titleBox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
|
||||||
|
GtkWidget* iconImage = gtk_image_new_from_file(find_asset("icon.png").c_str());
|
||||||
|
gtk_image_set_pixel_size(GTK_IMAGE(iconImage), 24);
|
||||||
|
gtk_box_append(GTK_BOX(titleBox), iconImage);
|
||||||
|
gtk_box_append(GTK_BOX(titleBox), gtk_label_new(_("gKeyMapper")));
|
||||||
|
gtk_header_bar_set_title_widget(GTK_HEADER_BAR(headerBar), titleBox);
|
||||||
|
|
||||||
|
GMenu* menu = g_menu_new();
|
||||||
|
g_menu_append(menu, _("Export configuration..."), "app.export-config");
|
||||||
|
g_menu_append(menu, _("Import configuration..."), "app.import-config");
|
||||||
|
|
||||||
|
GMenu* helpSection = g_menu_new();
|
||||||
|
g_menu_append(helpSection, _("About"), "app.about");
|
||||||
|
g_menu_append_section(menu, NULL, G_MENU_MODEL(helpSection));
|
||||||
|
|
||||||
|
GtkWidget* menuButton = gtk_menu_button_new();
|
||||||
|
gtk_menu_button_set_icon_name(GTK_MENU_BUTTON(menuButton), "open-menu-symbolic");
|
||||||
|
gtk_menu_button_set_menu_model(GTK_MENU_BUTTON(menuButton), G_MENU_MODEL(menu));
|
||||||
|
gtk_header_bar_pack_end(GTK_HEADER_BAR(headerBar), menuButton);
|
||||||
|
|
||||||
|
GtkWidget* outer = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||||
|
gtk_window_set_child(GTK_WINDOW(window), outer);
|
||||||
|
|
||||||
|
// Title / subtitle
|
||||||
|
GtkWidget* headerBox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 2);
|
||||||
|
gtk_widget_set_margin_top(headerBox, 16);
|
||||||
|
gtk_widget_set_margin_bottom(headerBox, 8);
|
||||||
|
gtk_widget_set_margin_start(headerBox, 16);
|
||||||
|
gtk_widget_set_margin_end(headerBox, 16);
|
||||||
|
gtk_box_append(GTK_BOX(outer), headerBox);
|
||||||
|
|
||||||
|
GtkWidget* title = gtk_label_new(nullptr);
|
||||||
|
gtk_label_set_markup(GTK_LABEL(title), "<span size='x-large' weight='bold'>G-Key Mapper</span>");
|
||||||
|
gtk_label_set_xalign(GTK_LABEL(title), 0.0f);
|
||||||
|
gtk_box_append(GTK_BOX(headerBox), title);
|
||||||
|
|
||||||
|
GtkWidget* subtitle = gtk_label_new(_("G1 to G9 of the Logitech G910 remapped to keys or commands"));
|
||||||
|
gtk_label_set_xalign(GTK_LABEL(subtitle), 0.0f);
|
||||||
|
gtk_widget_add_css_class(subtitle, "dim-label");
|
||||||
|
gtk_box_append(GTK_BOX(headerBox), subtitle);
|
||||||
|
|
||||||
|
// Table with all nine G keys (no scrolling needed, everything stays visible)
|
||||||
|
GtkWidget* grid = gtk_grid_new();
|
||||||
|
gtk_grid_set_row_spacing(GTK_GRID(grid), 6);
|
||||||
|
gtk_grid_set_column_spacing(GTK_GRID(grid), 8);
|
||||||
|
gtk_widget_set_margin_top(grid, 8);
|
||||||
|
gtk_widget_set_margin_bottom(grid, 4);
|
||||||
|
gtk_widget_set_margin_start(grid, 16);
|
||||||
|
gtk_widget_set_margin_end(grid, 16);
|
||||||
|
gtk_widget_set_hexpand(grid, TRUE);
|
||||||
|
gtk_box_append(GTK_BOX(outer), grid);
|
||||||
|
|
||||||
|
// Column headers
|
||||||
|
const char* headers[] = { _("G-Key"), _("Type"), _("Target (Key/Command)"), _("Action") };
|
||||||
|
for (int c = 0; c < 4; ++c) {
|
||||||
|
GtkWidget* h = gtk_label_new(headers[c]);
|
||||||
|
gtk_label_set_markup(GTK_LABEL(h), g_strdup_printf("<b>%s</b>", headers[c]));
|
||||||
|
gtk_widget_add_css_class(h, "dim-label");
|
||||||
|
gtk_grid_attach(GTK_GRID(grid), h, c, 0, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* typeOptions[] = { _("Key"), _("Command"), _("Disabled"), nullptr };
|
||||||
|
|
||||||
|
rows.resize(NUM_KEYS);
|
||||||
|
for (int i = 0; i < NUM_KEYS; ++i) {
|
||||||
|
rows[i].index = i;
|
||||||
|
|
||||||
|
// G key label
|
||||||
|
GtkWidget* keyLabel = gtk_label_new(g_strdup_printf("G%d", i + 1));
|
||||||
|
gtk_label_set_markup(GTK_LABEL(keyLabel), g_strdup_printf("<b>G%d</b>", i + 1));
|
||||||
|
gtk_grid_attach(GTK_GRID(grid), keyLabel, 0, i + 1, 1, 1);
|
||||||
|
rows[i].keyLabel = keyLabel;
|
||||||
|
|
||||||
|
// Type dropdown (fixed width so rows don't jump between languages)
|
||||||
|
GtkWidget* drop = gtk_drop_down_new_from_strings(typeOptions);
|
||||||
|
gtk_drop_down_set_selected(GTK_DROP_DOWN(drop), 0);
|
||||||
|
gtk_widget_set_size_request(drop, 150, -1);
|
||||||
|
gtk_grid_attach(GTK_GRID(grid), drop, 1, i + 1, 1, 1);
|
||||||
|
rows[i].typeDrop = drop;
|
||||||
|
|
||||||
|
g_signal_connect(drop, "notify::selected", G_CALLBACK(on_type_changed), &rows[i]);
|
||||||
|
|
||||||
|
// Target input (wide: commands and file paths need room)
|
||||||
|
GtkWidget* entry = gtk_entry_new();
|
||||||
|
gtk_entry_set_placeholder_text(GTK_ENTRY(entry), _("e.g. ctrl+c or ls -la"));
|
||||||
|
gtk_widget_set_size_request(entry, 440, -1);
|
||||||
|
gtk_widget_set_hexpand(entry, TRUE);
|
||||||
|
gtk_grid_attach(GTK_GRID(grid), entry, 2, i + 1, 1, 1);
|
||||||
|
rows[i].targetEntry = entry;
|
||||||
|
|
||||||
|
// Capture button
|
||||||
|
GtkWidget* capture = gtk_button_new_with_label(_("Capture"));
|
||||||
|
gtk_widget_set_size_request(capture, 180, -1);
|
||||||
|
g_signal_connect(capture, "clicked", G_CALLBACK(on_capture_clicked), &rows[i]);
|
||||||
|
gtk_grid_attach(GTK_GRID(grid), capture, 3, i + 1, 1, 1);
|
||||||
|
rows[i].captureButton = capture;
|
||||||
|
|
||||||
|
update_row_state(&rows[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Footer with save button
|
||||||
|
GtkWidget* footer = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
|
||||||
|
gtk_widget_set_margin_top(footer, 8);
|
||||||
|
gtk_widget_set_margin_bottom(footer, 16);
|
||||||
|
gtk_widget_set_margin_start(footer, 16);
|
||||||
|
gtk_widget_set_margin_end(footer, 16);
|
||||||
|
gtk_box_append(GTK_BOX(outer), footer);
|
||||||
|
|
||||||
|
GtkWidget* saveBtn = gtk_button_new_with_label(_("Save mappings"));
|
||||||
|
gtk_widget_add_css_class(saveBtn, "suggested-action");
|
||||||
|
g_signal_connect(saveBtn, "clicked", G_CALLBACK(on_save_clicked), nullptr);
|
||||||
|
gtk_box_append(GTK_BOX(footer), saveBtn);
|
||||||
|
|
||||||
|
GtkWidget* hint = gtk_label_new(_("Saved to ~/.config/gKeyMapper/mappings.conf"));
|
||||||
|
gtk_widget_add_css_class(hint, "dim-label");
|
||||||
|
gtk_widget_set_halign(hint, GTK_ALIGN_END);
|
||||||
|
gtk_widget_set_hexpand(hint, TRUE);
|
||||||
|
gtk_box_append(GTK_BOX(footer), hint);
|
||||||
|
|
||||||
|
gtk_window_present(GTK_WINDOW(window));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_activate(GtkApplication* app, gpointer /*user_data*/) {
|
||||||
|
GSimpleAction* exportAction = g_simple_action_new("export-config", NULL);
|
||||||
|
g_signal_connect(exportAction, "activate", G_CALLBACK(action_export), app);
|
||||||
|
g_action_map_add_action(G_ACTION_MAP(app), G_ACTION(exportAction));
|
||||||
|
|
||||||
|
GSimpleAction* importAction = g_simple_action_new("import-config", NULL);
|
||||||
|
g_signal_connect(importAction, "activate", G_CALLBACK(action_import), app);
|
||||||
|
g_action_map_add_action(G_ACTION_MAP(app), G_ACTION(importAction));
|
||||||
|
|
||||||
|
GSimpleAction* aboutAction = g_simple_action_new("about", NULL);
|
||||||
|
g_signal_connect(aboutAction, "activate", G_CALLBACK(action_about), app);
|
||||||
|
g_action_map_add_action(G_ACTION_MAP(app), G_ACTION(aboutAction));
|
||||||
|
|
||||||
|
build_ui(app);
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
setlocale(LC_ALL, "");
|
||||||
|
|
||||||
|
const char* localedir = g_getenv("GKEYMAPPER_LOCALEDIR");
|
||||||
|
if (!localedir || !*localedir) {
|
||||||
|
localedir = LOCALEDIR;
|
||||||
|
}
|
||||||
|
bindtextdomain(PACKAGE, localedir);
|
||||||
|
bind_textdomain_codeset(PACKAGE, "UTF-8");
|
||||||
|
textdomain(PACKAGE);
|
||||||
|
|
||||||
|
GtkApplication* app = gtk_application_new("com.example.gkeymapper",
|
||||||
|
G_APPLICATION_FLAGS_NONE);
|
||||||
|
g_signal_connect(app, "activate", G_CALLBACK(on_activate), nullptr);
|
||||||
|
int status = g_application_run(G_APPLICATION(app), argc, argv);
|
||||||
|
g_object_unref(app);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user