|
21 | 21 | #include <QDebug> |
22 | 22 | #include <QStringList> |
23 | 23 | #include <QString> |
| 24 | +#include <QFile> |
| 25 | +#include <QDir> |
| 26 | +#include <QStandardPaths> |
| 27 | +#include <QSettings> |
24 | 28 |
|
25 | 29 | #include "PlatformConfig.h" |
26 | 30 | #include "Log.h" |
@@ -210,11 +214,216 @@ void setupGnomeIME() { |
210 | 214 | } |
211 | 215 |
|
212 | 216 |
|
| 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 | + |
213 | 420 | void setupInputSources() { |
214 | 421 | auto de = detectDesktopEnvironment(); |
215 | 422 |
|
216 | 423 | if(de == DesktopEnvironment::GNOME) { |
217 | 424 | setupGnomeIME(); |
| 425 | + } else if(de == DesktopEnvironment::KDE) { |
| 426 | + setupKdeIME(); |
218 | 427 | } else if(de == DesktopEnvironment::macOS) { |
219 | 428 | #ifdef Q_OS_MACOS |
220 | 429 | bool enabled = macOS::getInputSourceEnabled(); |
|
0 commit comments