Scare Crowe d2ebfd0519 QortalOS Titan 5.60.12
Screw the description like that inbred T3Q
2022-03-05 21:17:59 +05:00

1193 lines
43 KiB
C++

/*
SPDX-FileCopyrightText: 2009 Wang Hoi <zealot.hoi@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
/** @file scim_panel_dbus.cpp
*/
#define KDE_signal signal
#undef QT_NO_STL
#define QT_STL
#define QT_NO_KEYWORDS
#include <config-scim.h>
#include <errno.h>
#include <list>
#include <signal.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <QCoreApplication>
#include <QDBusConnection>
#include <QDBusMessage>
#include <QMutex>
#include <QObject>
#include <QProcess>
#include <QString>
#include <QStringList>
#include <QThread>
#define Uses_C_STDIO
#define Uses_C_STDLIB
#define Uses_SCIM_LOOKUP_TABLE
#define Uses_SCIM_SOCKET
#define Uses_SCIM_TRANSACTION
#define Uses_SCIM_TRANS_COMMANDS
#define Uses_SCIM_CONFIG
#define Uses_SCIM_CONFIG_MODULE
//#define Uses_SCIM_DEBUG
#define Uses_SCIM_HELPER
#define Uses_SCIM_HELPER_MODULE
#define Uses_SCIM_PANEL_AGENT
#define Uses_STL_MAP
#define ENABLE_DEBUG 9
// scim use exceptions and template, so it doesn't work in hidden visibility
#pragma GCC visibility push(default)
#include <scim.h>
#pragma GCC visibility pop
Q_DECLARE_METATYPE(scim::Property)
Q_DECLARE_METATYPE(scim::PanelFactoryInfo)
Q_DECLARE_METATYPE(scim::HelperInfo)
using namespace scim;
// PanelAgent related functions
static bool initialize_panel_agent(const String &config, const String &display, bool resident);
static bool run_panel_agent(void);
static void start_auto_start_helpers(void);
static void slot_transaction_start(void);
static void slot_transaction_end(void);
static void slot_reload_config(void);
static void slot_turn_on(void);
static void slot_turn_off(void);
static void slot_update_screen(int screen);
static void slot_update_spot_location(int x, int y);
static void slot_update_factory_info(const PanelFactoryInfo &info);
static void slot_show_help(const String &help);
static void slot_show_factory_menu(const std::vector<PanelFactoryInfo> &menu);
static void slot_show_preedit_string(void);
static void slot_show_aux_string(void);
static void slot_show_lookup_table(void);
static void slot_hide_preedit_string(void);
static void slot_hide_aux_string(void);
static void slot_hide_lookup_table(void);
static void slot_update_preedit_string(const String &str, const AttributeList &attrs);
static void slot_update_preedit_caret(int caret);
static void slot_update_aux_string(const String &str, const AttributeList &attrs);
static void slot_update_lookup_table(const LookupTable &table);
static void slot_register_properties(const PropertyList &props);
static void slot_update_property(const Property &prop);
static void slot_register_helper_properties(int id, const PropertyList &props);
static void slot_update_helper_property(int id, const Property &prop);
static void slot_register_helper(int id, const HelperInfo &helper);
static void slot_remove_helper(int id);
static void slot_lock(void);
static void slot_unlock(void);
/////////////////////////////////////////////////////////////////////////////
// Declaration of internal variables.
/////////////////////////////////////////////////////////////////////////////
// static bool _ui_initialized = false;
static ConfigModule *_config_module = nullptr;
static ConfigPointer _config;
static std::vector<HelperInfo> _helper_list;
static bool _should_exit = false;
// static bool _panel_is_on = false;
static PanelAgent *_panel_agent = nullptr;
static QList<PanelFactoryInfo> _factory_list;
class PanelAgentThread;
PanelAgentThread *_panel_agent_thread;
class DBusHandler;
DBusHandler *_dbus_handler;
static QMutex _panel_agent_lock;
static QMutex _global_resource_lock;
static QMutex _transaction_lock;
/////////////////////////////////////////////////////////////////////////////
// Implementation of internal functions.
/////////////////////////////////////////////////////////////////////////////
static void ui_config_reload_callback(const ConfigPointer &config)
{
_config = config;
}
static QString AttrList2String(const AttributeList &attr_list)
{
QString result;
for (const Attribute &attr : attr_list) {
int type = (int)attr.get_type();
unsigned int start = attr.get_start();
unsigned int length = attr.get_length();
unsigned int value = attr.get_value();
result += QString("%1:%2:%3:%4;").arg(type).arg(start).arg(length).arg(value);
}
return result;
}
static QVariantList LookupTable2VariantList(const LookupTable &lookup_table)
{
QVariantList result;
QStringList labels;
QStringList candidates;
QStringList attrlist_list;
int current_page_size = lookup_table.get_current_page_size();
for (int i = 0; i < current_page_size; ++i) {
labels << QString::fromStdWString(lookup_table.get_candidate_label(i));
}
for (int i = 0; i < current_page_size; ++i) {
candidates << QString::fromStdWString(lookup_table.get_candidate_in_current_page(i));
attrlist_list << AttrList2String(lookup_table.get_attributes_in_current_page(i));
}
result << labels << candidates << attrlist_list << lookup_table.get_current_page_start()
<< (lookup_table.get_current_page_start() + lookup_table.get_current_page_size() < ((int)lookup_table.number_of_candidates()));
// result << labels << candidates << attrlist_list;
return result;
}
static QString Property2String(const Property &prop)
{
QString result;
int state = 0;
if (prop.active())
state |= SCIM_PROPERTY_ACTIVE;
if (prop.visible())
state |= SCIM_PROPERTY_VISIBLE;
result = QString("%1:%2:%3:%4:%5")
.arg(QString::fromUtf8(prop.get_key().c_str()))
.arg(QString::fromUtf8(prop.get_label().c_str()))
.arg(QString::fromUtf8(prop.get_icon().c_str()))
.arg(QString::fromUtf8(prop.get_tip().c_str()))
.arg(state);
return result;
}
#if 0
static QString
PanelFactoryInfo2String(const PanelFactoryInfo &info)
{
QString result = QString("%1:%2:%3:%4")
.arg(QString::fromUtf8(info.uuid.c_str()))
.arg(QString::fromUtf8(info.name.c_str()))
.arg(QString::fromUtf8(info.icon.c_str()))
.arg(QString::fromUtf8(info.lang.c_str()));
return result;
}
#endif
static QStringList PropertyList2LeafOnlyStringList(const QList<Property> &props)
{
QStringList list;
list.clear();
for (int i = 0; i < props.size(); ++i) {
bool ok = true;
for (int j = 0; j < props.size(); ++j) {
if (props.at(i).is_a_leaf_of(props.at(j))) {
SCIM_DEBUG_MAIN(1) << "Leaf" << props.at(i).get_key() << " " << props.at(j).get_key() << "\n";
ok = false;
}
}
if (ok)
list << Property2String(props.at(i));
}
return list;
}
static int dbus_event_type = QEvent::registerEventType(1988);
class DBusEvent : public QEvent
{
public:
enum SCIM_EVENT_TYPE {
TURN_ON,
TURN_OFF,
UP_SCREEN,
UP_SPOT_LOC,
UP_AUX,
UP_PREEDIT_STR,
UP_PREEDIT_CARET,
UP_LOOKUPTABLE,
UP_LOOKUPTABLE_CURSOR,
UP_FACTORY_INFO,
UP_PROPERTY,
UP_HELPER_PROPERTY,
REG_PROPERTIES,
REG_HELPER_PROPERTIES,
REG_HELPER,
RM_HELPER,
RM_PROPERTY,
SHOW_LOOKUPTABLE,
HIDE_LOOKUPTABLE,
SHOW_PREEDIT,
HIDE_PREEDIT,
SHOW_AUX,
HIDE_AUX,
SHOW_HELP,
SHOW_FACTORY_MENU,
};
DBusEvent(SCIM_EVENT_TYPE t, const QVariantList &arglist = QVariantList())
: QEvent((QEvent::Type)dbus_event_type)
, m_evtype(t)
, m_data(arglist)
{
}
SCIM_EVENT_TYPE scim_event_type() const
{
return m_evtype;
}
const QVariantList &data() const
{
return m_data;
}
private:
SCIM_EVENT_TYPE m_evtype;
QVariantList m_data;
};
class DBusHandler : public QObject
{
Q_OBJECT
public:
explicit DBusHandler(QObject *parent = nullptr)
: QObject(parent)
{
QDBusConnection("scim_panel").connect("", "", "org.kde.impanel", "MovePreeditCaret", this, SLOT(MovePreeditCaret(int)));
QDBusConnection("scim_panel").connect("", "", "org.kde.impanel", "SelectCandidate", this, SLOT(SelectCandidate(int)));
QDBusConnection("scim_panel").connect("", "", "org.kde.impanel", "LookupTablePageUp", this, SLOT(LookupTablePageUp()));
QDBusConnection("scim_panel").connect("", "", "org.kde.impanel", "LookupTablePageDown", this, SLOT(LookupTablePageDown()));
QDBusConnection("scim_panel").connect("", "", "org.kde.impanel", "TriggerProperty", this, SLOT(TriggerProperty(QString)));
QDBusConnection("scim_panel").connect("", "", "org.kde.impanel", "PanelCreated", this, SLOT(PanelCreated()));
QDBusConnection("scim_panel").connect("", "", "org.kde.impanel", "Exit", this, SLOT(Exit()));
QDBusConnection("scim_panel").connect("", "", "org.kde.impanel", "ReloadConfig", this, SLOT(ReloadConfig()));
QDBusConnection("scim_panel").connect("", "", "org.kde.impanel", "Configure", this, SLOT(Configure()));
logo_prop = Property("/Logo", "SCIM", String(SCIM_ICON_DIR) + "/trademark.png", "SCIM Input Method");
show_help_prop = Property("/StartHelp", "Help", "help-about", "About SCIM…");
factory_prop_prefix = QString::fromUtf8("/Factory/");
helper_prop_prefix = QString::fromUtf8("/Helper/");
}
~DBusHandler()
{
}
void setInitialHelpers(const std::vector<HelperInfo> &_helper_list)
{
QList<Property> props;
for (const HelperInfo &info : _helper_list) {
if (((info.option & SCIM_HELPER_STAND_ALONE) != 0) && ((info.option & SCIM_HELPER_AUTO_START) == 0)) {
props << Property(String(helper_prop_prefix.toUtf8().constData()) + info.uuid, info.name, info.icon, info.description);
}
}
if (!props.isEmpty()) {
helper_props_map.insert(0, props);
}
}
public Q_SLOTS:
void MovePreeditCaret(int pos)
{
SCIM_DEBUG_MAIN(1) << Q_FUNC_INFO << pos << "\n";
_panel_agent->move_preedit_caret(pos);
}
void SelectCandidate(int idx)
{
SCIM_DEBUG_MAIN(1) << Q_FUNC_INFO << idx << "\n";
_panel_agent->select_candidate(idx);
}
void LookupTablePageUp()
{
SCIM_DEBUG_MAIN(1) << Q_FUNC_INFO << "\n";
_panel_agent->lookup_table_page_up();
}
void LookupTablePageDown()
{
SCIM_DEBUG_MAIN(1) << Q_FUNC_INFO << "\n";
_panel_agent->lookup_table_page_down();
}
void TriggerProperty(const QString &key)
{
SCIM_DEBUG_MAIN(1) << qPrintable(key) << "\n";
if (key == show_help_prop.get_key().c_str()) {
SCIM_DEBUG_MAIN(1) << "about_to_show_help"
<< "\n";
_panel_agent->request_help();
return;
}
if (key == logo_prop.get_key().c_str()) {
SCIM_DEBUG_MAIN(1) << "about_to_show_factory_menu"
<< "\n";
_panel_agent->request_factory_menu();
return;
}
if (key.startsWith(factory_prop_prefix)) {
QString factory_uuid = key;
factory_uuid.remove(0, factory_prop_prefix.size());
SCIM_DEBUG_MAIN(1) << "about_to_change_factory" << qPrintable(factory_uuid) << "\n";
_panel_agent->change_factory(factory_uuid.toUtf8().constData());
return;
}
if (key.startsWith(helper_prop_prefix)) {
QString helper_uuid = key;
helper_uuid.remove(0, helper_prop_prefix.size());
SCIM_DEBUG_MAIN(1) << "about_to_start_helper" << qPrintable(helper_uuid) << "\n";
_panel_agent->start_helper(helper_uuid.toUtf8().constData());
return;
}
int i = 0;
for (i = 0; i < panel_props.size(); ++i) {
if (panel_props.at(i).get_key() == String(key.toUtf8().constData())) {
break;
}
}
// found one
QStringList list_result;
list_result.clear();
if (i < panel_props.size()) {
for (int j = 0; j < panel_props.size(); ++j) {
if (panel_props.at(j).is_a_leaf_of(panel_props.at(i))) {
list_result << Property2String(panel_props.at(j));
}
}
if (list_result.isEmpty()) {
_panel_agent->trigger_property(key.toUtf8().constData());
} else {
SCIM_DEBUG_MAIN(1) << "ExecMenu" << qPrintable(key) << "\n";
QDBusMessage message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "ExecMenu");
message << list_result;
QDBusConnection("scim_panel").send(message);
}
}
}
void PanelCreated()
{
QDBusMessage message;
QStringList list_result;
list_result.clear();
list_result << Property2String(logo_prop);
list_result << PropertyList2LeafOnlyStringList(panel_props);
for (const QList<Property> &props : std::as_const(helper_props_map)) {
list_result << PropertyList2LeafOnlyStringList(props);
}
list_result << Property2String(show_help_prop);
message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "RegisterProperties");
message << list_result;
QDBusConnection("scim_panel").send(message);
}
void Exit()
{
SCIM_DEBUG_MAIN(1) << Q_FUNC_INFO << "\n";
_panel_agent->exit();
_panel_agent->stop();
exit(1);
}
void ReloadConfig()
{
SCIM_DEBUG_MAIN(1) << Q_FUNC_INFO << "\n";
_panel_agent->reload_config();
if (!_config.null())
_config->reload();
}
void Configure()
{
SCIM_DEBUG_MAIN(1) << Q_FUNC_INFO << "\n";
QProcess::startDetached("scim-setup", QStringList());
}
protected:
bool event(QEvent *e) override
{
QStringList list_result;
QList<Property> prop_list;
if (e->type() == dbus_event_type) {
DBusEvent *ev = (DBusEvent *)e;
QDBusMessage message;
QVariantList data;
switch (ev->scim_event_type()) {
case DBusEvent::TURN_ON:
/*
list_result.clear();
list_result << Property2String(logo_prop);
list_result << PropertyList2LeafOnlyStringList(panel_props);
for(const QList<Property> &props : std::as_const(helper_props_map)) {
list_result << PropertyList2LeafOnlyStringList(props);
}
list_result << Property2String(show_help_prop);
message = QDBusMessage::createSignal("/kimpanel",
"org.kde.kimpanel.inputmethod",
"RegisterProperties");
message << list_result;
QDBusConnection("scim_panel").send(message);
*/
message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "Enable");
message << true;
QDBusConnection("scim_panel").send(message);
break;
case DBusEvent::TURN_OFF:
logo_prop.set_icon(String(SCIM_ICON_DIR) + "/trademark.png");
message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "UpdateProperty");
message << Property2String(logo_prop);
QDBusConnection("scim_panel").send(message);
/*
list_result.clear();
list_result << Property2String(logo_prop);
for (const QList<Property> &prop_list : std::as_const(helper_props_map)) {
list_result << PropertyList2LeafOnlyStringList(prop_list);
}
list_result << Property2String(show_help_prop);
message = QDBusMessage::createSignal("/kimpanel",
"org.kde.kimpanel.inputmethod",
"RegisterProperties");
message << list_result;
QDBusConnection("scim_panel").send(message);
*/
message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "Enable");
message << false;
QDBusConnection("scim_panel").send(message);
break;
case DBusEvent::SHOW_HELP:
message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "ExecDialog");
message << Property2String(Property("/Help", "Help", "", ev->data().at(0).toString().toUtf8().constData()));
QDBusConnection("scim_panel").send(message);
break;
case DBusEvent::SHOW_FACTORY_MENU:
message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "ExecMenu");
// X _factory_list.clear();
list_result.clear();
data = ev->data();
for (const QVariant &v : std::as_const(data)) {
PanelFactoryInfo factory_info = v.value<PanelFactoryInfo>();
// X _factory_list << factory_info;
list_result << Property2String(Property(String(factory_prop_prefix.toUtf8().constData()) + factory_info.uuid,
factory_info.name,
factory_info.icon,
factory_info.lang));
}
message << list_result;
SCIM_DEBUG_MAIN(1) << qPrintable(list_result.join(";")) << "\n";
QDBusConnection("scim_panel").send(message);
break;
case DBusEvent::SHOW_PREEDIT:
message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "ShowPreedit");
message << true;
QDBusConnection("scim_panel").send(message);
break;
case DBusEvent::SHOW_AUX:
message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "ShowAux");
message << true;
QDBusConnection("scim_panel").send(message);
break;
case DBusEvent::SHOW_LOOKUPTABLE:
message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "ShowLookupTable");
message << true;
QDBusConnection("scim_panel").send(message);
break;
case DBusEvent::HIDE_PREEDIT:
message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "ShowPreedit");
message << false;
QDBusConnection("scim_panel").send(message);
break;
case DBusEvent::HIDE_AUX:
message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "ShowAux");
message << false;
QDBusConnection("scim_panel").send(message);
break;
case DBusEvent::HIDE_LOOKUPTABLE:
message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "ShowLookupTable");
message << false;
QDBusConnection("scim_panel").send(message);
break;
case DBusEvent::UP_PROPERTY:
message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "UpdateProperty");
message << Property2String(ev->data().at(0).value<Property>());
QDBusConnection("scim_panel").send(message);
break;
case DBusEvent::UP_LOOKUPTABLE:
message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "UpdateLookupTable");
message << ev->data().at(0).toStringList();
message << ev->data().at(1).toStringList();
message << ev->data().at(2).toStringList();
message << ev->data().at(3).toBool();
message << ev->data().at(4).toBool();
QDBusConnection("scim_panel").send(message);
break;
case DBusEvent::UP_LOOKUPTABLE_CURSOR:
message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "UpdateLookupTableCursor");
message << ev->data().at(0).toInt();
QDBusConnection("scim_panel").send(message);
break;
case DBusEvent::UP_PREEDIT_CARET:
message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "UpdatePreeditCaret");
message << ev->data().at(0).toInt();
QDBusConnection("scim_panel").send(message);
break;
case DBusEvent::UP_PREEDIT_STR:
message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "UpdatePreeditText");
message << ev->data().at(0).toString();
message << ev->data().at(1).toString();
QDBusConnection("scim_panel").send(message);
break;
case DBusEvent::UP_AUX:
message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "UpdateAux");
message << ev->data().at(0).toString();
message << ev->data().at(1).toString();
QDBusConnection("scim_panel").send(message);
break;
case DBusEvent::UP_SPOT_LOC:
message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "UpdateSpotLocation");
message << ev->data().at(0).toInt();
message << ev->data().at(1).toInt();
QDBusConnection("scim_panel").send(message);
break;
case DBusEvent::UP_SCREEN:
message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "UpdateScreen");
message << ev->data().at(0).toInt();
QDBusConnection("scim_panel").send(message);
break;
case DBusEvent::UP_FACTORY_INFO:
SCIM_DEBUG_MAIN(1) << "update factory info\n";
logo_prop.set_icon(ev->data().at(0).value<PanelFactoryInfo>().icon);
message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "UpdateProperty");
message << Property2String(logo_prop);
QDBusConnection("scim_panel").send(message);
break;
case DBusEvent::REG_HELPER:
break;
case DBusEvent::REG_HELPER_PROPERTIES:
helper_props_map.clear();
prop_list.clear();
data = ev->data().at(1).toList();
for (const QVariant &v : std::as_const(data)) {
Property prop = v.value<Property>();
prop_list << prop;
}
helper_props_map.insert(ev->data().at(0).toInt(), prop_list);
list_result.clear();
list_result << Property2String(logo_prop);
list_result << PropertyList2LeafOnlyStringList(panel_props);
for (const QList<Property> &props : std::as_const(helper_props_map)) {
list_result << PropertyList2LeafOnlyStringList(props);
}
list_result << Property2String(show_help_prop);
message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "RegisterProperties");
message << list_result;
QDBusConnection("scim_panel").send(message);
break;
case DBusEvent::REG_PROPERTIES:
panel_props.clear();
data = ev->data();
for (const QVariant &v : std::as_const(data)) {
Property prop = v.value<Property>();
panel_props << prop;
SCIM_DEBUG_MAIN(1) << "REG_PROPERTIES" << qPrintable(Property2String(v.value<Property>())) << "\n";
}
list_result.clear();
list_result << Property2String(logo_prop);
list_result << PropertyList2LeafOnlyStringList(panel_props);
SCIM_DEBUG_MAIN(1) << "SIMPLIFY_PROPS " << panel_props.size() << " " << list_result.size() - 1 << "\n";
for (const QList<Property> &props : std::as_const(helper_props_map)) {
list_result << PropertyList2LeafOnlyStringList(props);
}
list_result << Property2String(show_help_prop);
message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "RegisterProperties");
message << list_result;
QDBusConnection("scim_panel").send(message);
break;
case DBusEvent::RM_HELPER:
helper_props_map.remove(ev->data().at(0).toInt());
list_result.clear();
list_result << Property2String(logo_prop);
list_result << PropertyList2LeafOnlyStringList(panel_props);
for (const QList<Property> &props : std::as_const(helper_props_map)) {
list_result << PropertyList2LeafOnlyStringList(props);
}
list_result << Property2String(show_help_prop);
message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "RegisterProperties");
message << list_result;
QDBusConnection("scim_panel").send(message);
break;
case DBusEvent::RM_PROPERTY:
message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "RemoveProperty");
// message << ev->data().at(0).V();
QDBusConnection("scim_panel").send(message);
break;
default:
message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "ImplementMe");
// message << ev->data().at(0).toInt();
SCIM_DEBUG_MAIN(1) << "Implement me:" << ev->scim_event_type() << "\n";
QDBusConnection("scim_panel").send(message);
break;
}
return true;
}
return QObject::event(e);
}
private:
QList<Property> panel_props;
QMap<int, QList<Property>> helper_props_map;
Property logo_prop;
Property show_help_prop;
QString factory_prop_prefix;
QString helper_prop_prefix;
QStringList cached_panel_props;
};
class PanelAgentThread : public QThread
{
Q_OBJECT
public:
explicit PanelAgentThread(QObject *parent = nullptr)
: QThread(parent)
{
}
~PanelAgentThread()
{
}
void run() override
{
if (!_panel_agent->run())
std::cerr << "Failed to run Panel.\n";
_global_resource_lock.lock();
_should_exit = true;
_global_resource_lock.unlock();
}
};
//////////////////////////////////////////////////////////////////////
// Start of PanelAgent Functions
//////////////////////////////////////////////////////////////////////
static bool initialize_panel_agent(const String &config, const String &display, bool resident)
{
_panel_agent = new PanelAgent();
if (!_panel_agent->initialize(config, display, resident))
return false;
_panel_agent->signal_connect_transaction_start(slot(slot_transaction_start));
_panel_agent->signal_connect_transaction_end(slot(slot_transaction_end));
_panel_agent->signal_connect_reload_config(slot(slot_reload_config));
_panel_agent->signal_connect_turn_on(slot(slot_turn_on));
_panel_agent->signal_connect_turn_off(slot(slot_turn_off));
_panel_agent->signal_connect_update_screen(slot(slot_update_screen));
_panel_agent->signal_connect_update_spot_location(slot(slot_update_spot_location));
_panel_agent->signal_connect_update_factory_info(slot(slot_update_factory_info));
_panel_agent->signal_connect_show_help(slot(slot_show_help));
_panel_agent->signal_connect_show_factory_menu(slot(slot_show_factory_menu));
_panel_agent->signal_connect_show_preedit_string(slot(slot_show_preedit_string));
_panel_agent->signal_connect_show_aux_string(slot(slot_show_aux_string));
_panel_agent->signal_connect_show_lookup_table(slot(slot_show_lookup_table));
_panel_agent->signal_connect_hide_preedit_string(slot(slot_hide_preedit_string));
_panel_agent->signal_connect_hide_aux_string(slot(slot_hide_aux_string));
_panel_agent->signal_connect_hide_lookup_table(slot(slot_hide_lookup_table));
_panel_agent->signal_connect_update_preedit_string(slot(slot_update_preedit_string));
_panel_agent->signal_connect_update_preedit_caret(slot(slot_update_preedit_caret));
_panel_agent->signal_connect_update_aux_string(slot(slot_update_aux_string));
_panel_agent->signal_connect_update_lookup_table(slot(slot_update_lookup_table));
_panel_agent->signal_connect_register_properties(slot(slot_register_properties));
_panel_agent->signal_connect_update_property(slot(slot_update_property));
_panel_agent->signal_connect_register_helper_properties(slot(slot_register_helper_properties));
_panel_agent->signal_connect_update_helper_property(slot(slot_update_helper_property));
_panel_agent->signal_connect_register_helper(slot(slot_register_helper));
_panel_agent->signal_connect_remove_helper(slot(slot_remove_helper));
_panel_agent->signal_connect_lock(slot(slot_lock));
_panel_agent->signal_connect_unlock(slot(slot_unlock));
_panel_agent->get_helper_list(_helper_list);
return true;
}
static bool run_panel_agent(void)
{
SCIM_DEBUG_MAIN(1) << "run_panel_agent ()\n";
_panel_agent_thread = NULL;
if (_panel_agent && _panel_agent->valid()) {
_panel_agent_thread = new PanelAgentThread();
_panel_agent_thread->start();
}
return (_panel_agent_thread != NULL);
}
static void start_auto_start_helpers(void)
{
SCIM_DEBUG_MAIN(1) << "start_auto_start_helpers () begin\n";
// Add Helper object items.
for (size_t i = 0; i < _helper_list.size(); ++i) {
SCIM_DEBUG_MAIN(1) << "--" << _helper_list[i].uuid << "--" << _helper_list[i].name << "--\n";
if ((_helper_list[i].option & SCIM_HELPER_AUTO_START)) {
_panel_agent->start_helper(_helper_list[i].uuid);
}
}
SCIM_DEBUG_MAIN(1) << "start_auto_start_helpers () end\n";
}
static void slot_transaction_start(void)
{
SCIM_DEBUG_MAIN(1) << "slot_transaction_start ()\n";
_transaction_lock.lock();
}
static void slot_transaction_end(void)
{
SCIM_DEBUG_MAIN(1) << "slot_transaction_end ()\n";
_transaction_lock.unlock();
}
static void slot_reload_config(void)
{
SCIM_DEBUG_MAIN(1) << "slot_reload_config ()\n";
if (!_config.null())
_config->reload();
else
SCIM_DEBUG_MAIN(1) << "config is null\n";
}
static void slot_turn_on(void)
{
SCIM_DEBUG_MAIN(1) << "slot_turn_on ()" << _dbus_handler << "\n";
qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::TURN_ON));
}
static void slot_turn_off(void)
{
SCIM_DEBUG_MAIN(1) << "slot_turn_off ()\n";
qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::TURN_OFF));
/*
*/
}
static void slot_update_screen(int num)
{
SCIM_DEBUG_MAIN(1) << "slot_update_screen ()\n";
qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::UP_SCREEN, QVariantList() << num));
}
static void slot_update_factory_info(const PanelFactoryInfo &info)
{
SCIM_DEBUG_MAIN(1) << "slot_update_factory_info ()\n";
qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::UP_FACTORY_INFO, QVariantList() << QVariant::fromValue(info)));
}
static void slot_show_help(const String &help)
{
SCIM_DEBUG_MAIN(1) << "slot_show_help ()\n";
qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::SHOW_HELP, QVariantList() << QString::fromUtf8(help.c_str())));
}
static void slot_show_factory_menu(const std::vector<PanelFactoryInfo> &factories)
{
SCIM_DEBUG_MAIN(1) << "slot_show_factory_menu ()\n";
QVariantList list;
for (const PanelFactoryInfo &info : factories) {
list << QVariant::fromValue(info);
}
qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::SHOW_FACTORY_MENU, list));
}
static void slot_update_spot_location(int x, int y)
{
SCIM_DEBUG_MAIN(1) << "slot_update_spot_location ()\n";
qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::UP_SPOT_LOC, QVariantList() << x << y));
}
static void slot_show_preedit_string(void)
{
SCIM_DEBUG_MAIN(1) << "slot_show_preedit_string ()\n";
qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::SHOW_PREEDIT));
}
static void slot_show_aux_string(void)
{
SCIM_DEBUG_MAIN(1) << "slot_show_aux_string ()\n";
qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::SHOW_AUX));
}
static void slot_show_lookup_table(void)
{
SCIM_DEBUG_MAIN(1) << "slot_show_lookup_table ()\n";
qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::SHOW_LOOKUPTABLE));
}
static void slot_hide_preedit_string(void)
{
SCIM_DEBUG_MAIN(1) << "slot_hide_preedit_string ()\n";
qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::HIDE_PREEDIT));
}
static void slot_hide_aux_string(void)
{
SCIM_DEBUG_MAIN(1) << "slot_hide_aux_string ()\n";
qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::HIDE_AUX));
}
static void slot_hide_lookup_table(void)
{
SCIM_DEBUG_MAIN(1) << "slot_hide_lookup_table ()\n";
qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::HIDE_LOOKUPTABLE));
}
static void slot_update_preedit_string(const String &str, const AttributeList &attrs)
{
SCIM_DEBUG_MAIN(1) << "slot_update_preedit_string ()" << str << "\n";
qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::UP_PREEDIT_STR, QVariantList() << QString::fromUtf8(str.c_str()) << AttrList2String(attrs)));
}
static void slot_update_preedit_caret(int caret)
{
SCIM_DEBUG_MAIN(1) << "slot_update_preedit_caret ()" << caret << "\n";
qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::UP_PREEDIT_CARET, QVariantList() << caret));
}
static void slot_update_aux_string(const String &str, const AttributeList &attrs)
{
SCIM_DEBUG_MAIN(1) << "slot_update_aux_string ()" << str << "\n";
qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::UP_AUX, QVariantList() << QString::fromUtf8(str.c_str()) << AttrList2String(attrs)));
}
static void slot_update_lookup_table(const LookupTable &table)
{
SCIM_DEBUG_MAIN(1) << "slot_update_lookup_table ()\n";
qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::UP_LOOKUPTABLE, LookupTable2VariantList(table)));
qApp->postEvent(
_dbus_handler,
new DBusEvent(DBusEvent::UP_LOOKUPTABLE_CURSOR, QVariantList() << (table.is_cursor_visible() ? table.get_cursor_pos_in_current_page() : -1)));
}
static void slot_register_properties(const PropertyList &props)
{
SCIM_DEBUG_MAIN(1) << "slot_register_properties ()\n";
QVariantList list;
for (const Property &prop : props) {
list << QVariant::fromValue(prop);
}
qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::REG_PROPERTIES, list));
}
static void slot_update_property(const Property &prop)
{
SCIM_DEBUG_MAIN(1) << "slot_update_property ()\n";
qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::UP_PROPERTY, QVariantList() << QVariant::fromValue(prop)));
}
static void slot_register_helper_properties(int id, const PropertyList &props)
{
SCIM_DEBUG_MAIN(1) << "slot_register_helper_properties ()\n";
QVariantList list;
for (const Property &prop : props) {
list << QVariant::fromValue(prop);
}
qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::REG_HELPER_PROPERTIES, QVariantList() << id << list));
}
static void slot_update_helper_property(int id, const Property &prop)
{
SCIM_DEBUG_MAIN(1) << "slot_update_helper_property ()\n";
qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::UP_HELPER_PROPERTY, QVariantList() << id << QVariant::fromValue(prop)));
}
static void slot_register_helper(int id, const HelperInfo &helper)
{
SCIM_DEBUG_MAIN(1) << "slot_register_helper ()\n";
qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::REG_HELPER, QVariantList() << id << QVariant::fromValue(helper)));
}
static void slot_remove_helper(int id)
{
SCIM_DEBUG_MAIN(1) << "slot_remove_helper ()\n";
qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::RM_HELPER, QVariantList() << id));
}
static void slot_lock(void)
{
SCIM_DEBUG_MAIN(1) << "slot_lock ()\n";
//_panel_agent_lock.lock();
}
static void slot_unlock(void)
{
SCIM_DEBUG_MAIN(1) << "slot_unlock ()\n";
//_panel_agent_lock.unlock();
}
//////////////////////////////////////////////////////////////////////
// End of PanelAgent-Functions
//////////////////////////////////////////////////////////////////////
static void signalhandler(int sig)
{
Q_UNUSED(sig)
SCIM_DEBUG_MAIN(1) << "In signal handler...\n";
if (_panel_agent)
_panel_agent->stop();
}
int main(int argc, char *argv[])
{
std::vector<String> config_list;
int i;
bool daemon = false;
int new_argc = 0;
char **new_argv = new char *[40];
String config_name("simple");
String display_name;
bool should_resident = true;
// QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale());
// Display version info
// std::cerr << "GTK Panel of SCIM " << SCIM_VERSION << "\n\n";
// get modules list
scim_get_config_module_list(config_list);
// Add a dummy config module, it's not really a module!
config_list.push_back("dummy");
// Use socket Config module as default if available.
if (!config_list.empty()) {
if (std::find(config_list.begin(), config_list.end(), config_name) == config_list.end())
config_name = config_list[0];
}
// DebugOutput::set_output("/home/ora/a.log");
// DebugOutput::enable_debug (SCIM_DEBUG_AllMask);
// parse command options
i = 0;
while (i < argc) {
if (++i >= argc)
break;
if (String("-l") == argv[i] || String("--list") == argv[i]) {
std::vector<String>::iterator it;
std::cout << "\n";
std::cout << "Available Config module:\n";
for (it = config_list.begin(); it != config_list.end(); ++it)
std::cout << " " << *it << "\n";
return 0;
}
if (String("-c") == argv[i] || String("--config") == argv[i]) {
if (++i >= argc) {
std::cerr << "no argument for option " << argv[i - 1] << "\n";
return -1;
}
config_name = argv[i];
continue;
}
if (String("-h") == argv[i] || String("--help") == argv[i]) {
std::cout << "Usage: " << argv[0] << " [option]...\n\n"
<< "The options are: \n"
<< " --display DISPLAY Run on display DISPLAY.\n"
<< " -l, --list List all of available config modules.\n"
<< " -c, --config NAME Uses specified Config module.\n"
<< " -d, --daemon Run " << argv[0] << " as a daemon.\n"
<< " -ns, --no-stay Quit if no connected client.\n"
#if ENABLE_DEBUG
<< " -v, --verbose LEVEL Enable debug info, to specific LEVEL.\n"
<< " -o, --output FILE Output debug information into FILE.\n"
#endif
<< " -h, --help Show this help message.\n";
return 0;
}
if (String("-d") == argv[i] || String("--daemon") == argv[i]) {
daemon = true;
continue;
}
if (String("-ns") == argv[i] || String("--no-stay") == argv[i]) {
should_resident = false;
continue;
}
if (String("-v") == argv[i] || String("--verbose") == argv[i]) {
if (++i >= argc) {
std::cerr << "no argument for option " << argv[i - 1] << "\n";
return -1;
}
DebugOutput::set_verbose_level(atoi(argv[i]));
continue;
}
if (String("-o") == argv[i] || String("--output") == argv[i]) {
if (++i >= argc) {
std::cerr << "No argument for option " << argv[i - 1] << "\n";
return -1;
}
DebugOutput::set_output(argv[i]);
continue;
}
if (String("--display") == argv[i]) {
if (++i >= argc) {
std::cerr << "No argument for option " << argv[i - 1] << "\n";
return -1;
}
display_name = argv[i];
continue;
}
if (String("--") == argv[i])
break;
std::cerr << "Invalid command line option: " << argv[i] << "\n";
return -1;
} // End of command line parsing.
new_argv[new_argc++] = argv[0];
// Store the rest argvs into new_argv.
for (++i; i < argc && new_argc < 40; ++i) {
new_argv[new_argc++] = argv[i];
}
// Make up DISPLAY env.
if (display_name.length()) {
new_argv[new_argc++] = strdup("--display");
new_argv[new_argc++] = const_cast<char *>(display_name.c_str());
setenv("DISPLAY", display_name.c_str(), 1);
}
new_argv[new_argc] = 0;
if (!config_name.length()) {
std::cerr << "No Config module is available!\n";
return -1;
}
if (config_name != "dummy") {
// load config module
_config_module = new ConfigModule(config_name);
if (!_config_module || !_config_module->valid()) {
std::cerr << "Can not load " << config_name << " Config module.\n";
return -1;
}
// create config instance
_config = _config_module->create_config();
} else {
_config = new DummyConfig();
}
if (_config.null()) {
std::cerr << "Failed to create Config instance from " << config_name << " Config module.\n";
return -1;
}
KDE_signal(SIGQUIT, signalhandler);
KDE_signal(SIGTERM, signalhandler);
KDE_signal(SIGINT, signalhandler);
KDE_signal(SIGHUP, signalhandler);
const QByteArray display = qgetenv("DISPLAY");
if (display.constData())
display_name = String(display.constData());
if (!initialize_panel_agent(config_name, display_name, should_resident)) {
std::cerr << "Failed to initialize Panel Agent!\n";
return -1;
}
if (daemon)
scim_daemon();
// connect the configuration reload signal.
_config->signal_connect_reload(slot(ui_config_reload_callback));
qRegisterMetaType<scim::Property>("scim::Property");
qRegisterMetaType<PanelFactoryInfo>("PanelFactoryInfo");
qRegisterMetaType<HelperInfo>("HelperInfo");
QDBusConnection::connectToBus(QDBusConnection::SessionBus, "scim_panel");
_dbus_handler = new DBusHandler();
_dbus_handler->setInitialHelpers(_helper_list);
if (!run_panel_agent()) {
std::cerr << "Failed to run Socket Server!\n";
return -1;
}
start_auto_start_helpers();
QCoreApplication app(argc, argv);
app.exec();
_panel_agent_thread->wait();
_config.reset();
std::cerr << "Successfully exited.\n";
return 0;
}
#include "main.moc"
#undef QT_NO_KEYWORDS
/*
vim:ts=4:nowrap:expandtab
*/