diff --git a/applets/CMakeLists.txt b/applets/CMakeLists.txt --- a/applets/CMakeLists.txt +++ b/applets/CMakeLists.txt @@ -7,6 +7,7 @@ add_subdirectory(mediaframe) add_subdirectory(notes) add_subdirectory(timer) +add_subdirectory(dict) find_package(KDEExperimentalPurpose QUIET) set_package_properties(KDEExperimentalPurpose PROPERTIES DESCRIPTION "EXPERIMENTAL. Support for QuickShare sharing" diff --git a/applets/dict/CMakeLists.txt b/applets/dict/CMakeLists.txt --- a/applets/dict/CMakeLists.txt +++ b/applets/dict/CMakeLists.txt @@ -1,14 +1,33 @@ -INCLUDE_DIRECTORIES( - ${QT_QTWEBKIT_INCLUDE_DIR}) +####################################################################################### +# Package (metadata.desktop and QML) +plasma_install_package(package org.kde.plasma_applet_dict) + +####################################################################################### +# Icon for the package +install(FILES accessories-dictionary.svgz + DESTINATION ${DATA_INSTALL_DIR}/icons/hicolor/scalable/apps/) + +####################################################################################### +# C++ Plugin + +find_package(Qt5 ${REQUIRED_QT_VERSION} CONFIG REQUIRED WebEngine) + +add_definitions(-DTRANSLATION_DOMAIN="plasma_applet_org.kde.plasma.dict") set(dict_SRCS - dict.cpp) + plugin/dict_plugin.cpp + plugin/dict_object.cpp +) -kde4_add_plugin(plasma_applet_dict ${dict_SRCS}) -target_link_libraries(plasma_applet_dict ${KDE4_PLASMA_LIBS} ${KDE4_KDEUI_LIBS} +add_library(dictplugin SHARED ${dict_SRCS}) +target_link_libraries(dictplugin + KF5::Plasma + KF5::IconThemes + KF5::I18n + Qt5::Quick + Qt5::WebEngine ) -install(TARGETS plasma_applet_dict DESTINATION ${PLUGIN_INSTALL_DIR}) -install(FILES plasma-dict-default.desktop DESTINATION ${SERVICES_INSTALL_DIR}) +install(FILES plugin/qmldir DESTINATION ${QML_INSTALL_DIR}/org/kde/plasma/private/dict) +install(TARGETS dictplugin DESTINATION ${QML_INSTALL_DIR}/org/kde/plasma/private/dict) -kde4_install_icons(${ICON_INSTALL_DIR}) diff --git a/applets/dict/Messages.sh b/applets/dict/Messages.sh --- a/applets/dict/Messages.sh +++ b/applets/dict/Messages.sh @@ -1,2 +1,2 @@ #! /usr/bin/env bash -$XGETTEXT *.cpp -o $podir/plasma_applet_qstardict.pot +$XGETTEXT `find . -name \*.qml -o -name \*.cpp` -o $podir/plasma_applet_org.kde.plasma.dict.pot diff --git a/applets/dict/TODO b/applets/dict/TODO deleted file mode 100644 --- a/applets/dict/TODO +++ /dev/null @@ -1,8 +0,0 @@ -TODO for dict applet - -Looks -Add clear button -Sliding animations -Configurable dictionaries -Migrate to layouts - diff --git a/applets/dict/hisc-app-accessories-dictionary.svgz b/applets/dict/accessories-dictionary.svgz rename from applets/dict/hisc-app-accessories-dictionary.svgz rename to applets/dict/accessories-dictionary.svgz index 18df3a62c1f02b972d5828a18fba8da597089e8f..18df3a62c1f02b972d5828a18fba8da597089e8f GIT binary patch literal 13780 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 KCTRfm$p8R5>)5RT literal 13780 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 KCTRfm$p8R5>)5RT diff --git a/applets/dict/dict.h b/applets/dict/dict.h deleted file mode 100644 --- a/applets/dict/dict.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2008 Nick Shaforostoff - * - * based on work by: - * Copyright (C) 2007 Thomas Georgiou and Jeff Cooper - * - * 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) any later version. - * - * 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 . - */ - -#ifndef DICT_H -#define DICT_H - -#include -#include - -class QTimer; -class CheckableStringListModel; - -class QGraphicsLinearLayout; - -namespace Plasma -{ - class IconWidget; - class LineEdit; - class TextBrowser; -} - -class DictApplet: public Plasma::PopupApplet -{ - Q_OBJECT - public: - DictApplet(QObject *parent, const QVariantList &args); - ~DictApplet(); - void init(); - - QGraphicsWidget *graphicsWidget(); - void setPath(const QString&); - - public slots: - void dataUpdated(const QString &name, const Plasma::DataEngine::Data &data); - void autoDefine(const QString &word); - void linkDefine(const QString &word); - void configChanged(); - - protected slots: - void define(); - void configAccepted(); - void focusEditor(); - void syncTheme(); - - protected: - void createConfigurationInterface(KConfigDialog *parent); - void popupEvent(bool shown); - - private: - QString m_source; - QTimer* m_timer; - QString m_dataEngine; - //QGraphicsPixmapItem *m_graphicsIcon; - QGraphicsWidget *m_graphicsWidget; - QGraphicsLinearLayout *m_layout; - QGraphicsLinearLayout *m_horLayout; - Plasma::LineEdit *m_wordEdit; - //Plasma::Flash *m_flash; -// QTextBrowser* m_defBrowser; - Plasma::TextBrowser* m_defBrowser; - Plasma::IconWidget *m_icon; - -// QList< QPair > m_dicts; - QWeakPointer m_dictsModel; - QStringList m_dicts; - QHash m_activeDicts; -}; - -K_EXPORT_PLASMA_APPLET(qstardict, DictApplet) - -#endif diff --git a/applets/dict/dict.cpp b/applets/dict/dict.cpp deleted file mode 100644 --- a/applets/dict/dict.cpp +++ /dev/null @@ -1,401 +0,0 @@ -/* - * Copyright (C) 2008 Nick Shaforostoff - * - * based on work by: - * Copyright (C) 2007 Thomas Georgiou and Jeff Cooper - * - * 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) any later version. - * - * 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 . - */ - -#include "dict.h" - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#define AUTO_DEFINE_TIMEOUT 500 - -using namespace Plasma; - - - -// Style sheet format -const char* translationCSS = - "dl {color: %1;}\n" - "a{color: %2}\n" - "a:visited{color: %3}\n"; - -DictApplet::DictApplet(QObject *parent, const QVariantList &args) - : Plasma::PopupApplet(parent, args) - , m_graphicsWidget(0) - , m_wordEdit(0) -{ - setPopupIcon(QLatin1String( "accessories-dictionary" )); - setAspectRatioMode(Plasma::IgnoreAspectRatio); -} - -void DictApplet::init() -{ - const char* dataEngines[]={"dict","qstardict"}; - bool engineChoice = dataEngine(QString( QLatin1String( dataEngines[1] ) ) )->isValid(); -// bool engineChoice = false; //for testing - m_dataEngine = QLatin1String( dataEngines[int(engineChoice)] ); - - // tooltip stuff - Plasma::ToolTipContent toolTipData; - toolTipData.setAutohide(true); - toolTipData.setMainText(name()); - toolTipData.setImage(KIcon(QLatin1String( "accessories-dictionary" ))); - - Plasma::ToolTipManager::self()->setContent(this, toolTipData); - - // Only register the tooltip in panels - switch (formFactor()) { - case Plasma::Horizontal: - case Plasma::Vertical: - Plasma::ToolTipManager::self()->registerWidget(this); - break; - default: - Plasma::ToolTipManager::self()->unregisterWidget(this); - break; - } -} - -DictApplet::~DictApplet() -{ - m_defBrowser->deleteLater(); -} - -QGraphicsWidget *DictApplet::graphicsWidget() -{ - if (m_graphicsWidget) { - return m_graphicsWidget; - } - - m_wordEdit = new LineEdit(this); - m_wordEdit->nativeWidget()->setClearButtonShown( true ); - m_wordEdit->nativeWidget()->setClickMessage(i18n("Enter word to define here")); - m_wordEdit->show(); - - m_defBrowser = new Plasma::TextBrowser(); - m_defBrowser->nativeWidget()->setNotifyClick(true); - connect(m_defBrowser->nativeWidget(),SIGNAL(urlClick(QString)),this,SLOT(linkDefine(QString))); - syncTheme(); - connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), SLOT(updateColors())); - m_defBrowser->hide(); - -// Icon in upper-left corner - m_icon = new Plasma::IconWidget(this); - m_icon->setIcon(QLatin1String( "accessories-dictionary" )); - -// Position lineedits - //const int wordEditOffset = 40; - m_icon->setPos(12,3); - //m_wordProxyWidget->setPos(15 + wordEditOffset,7); - //m_wordProxyWidget->show(); - // TODO m_wordEdit->setDefaultTextColor(Plasma::Theme::self()->color(Plasma::Theme::TextColor)); - -// Timer for auto-define - m_timer = new QTimer(this); - m_timer->setInterval(AUTO_DEFINE_TIMEOUT); - m_timer->setSingleShot(true); - connect(m_timer, SIGNAL(timeout()), this, SLOT(define())); - - m_horLayout = new QGraphicsLinearLayout(Qt::Horizontal); - m_horLayout->addItem(m_icon); - m_horLayout->addItem(m_wordEdit); - m_horLayout->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - m_layout = new QGraphicsLinearLayout(Qt::Vertical); - m_layout->addItem(m_horLayout); - m_layout->addItem(m_defBrowser); - - m_source.clear(); - dataEngine(m_dataEngine)->connectSource(m_source, this); - connect(m_wordEdit, SIGNAL(editingFinished()), this, SLOT(define())); - connect(m_wordEdit->nativeWidget(), SIGNAL(textChanged(QString)), this, SLOT(autoDefine(QString))); - - dataEngine(m_dataEngine)->connectSource(QLatin1String( "list-dictionaries" ), this); - - //connect(m_defEdit, SIGNAL(linkActivated(QString)), this, SLOT(linkDefine(QString))); - -// This is the fix for links/selecting text - //QGraphicsItem::GraphicsItemFlags flags = m_defEdit->flags(); - //flags ^= QGraphicsItem::ItemIsMovable; - // m_defEdit->setFlags(flags); - - /*m_flash = new Plasma::Flash(this); - m_flash->setColor(Qt::gray); - QFont fnt = qApp->font(); - fnt.setBold(true); - m_flash->setFont(fnt); - m_flash->setPos(25,-10); - m_flash->resize(QSize(200,20));*/ - - configChanged(); - - m_graphicsWidget = new QGraphicsWidget(this); - m_graphicsWidget->setLayout(m_layout); - m_graphicsWidget->setPreferredSize(500, 200); - - Animation *zoomAnim = - Plasma::Animator::create(Plasma::Animator::ZoomAnimation); - zoomAnim->setTargetWidget(m_wordEdit); - zoomAnim->setProperty("zoom", 1.0); - zoomAnim->setProperty("duration", 350); - zoomAnim->start(QAbstractAnimation::DeleteWhenStopped); - - return m_graphicsWidget; -} - -void DictApplet::syncTheme() -{ - // Gets the color scheme from default theme - KColorScheme colorScheme(QPalette::Active, KColorScheme::View, Plasma::Theme::defaultTheme()->colorScheme()); - - m_defBrowser->nativeWidget()->document()->setDefaultStyleSheet(QString(QLatin1String( translationCSS )) - .arg(colorScheme.foreground().color().name()) - .arg(colorScheme.foreground(KColorScheme::LinkText).color().name()) - .arg(colorScheme.foreground(KColorScheme::VisitedText).color().name())); -} - -void DictApplet::configChanged() -{ - KConfigGroup cg = config(); - m_dicts = cg.readEntry("KnownDictionaries", QStringList()); - QStringList activeDictNames = cg.readEntry("ActiveDictionaries", QStringList()); - for (QStringList::const_iterator i = m_dicts.constBegin(); i != m_dicts.constEnd(); ++i) { - m_activeDicts[*i]=activeDictNames.contains(*i); - } -} - -void DictApplet::linkDefine(const QString &text) -{ - //kDebug() <<"ACTIVATED"; - m_wordEdit->setText(text); - define(); -} - -void DictApplet::dataUpdated(const QString& source, const Plasma::DataEngine::Data &data) -{ - if (source==QLatin1String( "list-dictionaries" )) { - QStringList newDicts = data[QLatin1String( "dictionaries" )].toStringList(); - bool changed = false; - for (QStringList::const_iterator i = newDicts.constBegin(); i != newDicts.constEnd(); ++i) { - if (!m_dicts.contains(*i)) { - m_dicts << *i; - m_activeDicts[*i] = true; - changed = true; - } - } - - QStringList::iterator it = m_dicts.begin(); - while (it != m_dicts.end()) { - if (!newDicts.contains(*it)) { - it = m_dicts.erase(it); - changed = true; - } else { - ++it; - } - } - - if (changed) { - configAccepted(); - } - } - - if (!m_source.isEmpty()) { - m_defBrowser->show(); - } - - if (data.contains(QLatin1String( "text" ))) { - m_defBrowser->nativeWidget()->setHtml(data[QLatin1String("text")].toString()); - } - - updateGeometry(); -} - -void DictApplet::define() -{ - if (m_timer->isActive()) { - m_timer->stop(); - } - - QString newSource = m_wordEdit->text(); - QStringList dictsList; - - for (QStringList::const_iterator i = m_dicts.constBegin(); i != m_dicts.constEnd(); ++i) { - if (m_activeDicts.contains(*i) && m_activeDicts.value(*i)) { - dictsList << *i; - } - } - - if (!newSource.isEmpty() && !dictsList.isEmpty()) { - newSource.prepend(dictsList.join(QLatin1String( "," ) )+QLatin1Char( ':' )); - } - - if (newSource == m_source) { - return; - } - - dataEngine(m_dataEngine)->disconnectSource(m_source, this); - - if (!newSource.isEmpty()) { - //get new definition - //m_flash->flash(i18n("Looking up ") + m_word); - m_source = newSource; - dataEngine(m_dataEngine)->connectSource(m_source, this); - } else { - //make the definition box disappear - m_defBrowser->hide(); - } - - updateConstraints(); -} - -void DictApplet::autoDefine(const QString &word) -{ - Q_UNUSED(word) - m_timer->start(); -} - - -class CheckableStringListModel: public QStringListModel -{ -public: - CheckableStringListModel(QObject* parent, const QStringList& dicts, const QHash& activeDicts_) - : QStringListModel(parent) - , activeDicts(activeDicts_) - { - setStringList(dicts); - } - QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const - { - Q_UNUSED(section) - Q_UNUSED(orientation) - - if (role!=Qt::DisplayRole) - return QVariant(); - return i18n("Dictionary"); - } - Qt::DropActions supportedDropActions() const {return Qt::MoveAction;} - Qt::ItemFlags flags(const QModelIndex& index) const - { - if (!index.isValid()) - return Qt::ItemIsEnabled | Qt::ItemIsDropEnabled; - return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsDragEnabled; - } - bool setData (const QModelIndex& index, const QVariant& value, int role=Qt::EditRole) - { - if (role==Qt::CheckStateRole) - { - activeDicts[stringList().at(index.row())]=value.toInt()==Qt::Checked; - return true; - } - else - return QStringListModel::setData(index,value,role); - } - QVariant data(const QModelIndex& index, int role=Qt::EditRole) const - { - if (!index.isValid()) - return QVariant(); - - if (role==Qt::CheckStateRole) - return ( activeDicts.contains(stringList().at(index.row()))&&activeDicts.value(stringList().at(index.row())) )?Qt::Checked:Qt::Unchecked; - return QStringListModel::data(index,role); - } - -public: - QHash activeDicts; -}; - - -void DictApplet::createConfigurationInterface(KConfigDialog *parent) -{ - if (dataEngine(QLatin1String( "qstardict" ))->isValid()) { - QTreeView* widget=new QTreeView(parent); - widget->setDragEnabled(true); - widget->setAcceptDrops(true); - widget->setDragDropMode(QAbstractItemView::InternalMove); - widget->setDropIndicatorShown(true); - widget->setItemsExpandable(false); - widget->setAllColumnsShowFocus(true); - widget->setRootIsDecorated(false); - - delete m_dictsModel.data(); - CheckableStringListModel *model = new CheckableStringListModel(parent,m_dicts,m_activeDicts); - m_dictsModel = model; - widget->setModel(model); - - parent->addPage(widget, parent->windowTitle(), Applet::icon()); - connect(parent, SIGNAL(applyClicked()), this, SLOT(configAccepted())); - connect(parent, SIGNAL(okClicked()), this, SLOT(configAccepted())); - } -} - -void DictApplet::popupEvent(bool shown) -{ - //kDebug() << shown; - if (shown && m_wordEdit) { - focusEditor(); - } -} - -void DictApplet::configAccepted() -{ - if (m_dictsModel) { - CheckableStringListModel *model = m_dictsModel.data(); - m_dicts = model->stringList(); - m_activeDicts = model->activeDicts; - } - KConfigGroup cg = config(); - cg.writeEntry("KnownDictionaries", m_dicts); - - QStringList activeDictNames; - for (QStringList::const_iterator i = m_dicts.constBegin(); i != m_dicts.constEnd(); ++i) - if (m_activeDicts.contains(*i) && m_activeDicts.value(*i)) - activeDictNames<<*i; - - cg.writeEntry("ActiveDictionaries", activeDictNames); - - define(); - emit configNeedsSaving(); -} - -void DictApplet::focusEditor() -{ - m_wordEdit->clearFocus(); - m_wordEdit->setFocus(); - m_wordEdit->nativeWidget()->clearFocus(); - m_wordEdit->nativeWidget()->setFocus(); -} - diff --git a/applets/dict/package/contents/ui/main.qml b/applets/dict/package/contents/ui/main.qml new file mode 100644 --- /dev/null +++ b/applets/dict/package/contents/ui/main.qml @@ -0,0 +1,42 @@ +import QtQuick 2.0 +import QtQuick.Layouts 1.1 +import org.kde.plasma.components 2.0 as PlasmaComponents +import org.kde.plasma.core 2.0 as PlasmaCore +import QtWebEngine 1.1 + +import org.kde.plasma.private.dict 1.0 + +ColumnLayout { + + DictObject { + id: dict + onSearchInProgress: web.loadHtml(i18n("Looking up definition...")); + onDefinitionFound: web.loadHtml(html); + } + + PlasmaComponents.TextField { + id: input + placeholderText: i18n("Enter word to define here") + implicitWidth: units.gridUnit * 40 + Layout.fillWidth: true + onAccepted: { + if (input.text === "") { + web.visible = false; + } else { + web.visible = true; + dict.lookup(input.text); + } + } + } + + WebEngineView { + id: web + visible: false + Layout.fillWidth: true + //Layout.fillHeight: true + Layout.preferredHeight: 400 + zoomFactor: units.devicePixelRatio + profile: dict.webProfile + } + +} diff --git a/applets/dict/plasma-dict-default.desktop b/applets/dict/package/metadata.desktop rename from applets/dict/plasma-dict-default.desktop rename to applets/dict/package/metadata.desktop --- a/applets/dict/plasma-dict-default.desktop +++ b/applets/dict/package/metadata.desktop @@ -116,16 +116,21 @@ Icon=accessories-dictionary X-KDE-ServiceTypes=Plasma/Applet -X-KDE-Library=plasma_applet_dict +# Provides the config dialog +#X-KDE-Library=plasma_applet_dict X-KDE-PluginInfo-Author=The Plasma Team X-KDE-PluginInfo-Email=plasma-devel@kde.org -X-KDE-PluginInfo-Name=dict +X-KDE-PluginInfo-Name=org.kde.plasma_applet_dict X-KDE-PluginInfo-Version=1.0 X-KDE-PluginInfo-Website=http://plasma.kde.org/ X-KDE-PluginInfo-Category=Language X-KDE-PluginInfo-Depends= X-KDE-PluginInfo-License=GPL-2.0+ X-KDE-PluginInfo-EnabledByDefault=true +X-Plasma-API=declarativeappletscript +X-Plasma-MainScript=ui/main.qml +X-Plasma-RemoteLocation= + X-Plasma-Requires-FileDialog=Unused X-Plasma-Requires-LaunchApp=Unused diff --git a/applets/dict/plugin/dict_object.h b/applets/dict/plugin/dict_object.h new file mode 100644 --- /dev/null +++ b/applets/dict/plugin/dict_object.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2017 David Faure + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef DICT_OBJECT_H +#define DICT_OBJECT_H + +#include +#include +#include +#include +class QQuickWebEngineProfile; + +class DictObject : public QObject, public Plasma::DataEngineConsumer +{ + Q_OBJECT + Q_PROPERTY(QQuickWebEngineProfile* webProfile READ webProfile CONSTANT) + +public: + explicit DictObject(QObject *parent = nullptr); + + QQuickWebEngineProfile* webProfile() const; + +public Q_SLOTS: + void lookup(const QString &word); + +private Q_SLOTS: + void dataUpdated(const QString &sourceName, const Plasma::DataEngine::Data &data); + +Q_SIGNALS: + void searchInProgress(); + void definitionFound(const QString &html); + +private: + QString m_source; + QString m_dataEngine; + struct AvailableDict { + QString id; + QString description; + }; + std::vector m_availableDicts; + QString m_selectedDict; + + QQuickWebEngineProfile* m_webProfile; +}; + +#endif diff --git a/applets/dict/plugin/dict_object.cpp b/applets/dict/plugin/dict_object.cpp new file mode 100644 --- /dev/null +++ b/applets/dict/plugin/dict_object.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2017 David Faure + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "dict_object.h" +#include +#include +#include +#include +#include + + +// The KDE4 applet could use "qstardict" if available, but I have no idea where this came from. +static const char defaultDataEngine[] = "dict"; + +class DictSchemeHandler : public QWebEngineUrlSchemeHandler +{ +public: + DictSchemeHandler(DictObject *dict, QObject *parent) + : QWebEngineUrlSchemeHandler(parent), + m_dict(dict) + { + } + void requestStarted(QWebEngineUrlRequestJob *job) { + job->fail(QWebEngineUrlRequestJob::UrlInvalid); + const QString word = job->requestUrl().path(); + // different thread -> use invokeMethod + QMetaObject::invokeMethod(m_dict, "lookup", Q_ARG(QString, word)); + } +private: + DictObject *m_dict; +}; + +DictObject::DictObject(QObject *parent) + : QObject(parent), + m_dataEngine(QString::fromLatin1(defaultDataEngine)) +{ + dataEngine(m_dataEngine)->connectSource(QLatin1String("list-dictionaries"), this); + + m_selectedDict = QStringLiteral("wn"); // for testing, use e.g. fd-fra-eng + m_webProfile = new QQuickWebEngineProfile(this); + m_webProfile->installUrlSchemeHandler("dict", new DictSchemeHandler(this, this)); +} + +void DictObject::lookup(const QString &word) +{ + const QString newSource = m_selectedDict + ':' + word; + + if (!m_source.isEmpty()) { + dataEngine(m_dataEngine)->disconnectSource(m_source, this); + } + + if (!newSource.isEmpty()) { + // Look up new definition + emit searchInProgress(); + m_source = newSource; + dataEngine(m_dataEngine)->connectSource(m_source, this); + } +} + +void DictObject::dataUpdated(const QString &sourceName, const Plasma::DataEngine::Data &data) +{ + if (sourceName == QLatin1String("list-dictionaries")) { + m_availableDicts = {}; + m_availableDicts.resize(data.count()); + int i = 0; + for (auto it = data.begin(), end = data.end(); it != end; ++it, ++i) { + m_availableDicts[i] = AvailableDict{it.key(), it.value().toString()}; + } + } else { + const QString html = data.value(QStringLiteral("text")).toString(); + if (!html.isEmpty()) { + emit definitionFound(html); + } + } +} + +QQuickWebEngineProfile* DictObject::webProfile() const +{ + return m_webProfile; +} diff --git a/applets/dict/plugin/dict_plugin.h b/applets/dict/plugin/dict_plugin.h new file mode 100644 --- /dev/null +++ b/applets/dict/plugin/dict_plugin.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2015 Dominik Haumann + * Copyright (C) 2017 David Faure + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef DICT_PLUGIN_H +#define DICT_PLUGIN_H + +#include +#include + +class DictPlugin : public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + +public: + void registerTypes(const char *uri) Q_DECL_OVERRIDE; +}; + +#endif diff --git a/applets/dict/plugin/dict_plugin.cpp b/applets/dict/plugin/dict_plugin.cpp new file mode 100644 --- /dev/null +++ b/applets/dict/plugin/dict_plugin.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2015 Dominik Haumann + * Copyright (C) 2017 David Faure + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "dict_plugin.h" +#include "dict_object.h" + +#include + +void DictPlugin::registerTypes (const char *uri) +{ + Q_ASSERT(uri == QLatin1String("org.kde.plasma.private.dict")); + qmlRegisterType(uri, 1, 0, "DictObject"); +} diff --git a/applets/dict/plugin/qmldir b/applets/dict/plugin/qmldir new file mode 100644 --- /dev/null +++ b/applets/dict/plugin/qmldir @@ -0,0 +1,3 @@ +module org.kde.plasma.private.dict +plugin dictplugin +