Skip to content

Commit c6a16c8

Browse files
committed
Implement auto-config for KDE Fcitx
1 parent ce8b378 commit c6a16c8

File tree

1 file changed

+209
-0
lines changed

1 file changed

+209
-0
lines changed

src/frontend/PlatformConfig.cpp

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
#include <QDebug>
2222
#include <QStringList>
2323
#include <QString>
24+
#include <QFile>
25+
#include <QDir>
26+
#include <QStandardPaths>
27+
#include <QSettings>
2428

2529
#include "PlatformConfig.h"
2630
#include "Log.h"
@@ -210,11 +214,216 @@ void setupGnomeIME() {
210214
}
211215

212216

217+
QString findFcitx5WaylandLauncher() {
218+
QStringList candidates = {
219+
"/usr/share/applications/fcitx5-wayland-launcher.desktop",
220+
"/usr/local/share/applications/fcitx5-wayland-launcher.desktop",
221+
};
222+
223+
// Also check XDG data dirs
224+
QString xdgDataDirs = QProcessEnvironment::systemEnvironment().value("XDG_DATA_DIRS", "/usr/share:/usr/local/share");
225+
for (const auto &dir : xdgDataDirs.split(':')) {
226+
QString path = dir + "/applications/fcitx5-wayland-launcher.desktop";
227+
if (!candidates.contains(path)) {
228+
candidates.append(path);
229+
}
230+
}
231+
232+
for (const auto &path : candidates) {
233+
if (QFile::exists(path)) {
234+
return path;
235+
}
236+
}
237+
238+
return "";
239+
}
240+
241+
void setupKdeVirtualKeyboard() {
242+
QString launcherPath = findFcitx5WaylandLauncher();
243+
if (launcherPath.isEmpty()) {
244+
LOG_DEBUG("Fcitx5 Wayland launcher desktop file not found\n");
245+
return;
246+
}
247+
248+
// Read current virtual keyboard setting
249+
QProcess readProcess;
250+
readProcess.start("kreadconfig6", {"--file", "kwinrc", "--group", "Wayland", "--key", "InputMethod"});
251+
readProcess.waitForFinished();
252+
253+
QString currentValue = readProcess.readAllStandardOutput().trimmed();
254+
255+
if (currentValue == launcherPath) {
256+
LOG_DEBUG("KDE virtual keyboard already set to Fcitx5\n");
257+
return;
258+
}
259+
260+
// Set Fcitx5 as the virtual keyboard
261+
QProcess writeProcess;
262+
writeProcess.start("kwriteconfig6", {"--file", "kwinrc", "--group", "Wayland", "--key", "InputMethod", launcherPath});
263+
writeProcess.waitForFinished();
264+
265+
if (writeProcess.exitCode() == 0) {
266+
LOG_DEBUG("Set KDE virtual keyboard to Fcitx5: %s\n", launcherPath.toStdString().c_str());
267+
} else {
268+
LOG_ERROR("Failed to set KDE virtual keyboard: %s\n", writeProcess.readAllStandardError().toStdString().c_str());
269+
}
270+
}
271+
272+
bool addOpenBanglaToFcitx5ViaDBus() {
273+
// Get current input method group info
274+
QProcess getProcess;
275+
getProcess.start("gdbus", {"call", "--session",
276+
"--dest", "org.fcitx.Fcitx5",
277+
"--object-path", "/controller",
278+
"--method", "org.fcitx.Fcitx.Controller1.InputMethodGroupInfo",
279+
"Default"});
280+
getProcess.waitForFinished();
281+
282+
if (getProcess.exitCode() != 0) {
283+
return false;
284+
}
285+
286+
// Output format: ('us', [('keyboard-us', ''), ('openbangla', '')])
287+
QString output = getProcess.readAllStandardOutput().trimmed();
288+
289+
if (output.contains("'openbangla'")) {
290+
LOG_DEBUG("OpenBangla already in Fcitx5 input method group\n");
291+
return true;
292+
}
293+
294+
// Parse the default layout from the output
295+
// Format: ('layout', [...])
296+
QString defaultLayout = "us";
297+
int firstQuote = output.indexOf('\'');
298+
int secondQuote = output.indexOf('\'', firstQuote + 1);
299+
if (firstQuote >= 0 && secondQuote > firstQuote) {
300+
defaultLayout = output.mid(firstQuote + 1, secondQuote - firstQuote - 1);
301+
}
302+
303+
// Parse the existing input methods array
304+
// We need to reconstruct the array with openbangla added
305+
int arrayStart = output.indexOf('[');
306+
int arrayEnd = output.lastIndexOf(']');
307+
QString existingArray;
308+
if (arrayStart >= 0 && arrayEnd > arrayStart) {
309+
existingArray = output.mid(arrayStart, arrayEnd - arrayStart + 1);
310+
}
311+
312+
// Build new array: insert openbangla before the closing bracket
313+
QString newArray;
314+
if (existingArray.isEmpty() || existingArray == "[]") {
315+
newArray = "[('keyboard-us', ''), ('openbangla', '')]";
316+
} else {
317+
// Remove trailing ] and add openbangla
318+
newArray = existingArray.left(existingArray.length() - 1) + ", ('openbangla', '')]";
319+
}
320+
321+
QProcess setProcess;
322+
setProcess.start("gdbus", {"call", "--session",
323+
"--dest", "org.fcitx.Fcitx5",
324+
"--object-path", "/controller",
325+
"--method", "org.fcitx.Fcitx.Controller1.SetInputMethodGroupInfo",
326+
"Default", defaultLayout, newArray});
327+
setProcess.waitForFinished();
328+
329+
if (setProcess.exitCode() == 0) {
330+
LOG_DEBUG("Added OpenBangla to Fcitx5 input method group via DBus\n");
331+
return true;
332+
}
333+
334+
LOG_ERROR("Failed to add OpenBangla via DBus: %s\n", setProcess.readAllStandardError().toStdString().c_str());
335+
return false;
336+
}
337+
338+
void addOpenBanglaToFcitx5Profile() {
339+
QString profilePath = QDir::homePath() + "/.config/fcitx5/profile";
340+
341+
// Ensure the directory exists
342+
QDir().mkpath(QDir::homePath() + "/.config/fcitx5");
343+
344+
if (QFile::exists(profilePath)) {
345+
// Read existing profile and check if openbangla is already present
346+
QSettings profile(profilePath, QSettings::IniFormat);
347+
348+
// Scan existing groups for openbangla
349+
int itemCount = 0;
350+
bool found = false;
351+
352+
for (const auto &group : profile.childGroups()) {
353+
if (group.startsWith("Groups/0/Items/")) {
354+
itemCount++;
355+
profile.beginGroup(group);
356+
if (profile.value("Name").toString() == "openbangla") {
357+
found = true;
358+
}
359+
profile.endGroup();
360+
}
361+
}
362+
363+
if (found) {
364+
LOG_DEBUG("OpenBangla already in Fcitx5 profile\n");
365+
return;
366+
}
367+
368+
// Add openbangla as the next item
369+
QString newGroup = QString("Groups/0/Items/%1").arg(itemCount);
370+
profile.beginGroup(newGroup);
371+
profile.setValue("Name", "openbangla");
372+
profile.setValue("Layout", "");
373+
profile.endGroup();
374+
profile.sync();
375+
376+
LOG_DEBUG("Added OpenBangla to existing Fcitx5 profile\n");
377+
} else {
378+
// Create a new profile with keyboard-us and openbangla
379+
QSettings profile(profilePath, QSettings::IniFormat);
380+
381+
profile.beginGroup("Groups/0");
382+
profile.setValue("Name", "Default");
383+
profile.setValue("Default Layout", "us");
384+
profile.setValue("DefaultIM", "openbangla");
385+
profile.endGroup();
386+
387+
profile.beginGroup("Groups/0/Items/0");
388+
profile.setValue("Name", "keyboard-us");
389+
profile.setValue("Layout", "");
390+
profile.endGroup();
391+
392+
profile.beginGroup("Groups/0/Items/1");
393+
profile.setValue("Name", "openbangla");
394+
profile.setValue("Layout", "");
395+
profile.endGroup();
396+
397+
profile.beginGroup("GroupOrder");
398+
profile.setValue("0", "Default");
399+
profile.endGroup();
400+
401+
profile.sync();
402+
403+
LOG_DEBUG("Created new Fcitx5 profile with OpenBangla\n");
404+
}
405+
}
406+
407+
void setupFcitx5InputMethod() {
408+
// Try DBus first (works when Fcitx5 is already running)
409+
if (!addOpenBanglaToFcitx5ViaDBus()) {
410+
LOG_DEBUG("Fcitx5 DBus not available, writing profile directly\n");
411+
addOpenBanglaToFcitx5Profile();
412+
}
413+
}
414+
415+
void setupKdeIME() {
416+
setupKdeVirtualKeyboard();
417+
setupFcitx5InputMethod();
418+
}
419+
213420
void setupInputSources() {
214421
auto de = detectDesktopEnvironment();
215422

216423
if(de == DesktopEnvironment::GNOME) {
217424
setupGnomeIME();
425+
} else if(de == DesktopEnvironment::KDE) {
426+
setupKdeIME();
218427
} else if(de == DesktopEnvironment::macOS) {
219428
#ifdef Q_OS_MACOS
220429
bool enabled = macOS::getInputSourceEnabled();

0 commit comments

Comments
 (0)