1 /*
2 * SPDX-FileCopyrightText: 2012~2017 CSSlayer <wengxt@gmail.com>
3 * SPDX-FileCopyrightText: 2017~2017 xzhao <i@xuzhao.net>
4 *
5 * SPDX-License-Identifier: LGPL-2.1-or-later
6 */
7
8 #include "mainwindow.h"
9 #include "fcitxqtconfiguifactory.h"
10 #include "fcitxqtcontrollerproxy.h"
11 #include "fcitxqtwatcher.h"
12 #include <QDebug>
13 #include <QLocale>
14 #include <QMessageBox>
15 #include <QPushButton>
16 #include <QWindow>
17 #include <fcitx-utils/i18n.h>
18
19 namespace fcitx {
20
MainWindow(const QString & path,FcitxQtConfigUIWidget * pluginWidget,QWidget * parent)21 MainWindow::MainWindow(const QString &path, FcitxQtConfigUIWidget *pluginWidget,
22 QWidget *parent)
23 : QDialog(parent), path_(path), watcher_(new FcitxQtWatcher(this)),
24 pluginWidget_(pluginWidget), proxy_(0) {
25 setupUi(this);
26 watcher_->setConnection(QDBusConnection::sessionBus());
27 verticalLayout->insertWidget(0, pluginWidget_);
28 buttonBox->button(QDialogButtonBox::Ok)->setText(_("&Ok"));
29 buttonBox->button(QDialogButtonBox::Apply)->setText(_("&Apply"));
30 buttonBox->button(QDialogButtonBox::Reset)->setText(_("&Reset"));
31 buttonBox->button(QDialogButtonBox::Close)->setText(_("&Close"));
32 buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
33 buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
34 buttonBox->button(QDialogButtonBox::Reset)->setEnabled(false);
35 setWindowIcon(QIcon::fromTheme(pluginWidget_->icon()));
36 setWindowTitle(pluginWidget_->title());
37
38 connect(pluginWidget_, &FcitxQtConfigUIWidget::changed, this,
39 &MainWindow::changed);
40 if (pluginWidget_->asyncSave()) {
41 connect(pluginWidget_, &FcitxQtConfigUIWidget::saveFinished, this,
42 &MainWindow::saveFinished);
43 }
44 connect(pluginWidget_, &FcitxQtConfigUIWidget::saveSubConfig, this,
45 &MainWindow::saveSubConfig);
46 connect(buttonBox, &QDialogButtonBox::clicked, this, &MainWindow::clicked);
47 connect(watcher_, &FcitxQtWatcher::availabilityChanged, this,
48 &MainWindow::availabilityChanged);
49
50 watcher_->watch();
51 }
52
availabilityChanged(bool avail)53 void MainWindow::availabilityChanged(bool avail) {
54 if (!avail) {
55 return;
56 }
57 if (proxy_) {
58 delete proxy_;
59 }
60 proxy_ = new FcitxQtControllerProxy(watcher_->serviceName(),
61 QLatin1String("/controller"),
62 watcher_->connection(), this);
63 }
64
clicked(QAbstractButton * button)65 void MainWindow::clicked(QAbstractButton *button) {
66 QDialogButtonBox::StandardButton standardButton =
67 buttonBox->standardButton(button);
68 if (standardButton == QDialogButtonBox::Apply ||
69 standardButton == QDialogButtonBox::Ok) {
70 if (pluginWidget_->asyncSave())
71 pluginWidget_->setEnabled(false);
72 if (standardButton == QDialogButtonBox::Ok) {
73 closeAfterSave_ = true;
74 }
75 pluginWidget_->save();
76 if (!pluginWidget_->asyncSave())
77 saveFinished();
78 } else if (standardButton == QDialogButtonBox::Close) {
79 qApp->quit();
80 } else if (standardButton == QDialogButtonBox::Reset) {
81 pluginWidget_->load();
82 }
83 }
84
saveFinished()85 void MainWindow::saveFinished() {
86 if (proxy_) {
87 // Pass some arbitrary thing.
88 auto watcher = new QDBusPendingCallWatcher(
89 proxy_->SetConfig(path_, QDBusVariant(0)), this);
90 connect(watcher, &QDBusPendingCallWatcher::finished, this,
91 &MainWindow::saveFinishedPhase2);
92 } else {
93 saveFinishedPhase2(nullptr);
94 }
95 }
96
saveFinishedPhase2(QDBusPendingCallWatcher * watcher)97 void MainWindow::saveFinishedPhase2(QDBusPendingCallWatcher *watcher) {
98 if (watcher) {
99 watcher->deleteLater();
100 }
101 if (pluginWidget_->asyncSave()) {
102 pluginWidget_->setEnabled(true);
103 }
104 if (!watcher || watcher->isError()) {
105 QMessageBox::warning(
106 this, _("Failed to notify Fcitx"),
107 _("Failed to notify Fcitx about the configuration change."));
108 closeAfterSave_ = false;
109 return;
110 }
111 if (closeAfterSave_) {
112 qApp->quit();
113 }
114 }
115
saveSubConfig(const QString & path)116 void MainWindow::saveSubConfig(const QString &path) {
117 if (proxy_) {
118 // Pass some arbitrary thing.
119 proxy_->SetConfig(path, QDBusVariant(0));
120 }
121 }
122
changed(bool changed)123 void MainWindow::changed(bool changed) {
124 buttonBox->button(QDialogButtonBox::Ok)->setEnabled(changed);
125 buttonBox->button(QDialogButtonBox::Apply)->setEnabled(changed);
126 buttonBox->button(QDialogButtonBox::Reset)->setEnabled(changed);
127 }
128
setParentWindow(WId id)129 void MainWindow::setParentWindow(WId id) { wid_ = id; }
130
showEvent(QShowEvent * event)131 void MainWindow::showEvent(QShowEvent *event) {
132 if (!wid_) {
133 return;
134 }
135 setAttribute(Qt::WA_NativeWindow, true);
136 QWindow *subWindow = windowHandle();
137 Q_ASSERT(subWindow);
138
139 QWindow *mainWindow = QWindow::fromWinId(wid_);
140 wid_ = 0;
141 if (!mainWindow) {
142 // foreign windows not supported on all platforms
143 return;
144 }
145 connect(this, &QObject::destroyed, mainWindow, &QObject::deleteLater);
146 subWindow->setTransientParent(mainWindow);
147
148 QDialog::showEvent(event);
149 }
150 } // namespace fcitx
151