Verified Commit 4c4ce2db authored by Xuetian Weng's avatar Xuetian Weng
Browse files

Fixes T13320

Port kimpanel from dataengine to qml plugin.
parent ab42f47d
......@@ -179,7 +179,6 @@ add_subdirectory(runners)
add_subdirectory(containments)
add_subdirectory(toolboxes)
add_subdirectory(applets)
add_subdirectory(dataengines)
add_subdirectory(kcms)
add_subdirectory(knetattach)
add_subdirectory(attica-kde)
......
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
add_subdirectory(backend)
add_subdirectory(plugin)
plasma_install_package(package org.kde.plasma.kimpanel)
set(kimpanelplugin_SRCS
plugin/screen.cpp
plugin/kimpanelplugin.cpp
)
install(FILES plugin/qmldir DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/plasma/private/kimpanel)
add_library(kimpanelplugin SHARED ${kimpanelplugin_SRCS})
target_link_libraries(kimpanelplugin Qt5::Gui Qt5::Qml)
install(TARGETS kimpanelplugin DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/plasma/private/kimpanel)
......@@ -120,7 +120,7 @@ Item {
text: i18n("Configure Input Method")
icon: "configure"
onClicked: {
kimpanel.action("Configure");
helper.configure();
}
}
......@@ -128,7 +128,7 @@ Item {
text: i18n("Reload Config")
icon: "view-refresh"
onClicked: {
kimpanel.action("ReloadConfig");
helper.reloadConfig();
}
}
......@@ -136,7 +136,7 @@ Item {
text: i18n("Exit Input Method")
icon: "application-exit"
onClicked: {
kimpanel.action("Exit");
helper.exit();
}
}
......
......@@ -29,12 +29,13 @@ PlasmaCore.Dialog {
type: PlasmaCore.Dialog.PopupMenu
flags: Qt.Popup | Qt.WindowStaysOnTopHint | Qt.WindowDoesNotAcceptFocus
location: PlasmaCore.Types.Floating
property bool verticalLayout: false
property int highlightCandidate: -1
visible: helper.auxVisible || helper.preeditVisible || helper.lookupTableVisible
property bool verticalLayout: (helper.lookupTableLayout === 1) || (helper.lookupTableLayout === 0 && plasmoid.configuration.vertical_lookup_table);
property int highlightCandidate: helper.lookupTableCursor
property int hoveredCandidate: -1
property font preferredFont: plasmoid.configuration.use_default_font ? theme.defaultFont : plasmoid.configuration.font
property int baseSize: theme.mSize(preferredFont).height
property rect position
property rect position: helper.spotRect
onPositionChanged : updatePosition();
onWidthChanged : updatePosition();
......@@ -50,15 +51,19 @@ PlasmaCore.Dialog {
id: textLabel
width: auxLabel.width + preedit.width
height: Math.max(preedit.height, auxLabel.height)
visible: helper.auxVisible || helper.preeditVisible
PlasmaComponents.Label {
id: auxLabel
font: preferredFont
text: helper.auxText
visible: helper.auxVisible
}
Item {
id: preedit
width: preeditLabel1.width + preeditLabel2.width + 2
height: Math.max(preeditLabel1.height, preeditLabel2.height)
clip: true
visible: helper.preeditVisible
PlasmaComponents.Label {
id: preeditLabel1
anchors.top: parent.top
......@@ -125,7 +130,7 @@ PlasmaCore.Dialog {
id: candidateMouseArea
anchors.fill: parent
hoverEnabled: true
onReleased: selectCandidate(model.index)
onReleased: helper.selectCandidate(model.index)
onContainsMouseChanged: {
inputpanel.hoveredCandidate = containsMouse ? model.index : -1;
}
......@@ -152,7 +157,7 @@ PlasmaCore.Dialog {
Layout.maximumHeight: height
PlasmaCore.IconItem {
id: prevButton
source: inputpanel.verticalLayout ? "arrow-left" : "arrow-up"
source: inputpanel.verticalLayout ? "arrow-up" : "arrow-left"
width: inputpanel.baseSize
height: width
scale: prevButtonMouseArea.pressed ? 0.9 : 1
......@@ -161,12 +166,12 @@ PlasmaCore.Dialog {
id: prevButtonMouseArea
anchors.fill: parent
hoverEnabled: true
onReleased: action("LookupTablePageUp")
onReleased: helper.lookupTablePageUp()
}
}
PlasmaCore.IconItem {
id: nextButton
source: inputpanel.verticalLayout ? "arrow-right" : "arrow-down"
source: inputpanel.verticalLayout ? "arrow-down" : "arrow-right"
width: inputpanel.baseSize
height: width
scale: nextButtonMouseArea.pressed ? 0.9 : 1
......@@ -175,20 +180,13 @@ PlasmaCore.Dialog {
id: nextButtonMouseArea
anchors.fill: parent
hoverEnabled: true
onReleased: action("LookupTablePageDown")
onReleased: helper.lookupTablePageDown()
}
}
}
}
}
PlasmaCore.DataSource {
id: inputPanelEngine
engine: "kimpanel"
connectedSources: ["inputpanel"]
onDataChanged: timer.restart()
}
Kimpanel.Screen {
id: screen
}
......@@ -198,64 +196,46 @@ PlasmaCore.Dialog {
Timer {
id: timer
interval: 1
onTriggered: updateUI()
onTriggered: updateLookupTable()
}
}
function updateUI() {
var data = inputPanelEngine.data["inputpanel"];
if (!data) {
return;
}
var auxVisible = data["AuxVisible"] ? true : false;
var preeditVisible = data["PreeditVisible"] ? true : false;
var lookupTableVisible = data["LookupTableVisible"] ? true : false;
var pos = data["Position"] ? { 'x': data["Position"].x,
'y': data["Position"].y,
'w': data["Position"].width,
'h': data["Position"].height } : {'x' : 0, 'y': 0, 'w': 0, 'h': 0 };
inputpanel.position = Qt.rect(pos.x, pos.y, pos.w, pos.h);
Connections {
target: helper
function onPreeditTextChanged() {
var charArray = [...helper.preeditText];
preeditLabel1.text = charArray.slice(0, helper.caretPos).join('');
preeditLabel2.text = charArray.slice(helper.caretPos).join('');
}
var newVisibility = auxVisible || preeditVisible || lookupTableVisible;
if (!newVisibility) {
// If we gonna hide anyway, don't do the update.
inputpanel.hide();
return;
function onLookupTableChanged() {
timer.restart();
}
}
textLabel.visible = auxVisible || preeditVisible;
auxLabel.text = (auxVisible && data["AuxText"]) ? data["AuxText"] : ""
var preeditText = (preeditVisible && data["PreeditText"]) ? data["PreeditText"] : ""
var caret = data["CaretPos"] ? data["CaretPos"] : 0;
var charArray = [...preeditText];
preeditLabel1.text = charArray.slice(0, caret).join('');
preeditLabel2.text = charArray.slice(caret).join('');
preedit.visible = preeditVisible;
var layout = data["LookupTableLayout"] !== undefined ? data["LookupTableLayout"] : 0;
inputpanel.highlightCandidate = data["LookupTableCursor"] !== undefined ? data["LookupTableCursor"] : -1;
}
function updateLookupTable() {
inputpanel.hoveredCandidate = -1;
inputpanel.verticalLayout = (layout === 1) || (layout === 0 && plasmoid.configuration.vertical_lookup_table);
button.visible = lookupTableVisible
button.visible = helper.lookupTableVisible && (helper.hasPrev || helper.hasNext);
if (data["LookupTable"]) {
var table = data["LookupTable"];
if (lookupTableVisible) {
if (table.length < tableList.count) {
tableList.remove(table.length, tableList.count - table.length);
}
for (var i = 0; i < table.length; i ++) {
if (i >= tableList.count) {
tableList.append({'label' : table[i].label, 'text': table[i].text, 'index': i});
} else {
tableList.set(i, {'label' : table[i].label, 'text': table[i].text, 'index': i});
}
var labels = helper.labels;
var texts = helper.texts;
var length = Math.min(labels.length, texts.length);
if (helper.lookupTableVisible) {
if (length< tableList.count) {
tableList.remove(length, tableList.count - length);
}
for (var i = 0; i < length; i ++) {
if (i >= tableList.count) {
tableList.append({'label' : labels[i], 'text': texts[i], 'index': i});
} else {
tableList.set(i, {'label' : labels[i], 'text': texts[i], 'index': i});
}
} else {
tableList.clear();
}
}
// If we gonna show, do that after everything is ready.
if (newVisibility) {
inputpanel.show();
} else {
tableList.clear();
}
}
......@@ -294,17 +274,4 @@ PlasmaCore.Dialog {
inputpanel.x = newRect.x + (x - newRect.x) / devicePerPixelRatio;
inputpanel.y = newRect.y + (y - newRect.y) / devicePerPixelRatio;
}
function action(key) {
var service = inputPanelEngine.serviceForSource("inputpanel");
var operation = service.operationDescription(key);
service.startOperationCall(operation);
}
function selectCandidate(index) {
var service = inputPanelEngine.serviceForSource("inputpanel");
var operation = service.operationDescription("SelectCandidate");
operation.candidate = index;
service.startOperationCall(operation);
}
}
......@@ -22,6 +22,7 @@ import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.kquickcontrolsaddons 2.0
import org.kde.plasma.private.kimpanel 0.1 as Kimpanel
Item {
id: kimpanel
......@@ -77,9 +78,7 @@ Item {
if (model.key == 'kimpanel-placeholder') {
return;
}
clickHandler(model.key);
// clickHandler will trigger the menu, but we have to wait for
// the menu data. So we have to set the visual parent ahead.
helper.triggerProperty(model.key);
actionMenu.visualParent = statusIcon;
} else {
contextMenu.open(statusIcon, {key: model.key, label: model.label});
......@@ -90,19 +89,6 @@ Item {
}
}
function clickHandler(key) {
var service = dataEngine.serviceForSource("statusbar");
var operation = service.operationDescription("TriggerProperty");
operation.key = key;
service.startOperationCall(operation);
}
function action(key) {
var service = dataEngine.serviceForSource("statusbar");
var operation = service.operationDescription(key);
service.startOperationCall(operation);
}
function hideAction(key) {
// We must use assignment to change the configuration property,
// otherwise it won't get notified.
......@@ -127,28 +113,20 @@ Item {
}
function showMenu(menu, menuData) {
if (!menuData) {
return;
var actionList = [];
for (var i = 0; i < menuData.length; i++ ) {
actionList.push({"actionId": menuData[i].key, "icon": menuData[i].icon, "text": menuData[i].label, hint: menuData[i].hint});
}
if (menuData["timestamp"] > menu.timestamp) {
menu.timestamp = menuData["timestamp"];
var actionList = [];
for (var i = 0; i < menuData["props"].length; i++ ) {
actionList.push({"actionId": menuData["props"][i].key, "icon": menuData["props"][i].icon, "text": menuData["props"][i].label, hint: menuData["props"][i].hint});
}
if (actionList.length > 0) {
menu.actionList = actionList;
menu.open();
}
if (actionList.length > 0) {
menu.actionList = actionList;
menu.open();
}
}
ActionMenu {
property var timestamp: 0;
id: actionMenu
onActionClicked: {
clickHandler(actionId);
helper.triggerProperty(model.key);
}
}
......@@ -160,11 +138,7 @@ Item {
id: timer
interval: 50
onTriggered: {
var barData = dataEngine.data["statusbar"];
var data = [];
if (barData && barData["Properties"]) {
data = barData["Properties"];
}
var data = helper.properties;
var nodata = data.length == 0;
var count = list.count;
var c = 0, i;
......@@ -214,20 +188,19 @@ Item {
}
}
PlasmaCore.DataSource {
id: dataEngine
engine: "kimpanel"
connectedSources: ["statusbar"]
onDataChanged: {
showMenu(actionMenu, dataEngine.data["statusbar"]["Menu"]);
var data = dataEngine.data["statusbar"]["Properties"];
if (!data) {
kimpanel.visibleButtons = 0;
return;
}
Kimpanel.Kimpanel {
id: helper
}
Connections {
target: helper
function onPropertiesChanged() {
timer.restart();
}
function onMenuTriggered(menu) {
console.log(menu);
showMenu(actionMenu, menu);
}
}
}
set(kimpanelplugin_SRCS
kimpanel.cpp
screen.cpp
kimpanelplugin.cpp
kimpanelagent.cpp
)
QT5_ADD_DBUS_ADAPTOR(kimpanelplugin_SRCS
org.kde.impanel.xml
kimpanelagent.h
PanelAgent)
add_library(kimpanelplugin SHARED ${kimpanelplugin_SRCS})
target_compile_definitions(kimpanelplugin PRIVATE -DKIMPANEL_LIBEXEC_DIR=\"${KDE_INSTALL_FULL_LIBEXECDIR}\")
target_link_libraries(kimpanelplugin Qt5::Gui Qt5::Qml Qt5::DBus)
install(TARGETS kimpanelplugin DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/plasma/private/kimpanel)
install(FILES qmldir DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/plasma/private/kimpanel)
/*
* Copyright 2020 Weng Xuetian <wengxt@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include "kimpanel.h"
Kimpanel::Kimpanel(QObject* parent) : QObject(parent), m_panelAgent(new PanelAgent(this))
{
connect(m_panelAgent, &PanelAgent::updateAux, this, &Kimpanel::updateAux);
connect(m_panelAgent, &PanelAgent::updatePreeditText, this, &Kimpanel::updatePreeditText);
connect(m_panelAgent, &PanelAgent::updatePreeditCaret, this, &Kimpanel::updatePreeditCaret);
connect(m_panelAgent, &PanelAgent::updateLookupTable, this, &Kimpanel::updateLookupTable);
connect(m_panelAgent, &PanelAgent::updateSpotLocation, this, &Kimpanel::updateSpotLocation);
connect(m_panelAgent, &PanelAgent::updateSpotRect, this, &Kimpanel::updateSpotRect);
connect(m_panelAgent, &PanelAgent::showAux, this, &Kimpanel::showAux);
connect(m_panelAgent, &PanelAgent::showPreedit, this, &Kimpanel::showPreedit);
connect(m_panelAgent, &PanelAgent::showLookupTable, this, &Kimpanel::showLookupTable);
connect(m_panelAgent, &PanelAgent::updateLookupTableCursor, this, &Kimpanel::updateLookupTableCursor);
connect(m_panelAgent, &PanelAgent::updateLookupTableFull, this, &Kimpanel::updateLookupTableFull);
connect(m_panelAgent, &PanelAgent::updateProperty, this, &Kimpanel::updateProperty);
connect(m_panelAgent, &PanelAgent::registerProperties, this, &Kimpanel::registerProperties);
connect(m_panelAgent, &PanelAgent::execMenu, this, &Kimpanel::execMenu);
connect(m_panelAgent, &PanelAgent::execDialog, this, &Kimpanel::execDialog);
}
void Kimpanel::updateAux(const QString& text, const QList< TextAttribute >& attrList)
{
Q_UNUSED(attrList);
if (m_auxText != text) {
m_auxText = text;
emit auxTextChanged();
}
}
void Kimpanel::updatePreeditText(const QString& text, const QList<TextAttribute>& attrList)
{
Q_UNUSED(attrList);
if (m_preeditText != text) {
m_preeditText = text;
emit preeditTextChanged();
}
}
void Kimpanel::updatePreeditCaret(int pos)
{
if (m_caretPos != pos) {
m_caretPos = pos;
emit preeditTextChanged();
}
}
void Kimpanel::updateLookupTable(const KimpanelLookupTable& lookupTable)
{
m_labels.clear();
m_texts.clear();
Q_FOREACH(const KimpanelLookupTable::Entry & entry, lookupTable.entries) {
m_labels << entry.label;
m_texts << entry.text;
}
m_hasPrev = lookupTable.has_prev;
m_hasNext = lookupTable.has_next;
emit lookupTableChanged();
}
void Kimpanel::updateSpotLocation(int x, int y)
{
updateSpotRect(x, y, 0, 0);
}
void Kimpanel::updateSpotRect(int x, int y, int w, int h)
{
m_spotRect = QRect(x, y, w, h);
emit spotRectChanged();
}
void Kimpanel::showAux(bool visible)
{
if (m_auxVisible != visible) {
m_auxVisible = visible;
emit auxTextChanged();
}
}
void Kimpanel::showPreedit(bool visible)
{
if (m_preeditVisible != visible) {
m_preeditVisible = visible;
emit preeditTextChanged();
}
}
void Kimpanel::showLookupTable(bool visible)
{
if (m_lookupTableVisible != visible) {
m_lookupTableVisible = visible;
emit lookupTableChanged();
}
}
void Kimpanel::updateLookupTableCursor(int cursor)
{
if (m_lookupTableCursor != cursor) {
m_lookupTableCursor = cursor;
emit lookupTableChanged();
}
}
void Kimpanel::updateLookupTableFull(const KimpanelLookupTable& lookupTable, int cursor, int layout)
{
m_labels.clear();
m_texts.clear();
Q_FOREACH(const KimpanelLookupTable::Entry & entry, lookupTable.entries) {
QVariantMap map;
m_labels << entry.label;
m_texts << entry.text;
}
m_hasPrev = lookupTable.has_prev;
m_hasNext = lookupTable.has_next;
m_lookupTableCursor = cursor;
m_lookupTableLayout = layout;
emit lookupTableChanged();
}
void Kimpanel::updateProperty(const KimpanelProperty& property)
{
for (auto &prop : m_props) {
if (prop.toMap()["key"] == property.key) {
prop = property.toMap();
emit propertiesChanged();
break;
}
}
}
void Kimpanel::registerProperties(const QList<KimpanelProperty>& props)
{
m_props.clear();
for (const auto &prop : props) {
m_props << prop.toMap();
}
emit propertiesChanged();
}
void Kimpanel::execMenu(const QList<KimpanelProperty>& props)
{
QVariantList menuProps;
for (const auto &prop : props) {
menuProps << prop.toMap();
}
emit menuTriggered(menuProps);
}
void Kimpanel::execDialog(const KimpanelProperty& prop)
{
Q_UNUSED(prop)
}
void Kimpanel::configure()
{
m_panelAgent->configure();
}
void Kimpanel::exit()
{
m_panelAgent->exit();
}