diff --git a/.gitignore b/.gitignore index 5058266b2..81e56f239 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +*.swp # / /ChangeLog @@ -31,7 +32,6 @@ /byeoru-data/Makefile /byeoru-data/Makefile.in - # /doc/ /doc/Makefile.in /doc/Makefile @@ -501,6 +501,71 @@ /qt4/toolbar/uim-toolbar-qt4.pro /qt4/toolbar/*.o +# /qt5/ +/qt5/Makefile +/qt5/Makefile.in + +# /qt5/candwin/ +/qt5/candwin/Makefile +/qt5/candwin/Makefile.in +/qt5/candwin/Makefile.qmake +/qt5/candwin/moc_*.cpp +/qt5/candwin/uim-candwin-qt5 +/qt5/candwin/uim-candwin-qt5.pro +/qt5/candwin/*.o + +# /qt5/chardict/ +/qt5/chardict/Makefile +/qt5/chardict/Makefile.in +/qt5/chardict/Makefile.qmake +/qt5/chardict/moc_*.cpp +/qt5/chardict/uim-chardict-qt5 +/qt5/chardict/uim-chardict-qt5.pro +/qt5/chardict/*.o + +# /qt5/edittest/ +/qt5/edittest/Makefile +/qt5/edittest/Makefile.in +/qt5/edittest/Makefile.qmake +/qt5/edittest/edittest +/qt5/edittest/*.o + +# /qt5/immodule/ +/qt5/immodule/Makefile +/qt5/immodule/Makefile.in +/qt5/immodule/Makefile.qmake +/qt5/immodule/libuimplatforminputcontextplugin.so +/qt5/immodule/moc_*.cpp +/qt5/immodule/quimplatforminputcontextplugin.pro +/qt5/immodule/*.o + +# /qt5/pref/ +/qt5/pref/Makefile +/qt5/pref/Makefile.in +/qt5/pref/Makefile.qmake +/qt5/pref/moc_*.cpp +/qt5/pref/uim-pref-qt5 +/qt5/pref/uim-pref-qt5.pro +/qt5/pref/*.o + +# /qt5/switcher/ +/qt5/switcher/Makefile +/qt5/switcher/Makefile.in +/qt5/switcher/Makefile.qmake +/qt5/switcher/moc_*.cpp +/qt5/switcher/uim-im-switcher-qt5 +/qt5/switcher/uim-im-switcher-qt5.pro +/qt5/switcher/*.o + +# /qt5/toolbar/ +/qt5/toolbar/Makefile +/qt5/toolbar/Makefile.in +/qt5/toolbar/Makefile.qmake +/qt5/toolbar/moc_*.cpp +/qt5/toolbar/uim-toolbar-qt5 +/qt5/toolbar/uim-toolbar-qt5.pro +/qt5/toolbar/*.o + # /replace/ /replace/.deps/ /replace/.libs/ diff --git a/Makefile.am b/Makefile.am index 609bc2329..07b9c6397 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,8 +2,7 @@ AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 SUBDIRS = m4 doc replace sigscheme uim scm test test2 \ - gtk2 gtk3 qt3 notify -SUBDIRS += qt4 + gtk2 gtk3 qt3 qt4 qt5 notify SUBDIRS += xim fep emacs po pixmaps examples tables byeoru-data EXTRA_DIST = RELNOTE ChangeLog.old ChangeLog.old.2 autogen.sh make-dist.sh \ diff --git a/configure.ac b/configure.ac index 5fd5d3f5c..1f67c6324 100644 --- a/configure.ac +++ b/configure.ac @@ -36,6 +36,7 @@ AC_PATH_PROGS(MD5, md5 md5sum) AC_PATH_PROGS(SHA1, sha1 sha1sum) AC_PATH_PROGS(SED, sed gsed) AX_PATH_QMAKE4 +AX_PATH_QMAKE5 AM_MAINTAINER_MODE @@ -1019,10 +1020,56 @@ case "$enable_qt4_qt3support" in ;; esac +dnl ***************************** +dnl *** Check for Qt5 Library *** +dnl ***************************** +AC_ARG_WITH(qt5, + AC_HELP_STRING([--with-qt5], + [build qt5 helper applications + @<:@default=no@:>@]), + [ + case $with_qt5 in + no) + use_qt5="no" + ;; + yes|*) + use_qt5="yes" + ;; + esac + ], + [ + use_qt5="no" + ]) + + +AC_ARG_WITH(qt5-immodule, + AC_HELP_STRING([--with-qt5-immodule], + [Build qt5-immodule extension + @<:@default=no@:>@]), + [ + case $with_qt5_immodule in + no) + use_qt5_immodule="no" + ;; + yes|*) + use_qt5_immodule="yes" + ;; + esac + + ], + [ + use_qt5_immodule="no" + ]) +if test x$use_qt5 = xyes || test x$use_qt5_immodule = xyes; then + if test -z "$QMAKE5"; then + AC_MSG_ERROR([no qmake for Qt5 found]) + fi +fi + default_toolkit="gtk" AC_ARG_ENABLE(default-toolkit, AC_HELP_STRING([--enable-default-toolkit], - [Determine default toolkit (gtk, gtk3, qt, or qt4) + [Determine default toolkit (gtk, gtk3, qt, qt4 or qt5) @<:@default=gtk@:>@]), [ if test x"$enable_default_toolkit" = "xgtk" && test x"$use_gtk2" = "xyes"; then @@ -1037,6 +1084,9 @@ AC_ARG_ENABLE(default-toolkit, if test x"$enable_default_toolkit" = "xqt4" && test x"$use_qt4" = "xyes"; then default_toolkit="qt4" fi + if test x"$enable_default_toolkit" = "xqt5" && test x"$use_qt5" = "xyes"; then + default_toolkit="qt5" + fi ], []) @@ -1268,6 +1318,7 @@ AM_CONDITIONAL(DEFAULT_TOOLKIT_GTK, test x$default_toolkit = xgtk) AM_CONDITIONAL(DEFAULT_TOOLKIT_GTK3, test x$default_toolkit = xgtk3) AM_CONDITIONAL(DEFAULT_TOOLKIT_QT, test x$default_toolkit = xqt) AM_CONDITIONAL(DEFAULT_TOOLKIT_QT4, test x$default_toolkit = xqt4) +AM_CONDITIONAL(DEFAULT_TOOLKIT_QT5, test x$default_toolkit = xqt5) AM_CONDITIONAL(APPLET_GNOME, test x$use_applet_gnome = xyes) AM_CONDITIONAL(APPLET_GNOME3, test x$use_applet_gnome3 = xyes) AM_CONDITIONAL(UIM_FEP, test x$use_uim_fep = xyes) @@ -1533,7 +1584,7 @@ if test "x$use_applet_kde4" = "xyes" && test "x$CMAKE" = "xno"; then use_applet_kde4="no" fi AC_PATH_PROG(KDE4_CONFIG, [kde4-config], [no]) -if test "x$use_qt4" = "xyes"; then +if test "x$use_qt4" = "xyes" || test "x$use_qt5" = "xyes"; then if test "x$KDE4_CONFIG" != "xno"; then KDE4_ICONDIR=`$KDE4_CONFIG --expandvars --install icon` fi @@ -1565,6 +1616,8 @@ AM_CONDITIONAL(APPLET_KDE, test x$use_applet_kde = xyes) AM_CONDITIONAL(QT4, test x$use_qt4 = xyes) AM_CONDITIONAL(QT4_IMMODULE, test x$use_qt4_immodule = xyes) AM_CONDITIONAL(APPLET_KDE4, test x$use_applet_kde4 = xyes) +AM_CONDITIONAL(QT5, test x$use_qt5 = xyes) +AM_CONDITIONAL(QT5_IMMODULE, test x$use_qt5_immodule = xyes) AC_ARG_ENABLE(pref, AC_HELP_STRING([--enable-pref], @@ -1588,6 +1641,9 @@ AC_ARG_ENABLE(pref, elif test x"$default_toolkit" = "xqt4" && \ test x"$use_qt4" = "xyes"; then use_pref="yes" + elif test x"$default_toolkit" = "xqt5" && \ + test x"$use_qt5" = "xyes"; then + use_pref="yes" else use_pref="no" AC_MSG_WARN([uim-pref needs Gtk+ or Qt toolkit, disabled...]) @@ -1607,6 +1663,9 @@ AC_ARG_ENABLE(pref, elif test x"$default_toolkit" = "xqt4" && \ test x"$use_qt4" = "xyes"; then use_pref="yes" + elif test x"$default_toolkit" = "xqt5" && \ + test x"$use_qt5" = "xyes"; then + use_pref="yes" else use_pref="no" AC_MSG_WARN([uim pref needs Gtk+ or Qt toolkit, disabled...]) @@ -1971,6 +2030,20 @@ AC_CONFIG_FILES([Makefile qt4/toolbar/plasma-applet-uim.desktop qt4/toolbar/uim-toolbar-qt4.pro qt4/toolbar/Makefile + qt5/Makefile + qt5/candwin/Makefile + qt5/candwin/uim-candwin-qt5.pro + qt5/chardict/Makefile + qt5/chardict/uim-chardict-qt5.pro + qt5/edittest/Makefile + qt5/immodule/quimplatforminputcontextplugin.pro + qt5/immodule/Makefile + qt5/pref/uim-pref-qt5.pro + qt5/pref/Makefile + qt5/switcher/uim-im-switcher-qt5.pro + qt5/switcher/Makefile + qt5/toolbar/uim-toolbar-qt5.pro + qt5/toolbar/Makefile xim/Makefile fep/Makefile emacs/Makefile @@ -2052,6 +2125,30 @@ if test "x$use_knotify4" = xyes; then ${cmake_option} ${ac_abs_top_srcdir}/notify cd - fi +# Generate Makefiles for Qt5 by qmake +if test x$use_qt5 = xyes; then + if test x$use_qt5_immodule = xyes; then + qt5_immodule_option="DEFINES+=QT5_IMMODULE" + fi + ${QMAKE5} -o ${ac_abs_top_builddir}/qt5/candwin/Makefile.qmake \ + ${ac_abs_top_builddir}/qt5/candwin/uim-candwin-qt5.pro + ${QMAKE5} -o ${ac_abs_top_builddir}/qt5/chardict/Makefile.qmake \ + ${ac_abs_top_builddir}/qt5/chardict/uim-chardict-qt5.pro + ${QMAKE5} -o ${ac_abs_top_builddir}/qt5/pref/Makefile.qmake \ + ${qt5_immodule_option} \ + ${ac_abs_top_builddir}/qt5/pref/uim-pref-qt5.pro + ${QMAKE5} -o ${ac_abs_top_builddir}/qt5/switcher/Makefile.qmake \ + ${ac_abs_top_builddir}/qt5/switcher/uim-im-switcher-qt5.pro + ${QMAKE5} -o ${ac_abs_top_builddir}/qt5/toolbar/Makefile.qmake \ + ${ac_abs_top_builddir}/qt5/toolbar/uim-toolbar-qt5.pro +fi +if test x$use_qt5_immodule = xyes; then + ${QMAKE5} -o ${ac_abs_top_builddir}/qt5/immodule/Makefile.qmake \ + ${ac_abs_top_builddir}/qt5/immodule/quimplatforminputcontextplugin.pro + ${QMAKE5} -o ${ac_abs_top_builddir}/qt5/edittest/Makefile.qmake \ + ${ac_abs_top_srcdir}/qt4/edittest/edittest.pro +fi + AC_MSG_RESULT([ Configure Result : @@ -2080,6 +2177,8 @@ Configure Result : Qt4 : ${use_qt4} Qt4 immodule : ${use_qt4_immodule} Qt4 Qt3Support : ${use_qt4_qt3support} + Qt5 : ${use_qt5} + Qt5 immodule : ${use_qt5_immodule} KDE3 Applet : ${use_applet_kde} KDE4 Applet : ${use_applet_kde4} FEP : ${use_uim_fep} diff --git a/m4/Makefile.am b/m4/Makefile.am index e7f2db520..7543d82f9 100644 --- a/m4/Makefile.am +++ b/m4/Makefile.am @@ -6,6 +6,7 @@ EXTRA_DIST = \ ax_func_sigsetjmp.m4 \ ax_lib_glibc.m4 \ ax_path_qmake4.m4 \ + ax_path_qmake5.m4 \ codeset.m4 \ gettext.m4 \ glibc21.m4 \ diff --git a/m4/ax_path_qmake5.m4 b/m4/ax_path_qmake5.m4 new file mode 100644 index 000000000..fc23f5ca9 --- /dev/null +++ b/m4/ax_path_qmake5.m4 @@ -0,0 +1,39 @@ +##### +# +# SYNOPSIS +# +# AX_PATH_QMAKE5 +# +# DESCRIPTION +# +# Check for Qt5 version of qmake. +# +# $QMAKE5 is set to absolute name of the executable if found. +# +# COPYLEFT +# +# Copyright (c) 2007 YAMAMOTO Kengo +# Copyright (c) 2012 Muneyuki Noguchi +# +# Copying and distribution of this file, with or without +# modification, are permitted in any medium without royalty provided +# the copyright notice and this notice are preserved. + +AC_DEFUN([AX_PATH_QMAKE5], [ + ax_guessed_qt5_dirs="/usr/lib/qt5/bin:/usr/local/lib/qt5/bin:/usr/qt5/bin:/usr/local/qt5/bin:${QT5DIR}/bin:${QTDIR}/bin" + AC_PROG_EGREP + AC_PATH_PROGS(_QMAKE5, [qmake-qt5 qmake5], [], ["$PATH:$ax_guessed_qt5_dirs"]) + AC_PATH_PROGS(_QMAKE, [qmake], [], ["$PATH:$ax_guessed_qt5_dirs"]) + + AC_CACHE_CHECK([for Qt5 version of qmake], ax_cv_path_QMAKE5, [ + ax_cv_path_QMAKE5=no + for qmake5 in ${_QMAKE5} ${_QMAKE}; do + if ($qmake5 --version 2>&1 | $EGREP -q 'Qt version 5'); then + QMAKE5="$qmake5" + ax_cv_path_QMAKE5="$qmake5" + break + fi + done + ]) + AC_SUBST([QMAKE5]) +]) diff --git a/make-dist.sh b/make-dist.sh index 0d4d8821b..48af6256e 100755 --- a/make-dist.sh +++ b/make-dist.sh @@ -26,7 +26,7 @@ fi # --without-scim since it is broken # --without-qt -CONF_FULL_WO_MAINT="$CONF_NOWERROR --enable-debug --enable-fep --enable-emacs --enable-gnome-applet --enable-gnome3-applet --enable-kde-applet --enable-kde4-applet --enable-pref --enable-dict --enable-notify=libnotify,knotify4 --with-anthy --with-canna --with-wnn --with-sj3 --with-mana --with-prime --with-m17nlib --without-scim --with-gtk2 --with-gtk3 --without-qt --without-qt-immodule --enable-compat-scm --with-eb --with-eb-conf=$EB_CONF --with-libedit --with-qt4 --with-qt4-immodule" +CONF_FULL_WO_MAINT="$CONF_NOWERROR --enable-debug --enable-fep --enable-emacs --enable-gnome-applet --enable-gnome3-applet --enable-kde-applet --enable-kde4-applet --enable-pref --enable-dict --enable-notify=libnotify,knotify4 --with-anthy --with-canna --with-wnn --with-sj3 --with-mana --with-prime --with-m17nlib --without-scim --with-gtk2 --with-gtk3 --without-qt --without-qt-immodule --enable-compat-scm --with-eb --with-eb-conf=$EB_CONF --with-libedit --with-qt4 --with-qt4-immodule --with-qt5 --with-qt5-immodule" CONF_FULL="$CONF_MAINT $CONF_FULL_WO_MAINT" git submodule update --init --recursive diff --git a/qt4/candwin/Makefile.am b/qt4/candwin/Makefile.am index e9f2f70c6..30d39909e 100644 --- a/qt4/candwin/Makefile.am +++ b/qt4/candwin/Makefile.am @@ -17,5 +17,12 @@ endif FORCE: EXTRA_DIST = uim-candwin-qt4.pro.in \ - qt4.h \ - qt4.cpp + abstractcandidatewindow.h \ + abstractcandidatewindow.cpp \ + candidatetablewindow.h \ + candidatetablewindow.cpp \ + candidatewindow.h \ + candidatewindow.cpp \ + subwindow.h \ + subwindow.cpp \ + qt4.cpp diff --git a/qt4/candwin/abstractcandidatewindow.cpp b/qt4/candwin/abstractcandidatewindow.cpp new file mode 100644 index 000000000..d49ecfae8 --- /dev/null +++ b/qt4/candwin/abstractcandidatewindow.cpp @@ -0,0 +1,197 @@ +/* + + copyright (c) 2010-2012 uim Project http://code.google.com/p/uim/ + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of authors nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +*/ +#include "abstractcandidatewindow.h" + +#include +#include +#if QT_VERSION < 0x050000 +# include +# include +# include +#else +# include +# include +# include +#endif + +#include "util.h" + +const Qt::WindowFlags candidateFlag = (Qt::Window + | Qt::WindowStaysOnTopHint + | Qt::FramelessWindowHint + | Qt::Tool +#if defined(Q_WS_X11) + | Qt::X11BypassWindowManagerHint +#endif + ); + +AbstractCandidateWindow::AbstractCandidateWindow(QWidget *parent) +: QFrame(parent, candidateFlag) +{ + setFrameStyle(Raised|NoFrame); + + // setup NumberLabel + numLabel = new QLabel; + numLabel->adjustSize(); + + notifier = new QSocketNotifier(0, QSocketNotifier::Read); + connect(notifier, SIGNAL(activated(int)), + this, SLOT(slotStdinActivated(int))); +} + +AbstractCandidateWindow::~AbstractCandidateWindow() +{ +} + +void AbstractCandidateWindow::setupSubWindow() +{ +} + +void AbstractCandidateWindow::shiftPage(int idx) +{ + Q_UNUSED(idx) +} + +#ifdef WORKAROUND_BROKEN_RESET_IN_QT4 +void AbstractCandidateWindow::showEvent(QShowEvent *event) +{ + QFrame::showEvent(event); + + fprintf(stdout, "shown\f\f"); + fflush(stdout); +} + +void AbstractCandidateWindow::hideEvent(QHideEvent *event) +{ + QFrame::hideEvent(event); + fprintf(stdout, "hidden\f\f"); + fflush(stdout); +} +#endif + +void AbstractCandidateWindow::slotStdinActivated(int fd) +{ + QList messageList = parse_messages(get_messages(fd)); + for (int i = 0, j = messageList.count(); i < j; i++) { + QStringList message = messageList[i]; + QString command = message[0]; + if (command == "candidate_activate") + candidateActivate(); + else if (command == "hide") + hide(); + else if (command == "layout_window") + layoutWindow(message[1].toInt(), message[2].toInt(), + message[3].toInt()); + else if (command == "move_candwin") + moveCandwin(message[1].toInt(), message[2].toInt()); + else if (command == "popup") + popup(); + else if (command == "set_index") + setIndex(message[1].toInt(), message[2].toInt(), + message[3].toInt()); + else if (command == "setup_sub_window") + setupSubWindow(); + else if (command == "shift_page") + shiftPage(message[1].toInt()); + else if (command == "update_label") + updateLabel(message[1]); + else if (command == "update_size") + updateSize(); + else if (command == "update_view") + updateView(message[1].toInt(), candidateData(message)); + } +} + +QList AbstractCandidateWindow::candidateData( + const QStringList &message) +{ + QList stores; + for (int i = 2, j = message.count(); i < j; i++) { + QStringList candidate = message[i].split('\a'); + + int count = candidate.count(); + if (count < 3) + continue; + + CandData cand; + cand.headingLabel = candidate[0]; + cand.str = candidate[1]; + cand.annotation = candidate[2]; + + stores.append(cand); + } + return stores; +} + +void AbstractCandidateWindow::popup() +{ + fprintf(stdout, "set_focus_widget\f\f"); + fflush(stdout); + raise(); + show(); +} + +void AbstractCandidateWindow::layoutWindow(int x, int y, int h) +{ + int destX = x; + int destY = y + h; + + int screenW = QApplication::desktop()->screenGeometry().width(); + int screenH = QApplication::desktop()->screenGeometry().height(); + + if (destX + width() > screenW) + destX = screenW - width(); + + if (destY + height() > screenH) + destY = y - height(); + + move(destX, destY); +} + +void AbstractCandidateWindow::moveCandwin(int x, int y) +{ + QPoint p = pos(); + move(p.x() + x, p.y() + y); +} + +void AbstractCandidateWindow::candidateActivate() +{ + popup(); + fprintf(stdout, "set_candwin_active\f\f"); + fflush(stdout); +} + +void AbstractCandidateWindow::updateLabel(const QString &indexString) +{ + numLabel->setText(indexString); +} diff --git a/qt4/candwin/abstractcandidatewindow.h b/qt4/candwin/abstractcandidatewindow.h new file mode 100644 index 000000000..ad1ff3983 --- /dev/null +++ b/qt4/candwin/abstractcandidatewindow.h @@ -0,0 +1,90 @@ +/* + + copyright (c) 2010-2012 uim Project http://code.google.com/p/uim/ + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of authors nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +*/ +#ifndef UIM_QT4_IMMODULE_ABSTRACT_CANDIDATE_WINDOW_H +#define UIM_QT4_IMMODULE_ABSTRACT_CANDIDATE_WINDOW_H + +#include +#if QT_VERSION < 0x050000 +# include +#else +# include +#endif + +#include + +#include "util.h" + +class QLabel; +class QSocketNotifier; + +class AbstractCandidateWindow : public QFrame +{ + Q_OBJECT + + public: + explicit AbstractCandidateWindow(QWidget *parent); + virtual ~AbstractCandidateWindow(); + + protected: + virtual void setupSubWindow(); + + virtual void shiftPage(int idx); + virtual void setIndex(int totalindex, int displayLimit, + int candidateIndex) = 0; + virtual void updateView(int ncandidates, + const QList &stores) = 0; + virtual void updateSize() = 0; + +#ifdef WORKAROUND_BROKEN_RESET_IN_QT4 + virtual void showEvent(QShowEvent *event); + virtual void hideEvent(QHideEvent *event); +#endif + + // widget + QLabel *numLabel; + + private slots: + void slotStdinActivated(int fd); + + private: + QList candidateData(const QStringList &message); + void popup(); + void layoutWindow(int x, int y, int height); + void moveCandwin(int x, int y); + void candidateActivate(); + void updateLabel(const QString &indexString); + + QSocketNotifier *notifier; +}; + +#endif /* Not def: UIM_QT4_IMMODULE_ABSTRACT_CANDIDATE_WINDOW_H */ diff --git a/qt4/immodule/candidatetablewindow.cpp b/qt4/candwin/candidatetablewindow.cpp similarity index 91% rename from qt4/immodule/candidatetablewindow.cpp rename to qt4/candwin/candidatetablewindow.cpp index 3fe31ef1f..23a0c919b 100644 --- a/qt4/immodule/candidatetablewindow.cpp +++ b/qt4/candwin/candidatetablewindow.cpp @@ -32,16 +32,23 @@ */ #include "candidatetablewindow.h" -#include +#include + #include -#include -#include -#include +#if QT_VERSION < 0x050000 +# include +# include +# include +# include +#else +# include +# include +# include +# include +#endif #include -#include "quiminputcontext.h" - static const int TABLE_NR_CELLS = TABLE_NR_COLUMNS * TABLE_NR_ROWS; static const int BLOCK_SPACING = 20; @@ -134,9 +141,10 @@ QSize CandidateTableWindow::sizeHint() const void CandidateTableWindow::slotCandidateClicked(int index) { - if (ic && ic->uimContext()) - uim_set_candidate_index(ic->uimContext(), index); - updateLabel(); + fprintf(stdout, "set_candidate_index\f%d\f\f", index); + fflush(stdout); + fprintf(stdout, "update_label\f\f"); + fflush(stdout); } static char *initTableInternal() @@ -229,7 +237,8 @@ void CandidateTableWindow::setBlockVisible(QLayout *layout, bool visible) } } -void CandidateTableWindow::updateView(int newpage, int ncandidates) +void CandidateTableWindow::updateView(int ncandidates, + const QList &stores) { for (int i = 0; i < TABLE_NR_ROWS; i++) { for (int j = 0; j < TABLE_NR_COLUMNS; j++) { @@ -250,15 +259,13 @@ void CandidateTableWindow::updateView(int newpage, int ncandidates) } if (index - delta >= ncandidates) continue; - int candidateIndex = displayLimit * newpage + index - delta; - uim_candidate cand = stores[candidateIndex]; - QString candString - = QString::fromUtf8(uim_candidate_get_cand_str(cand)); + int candidateIndex = index - delta; + CandData cand = stores[candidateIndex]; + QString candString = cand.str; if (!candString.isEmpty()) { int row = i; int column = j; - QString headString - = QString::fromUtf8(uim_candidate_get_heading_label(cand)); + QString headString = cand.headingLabel; getButtonPosition(row, column, headString); KeyButton *b = buttonArray[row][column]; // '&' shouldn't be used as the shortcut key @@ -297,10 +304,14 @@ void CandidateTableWindow::updateSize() setMinimumSize(QSize(0, 0)); } -void CandidateTableWindow::setIndex(int totalIndex) +void CandidateTableWindow::setIndex(int totalindex, int displayLimit, + int candidateIndex) { - AbstractCandidateWindow::setIndex(totalIndex); - updateLabel(); + Q_UNUSED(totalindex) + Q_UNUSED(displayLimit) + Q_UNUSED(candidateIndex) + fprintf(stdout, "update_label\f\f"); + fflush(stdout); } void CandidateTableWindow::getButtonPosition(int &row, int &column, diff --git a/qt4/immodule/candidatetablewindow.h b/qt4/candwin/candidatetablewindow.h similarity index 91% rename from qt4/immodule/candidatetablewindow.h rename to qt4/candwin/candidatetablewindow.h index 2b52a95fa..04e2806f7 100644 --- a/qt4/immodule/candidatetablewindow.h +++ b/qt4/candwin/candidatetablewindow.h @@ -33,7 +33,12 @@ #ifndef UIM_QT4_IMMODULE_CANDIDATE_TABLE_WINDOW_H #define UIM_QT4_IMMODULE_CANDIDATE_TABLE_WINDOW_H -#include +#include +#if QT_VERSION < 0x050000 +# include +#else +# include +#endif #include "abstractcandidatewindow.h" @@ -62,9 +67,9 @@ class CandidateTableWindow : public AbstractCandidateWindow QGridLayout *createLayout(int row, int column, int rowOffset, int columnOffset); void setBlockVisible(QLayout *layout, bool visible); - void updateView(int newpage, int ncandidates); + void updateView(int ncandidates, const QList &stores); void updateSize(); - void setIndex(int totalIndex); + void setIndex(int totalIndex, int displayLimit, int candidateIndex); void getButtonPosition(int &row, int &column, const QString &headString); diff --git a/qt4/candwin/candidatewindow.cpp b/qt4/candwin/candidatewindow.cpp new file mode 100644 index 000000000..17b15b4b1 --- /dev/null +++ b/qt4/candwin/candidatewindow.cpp @@ -0,0 +1,324 @@ +/* + +Copyright (c) 2003-2012 uim Project http://code.google.com/p/uim/ + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +3. Neither the name of authors nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +*/ +#include "candidatewindow.h" + +#include + +#include +#include +#if QT_VERSION < 0x050000 +# include +# include +# include +#else +# include +# include +# include +#endif + +#include + +#include "subwindow.h" + +static const int MIN_CAND_WIDTH = 80; + +static const int HEADING_COLUMN = 0; +static const int CANDIDATE_COLUMN = 1; +static const int ANNOTATION_COLUMN = 2; + +CandidateWindow::CandidateWindow(QWidget *parent, bool vertical) +: AbstractCandidateWindow(parent), subWin(0), + hasAnnotation(uim_scm_symbol_value_bool("enable-annotation?")), + isVertical(vertical) +{ + //setup CandidateList + cList = new CandidateListView(0, isVertical); + cList->setSelectionMode(QAbstractItemView::SingleSelection); + cList->setSelectionBehavior(isVertical + ? QAbstractItemView::SelectRows : QAbstractItemView::SelectColumns); + cList->setMinimumWidth(MIN_CAND_WIDTH); + if (isVertical) + // the last column is dummy for adjusting size. + cList->setColumnCount(hasAnnotation ? 4 : 3); + else + cList->setRowCount(2); + cList->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents); + cList->horizontalHeader()->setStretchLastSection(true); + if (!isVertical) { + cList->verticalHeader() + ->setResizeMode(QHeaderView::ResizeToContents); + cList->verticalHeader()->setStretchLastSection(true); + } + cList->horizontalHeader()->hide(); + cList->verticalHeader()->hide(); + cList->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + cList->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + cList->setAutoScroll(false); + cList->setShowGrid(false); + connect(cList, SIGNAL(cellClicked(int, int)), + this , SLOT(slotCandidateSelected(int, int))); + connect(cList, SIGNAL(itemSelectionChanged()), + this , SLOT(slotHookSubwindow())); + + QVBoxLayout *layout = new QVBoxLayout; + layout->setMargin(0); + layout->setSpacing(0); + layout->addWidget(cList); + layout->addWidget(numLabel); + setLayout(layout); +} + +void CandidateWindow::setupSubWindow() +{ + if (!subWin) + subWin = new SubWindow(this); +} + +void CandidateWindow::updateView(int ncandidates, + const QList &stores) +{ + cList->clearContents(); + annotations.clear(); + + if (isVertical) + cList->setRowCount(ncandidates); + else + // the last column is dummy for adjusting size. + cList->setColumnCount(ncandidates + 1); + for (int i = 0; i < ncandidates ; i++) { + CandData cand = stores[i]; + QString headString = cand.headingLabel; + QString candString = cand.str; + QString annotationString; + if (hasAnnotation) { + annotationString = cand.annotation; + annotations.append(annotationString); + } + + // insert new item to the candidate list + if (isVertical) { + QTableWidgetItem *headItem = new QTableWidgetItem; + headItem->setText(headString); + headItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + + QTableWidgetItem *candItem = new QTableWidgetItem; + candItem->setText(candString); + candItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + + cList->setItem(i, HEADING_COLUMN, headItem); + cList->setItem(i, CANDIDATE_COLUMN, candItem); + + if (hasAnnotation) { + QTableWidgetItem *annotationItem = new QTableWidgetItem; + annotationItem->setFlags( + Qt::ItemIsSelectable | Qt::ItemIsEnabled); + if (!annotationString.isEmpty()) + annotationItem->setText("..."); + + cList->setItem(i, ANNOTATION_COLUMN, annotationItem); + } + cList->setRowHeight(i, + QFontMetrics(cList->font()).height() + 2); + } else { + QTableWidgetItem *candItem = new QTableWidgetItem; + candItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + + QString candText = headString + ": " + candString; + if (hasAnnotation && !annotationString.isEmpty()) + candText += "..."; + candItem->setText(candText); + + cList->setItem(0, i, candItem); + } + } + if (!isVertical) + cList->setRowHeight(0, QFontMetrics(cList->font()).height() + 2); +} + +void CandidateWindow::updateSize() +{ + // size adjustment + cList->updateGeometry(); + setFixedSize(sizeHint()); +} + +void CandidateWindow::setIndex(int totalindex, int displayLimit, + int candidateIndex) +{ + // select item + if (candidateIndex >= 0) { + int pos = totalindex; + if (displayLimit) + pos = candidateIndex % displayLimit; + + int row; + int column; + if (isVertical) { + row = pos; + column = 0; + } else { + row = 0; + column = pos; + } + if (cList->item(row, column) + && !cList->item(row, column)->isSelected()) { + cList->clearSelection(); + if (isVertical) + cList->selectRow(pos); + else + cList->selectColumn(pos); + } + } else { + cList->clearSelection(); + } + + fprintf(stdout, "update_label\f\f"); + fflush(stdout); +} + +void CandidateWindow::slotCandidateSelected(int row, int column) +{ + fprintf(stdout, "set_candidate_index_2\f%d\f\f", isVertical ? row : column); + fflush(stdout); + fprintf(stdout, "update_label\f\f"); + fflush(stdout); +} + +void CandidateWindow::shiftPage(int idx) +{ + cList->clearSelection(); + if (isVertical) + cList->selectRow(idx); + else + cList->selectColumn(idx); +} + +void CandidateWindow::slotHookSubwindow() +{ + if (!hasAnnotation || !subWin) + return; + + QList list = cList->selectedItems(); + if (list.isEmpty()) + return; + QTableWidgetItem *item = list[0]; + + // cancel previous hook + subWin->cancelHook(); + + // hook annotation + QString annotationString + = annotations.at(isVertical ? item->row() : item->column()); + if (!annotationString.isEmpty()) { + subWin->layoutWindow(subWindowRect(frameGeometry(), item), + isVertical); + subWin->hookPopup(annotationString); + } +} + +// Moving and Resizing affects the position of Subwindow +void CandidateWindow::moveEvent(QMoveEvent *e) +{ + // move subwindow + if (subWin) + subWin->layoutWindow(subWindowRect(QRect(e->pos(), size())), + isVertical); +} + +void CandidateWindow::resizeEvent(QResizeEvent *e) +{ + // move subwindow + if (subWin) + subWin->layoutWindow(subWindowRect(QRect(pos(), e->size())), + isVertical); +} + +void CandidateWindow::hideEvent(QHideEvent *event) +{ + AbstractCandidateWindow::hideEvent(event); + if (subWin) + subWin->cancelHook(); +} + +QRect CandidateWindow::subWindowRect(const QRect &rect, + const QTableWidgetItem *item) +{ + if (!item) { + QList list = cList->selectedItems(); + if (list.isEmpty()) + return rect; + item = list[0]; + } + QRect r = rect; + if (isVertical) { + r.setY(rect.y() + cList->rowHeight(0) * item->row()); + } else { + int xdiff = 0; + for (int i = 0, j = item->column(); i < j; i++) { + xdiff += cList->columnWidth(i); + } + r.setX(rect.x() + xdiff); + } + return r; +} + +QSize CandidateWindow::sizeHint() const +{ + QSize cListSizeHint = cList->sizeHint(); + + // According to the Qt4 documentation on the QFrame class, + // the frame width is 1 pixel. + int frame = 1 * 2; + int width = cListSizeHint.width() + frame; + int height = cListSizeHint.height() + numLabel->height() + frame; + + return QSize(width, height); +} + +QSize CandidateListView::sizeHint() const +{ + // frame width + int frame = style()->pixelMetric(QStyle::PM_DefaultFrameWidth) * 2; + + // the size of the dummy row should be 0. + const int rowNum = isVertical ? rowCount() : rowCount() - 1; + if (rowNum == 0) { + return QSize(MIN_CAND_WIDTH, frame); + } + int width = frame; + // the size of the dummy column should be 0. + for (int i = 0; i < columnCount() - 1; i++) + width += columnWidth(i); + + return QSize(width, rowHeight(0) * rowNum + frame); +} diff --git a/qt4/immodule/candidatewindow.h b/qt4/candwin/candidatewindow.h similarity index 74% rename from qt4/immodule/candidatewindow.h rename to qt4/candwin/candidatewindow.h index b34bf2402..06e299f35 100644 --- a/qt4/immodule/candidatewindow.h +++ b/qt4/candwin/candidatewindow.h @@ -33,7 +33,12 @@ SUCH DAMAGE. #ifndef UIM_QT4_IMMODULE_CANDIDATE_WINDOW_H #define UIM_QT4_IMMODULE_CANDIDATE_WINDOW_H -#include +#include +#if QT_VERSION < 0x050000 +# include +#else +# include +#endif #include "abstractcandidatewindow.h" @@ -45,30 +50,28 @@ class CandidateWindow : public AbstractCandidateWindow Q_OBJECT public: - explicit CandidateWindow( QWidget *parent, bool vertical = true ); + explicit CandidateWindow(QWidget *parent, bool vertical = true); QSize sizeHint() const; private slots: - void slotCandidateSelected( int row, int column ); + void slotCandidateSelected(int row, int column); void slotHookSubwindow(); private: - void activateCandwin( int dLimit ); + void setupSubWindow(); - void updateView( int newpage, int ncandidates ); + void updateView(int ncandidates, const QList &stores); void updateSize(); - void shiftPage( bool forward ); - void setIndex( int totalindex ); - - void setNrCandidates( int nrCands, int dLimit ); + void shiftPage(int idx); + void setIndex(int totalindex, int displayLimit, int candidateIndex); // Moving and Resizing affects the position of Subwindow - virtual void moveEvent( QMoveEvent * ); - virtual void resizeEvent( QResizeEvent * ); - virtual void hideEvent( QHideEvent *event ); + virtual void moveEvent(QMoveEvent *); + virtual void resizeEvent(QResizeEvent *); + virtual void hideEvent(QHideEvent *event); - QRect subWindowRect( const QRect &rect, const QTableWidgetItem *item = 0 ); + QRect subWindowRect(const QRect &rect, const QTableWidgetItem *item = 0); // widgets CandidateListView *cList; @@ -88,8 +91,8 @@ class CandidateListView : public QTableWidget Q_OBJECT public: - explicit CandidateListView( QWidget *parent = 0, bool vertical = true ) - : QTableWidget( parent ), isVertical( vertical ) {} + explicit CandidateListView(QWidget *parent = 0, bool vertical = true) + : QTableWidget(parent), isVertical(vertical) {} ~CandidateListView() {} QSize sizeHint() const; diff --git a/qt4/candwin/qt4.cpp b/qt4/candwin/qt4.cpp index be0d91759..dae40fa39 100644 --- a/qt4/candwin/qt4.cpp +++ b/qt4/candwin/qt4.cpp @@ -32,8 +32,6 @@ */ #include -#include "qt4.h" - #include #include #include @@ -43,565 +41,75 @@ #include #include #include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "qtgettext.h" - -static const int NR_CANDIDATES = 10; -static const int MIN_CAND_WIDTH = 80; - -static const int HEADING_COLUMN = 0; -static const int CANDIDATE_COLUMN = 1; - -const Qt::WindowFlags candidateFlag = ( Qt::Window - | Qt::WindowStaysOnTopHint - | Qt::FramelessWindowHint - | Qt::Tool -#if defined(Q_WS_X11) - | Qt::X11BypassWindowManagerHint -#endif - ); -static QSocketNotifier *notifier = 0; - -CandidateWindow::CandidateWindow( QWidget *parent ) -: QFrame( parent, candidateFlag ), nrCandidates( 0 ), candidateIndex( 0 ), - displayLimit( NR_CANDIDATES ), pageIndex( -1 ), isActive( false ) -{ - setFrameStyle( Raised | NoFrame ); - setFocusPolicy( Qt::NoFocus ); - - //setup CandidateList - cList = new QTableWidget; - cList->setSelectionMode( QAbstractItemView::SingleSelection ); - cList->setSelectionBehavior( QAbstractItemView::SelectRows ); - // the last column is dummy for adjusting size. - cList->setColumnCount( 3 ); - cList->horizontalHeader()->setResizeMode( QHeaderView::ResizeToContents ); - cList->horizontalHeader()->setStretchLastSection( true ); - cList->horizontalHeader()->hide(); - cList->verticalHeader()->hide(); - cList->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); - cList->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); - cList->setAutoScroll( false ); - cList->setShowGrid( false ); - cList->setMinimumWidth( MIN_CAND_WIDTH ); - connect( cList, SIGNAL( cellClicked( int, int ) ), - this , SLOT( slotCandidateSelected( int ) ) ); - - //setup NumberLabel - numLabel = new QLabel; - numLabel->setFocusPolicy( Qt::NoFocus ); - numLabel->adjustSize(); - - notifier = new QSocketNotifier( 0, QSocketNotifier::Read ); - connect( notifier, SIGNAL( activated( int ) ), - this, SLOT( slotStdinActivated( int ) ) ); - QVBoxLayout *layout = new QVBoxLayout; - layout->setMargin( 0 ); - layout->setSpacing( 0 ); - layout->addWidget( cList ); - layout->addWidget( numLabel ); - setLayout( layout ); - - hide(); -} - -CandidateWindow::~CandidateWindow() -{ - if ( !stores.isEmpty() ) - stores.clear(); -} - -void CandidateWindow::activateCand( const QStringList &list ) -{ -#if defined(ENABLE_DEBUG) - qDebug( "uim-candwin-qt4: activateCand()" ); -#endif - /** - * format: activate\fcharset=$charset\fdisplay_limit=$value\fhead1\acand1\aannot1\fhead2\acand2\aannot2\fhead3\acand3\aannot3\f - */ - - // remove old data - cList->clearContents(); - cList->setRowCount( 0 ); - stores.clear(); - - // get charset and create codec - QTextCodec *codec = 0; - if ( !list[ 1 ].isEmpty() - && list[ 1 ].startsWith( QLatin1String( "charset" ) ) ) - { - const QStringList l = list[ 1 ].split( '=', QString::SkipEmptyParts ); - codec = QTextCodec::codecForName( l[ 1 ].toAscii() ); - } - - // get display_limit - if ( !list[ 2 ].isEmpty() - && list[ 2 ].startsWith( QLatin1String( "display_limit" ) ) ) - { - const QStringList l = list[ 2 ].split( '=', QString::SkipEmptyParts ); - displayLimit = l[ 1 ].toInt(); - } - - for ( int i = 3; !list[ i ].isNull(); i++ ) - { - // case list[i] = "" - if ( list[ i ].isEmpty() ) - break; - - // split heading_label and cand_str - QStringList l = list[ i ].split( '\a' ); - - // store data - CandData d; - QString headString; - if ( codec ) - headString = codec->toUnicode( l[ 0 ].toAscii() ); - else - headString = l [ 0 ]; - - d.label = headString; - - l.pop_front(); - QString candString = l [ 0 ]; - - if ( codec ) - d.str = codec->toUnicode( candString.toAscii() ); - else - d.str = candString; - - l.pop_front(); - QString annotString = l [ 0 ]; - - stores.append( d ); - } - - // set default value - candidateIndex = -1; - nrCandidates = stores.count(); - - // shift to default page - setPage( 0 ); - - adjustCandidateWindowSize(); - show(); - - isActive = true; -} -void CandidateWindow::selectCand( const QStringList &list ) -{ -#if defined(ENABLE_DEBUG) - qDebug( "uim-candwin-qt4: selectCand()" ); -#endif - const int index = list[ 1 ].toInt(); - needHighlight = (list[ 2 ].toInt() == 1); - setIndex( index ); - - updateLabel(); -} - -void CandidateWindow::moveCand( const QStringList &list ) -{ -#if defined(ENABLE_DEBUG) - qDebug( "uim-candwin-qt4: moveCand()" ); +#if QT_VERSION < 0x050000 +# include +# include +# include +# include +# include +# include +#else +# include +# include +# include +# include +# include +# include #endif - if ( list[ 1 ].isEmpty() || list[ 2 ].isEmpty() ) - return ; - - const int topwin_x = list[ 1 ].toInt(); - const int topwin_y = list[ 2 ].toInt(); - const int cw_wi = width(); - const int cw_he = height(); - const int sc_wi = QApplication::desktop() ->screenGeometry().width(); - const int sc_he = QApplication::desktop() ->screenGeometry().height(); - - int x, y; - if ( sc_wi < topwin_x + cw_wi ) - { - x = topwin_x - cw_wi; - } - else - { - x = topwin_x; - } - - if ( sc_he < topwin_y + cw_he ) - { - /* FIXME : How can I determine the preedit height? */ - y = topwin_y - cw_he - 20; - } - else - { - y = topwin_y; - } - move( x, y ); -} - -void CandidateWindow::showCand() -{ -#if defined(ENABLE_DEBUG) - qDebug( "uim-candwin-qt4: showCand()" ); -#endif - if ( isActive ) - show(); -} -void CandidateWindow::deactivateCand() -{ -#if defined(ENABLE_DEBUG) - qDebug( "uim-candwin-qt4: deactivateCand()" ); -#endif - hide(); - isActive = false; -} -void CandidateWindow::setNrCandidates( const QStringList &list ) -{ -#if defined(ENABLE_DEBUG) - qDebug( "uim-candwin-qt: setNrCandidates()" ); -#endif - if ( list[ 1 ].isEmpty() || list[ 2 ].isEmpty() ) - return ; - - // remove old data - cList->clearContents(); - cList->setRowCount( 0 ); - stores.clear(); - - // set default value - candidateIndex = -1; - nrCandidates = list[ 1 ].toInt(); - displayLimit = list[ 2 ].toInt(); - needHighlight = false; - isActive = true; - - // setup dummy stores - for ( int i = 0; i < nrCandidates; i++ ) { - CandData d; - stores.append( d ); - } -} -void CandidateWindow::setPageCandidates( const QStringList &list ) -{ -#if defined(ENABLE_DEBUG) - qDebug( "uim-candwin-qt: setPageCandidates()" ); -#endif - /** - * format: set_page_candidates\fcharset=$charset\fpage=$value\fhead1\acand1\aannot1\fhead2\acand2\aannot2\fhead3\acand3\aannot3\f - */ +#include "candidatewindow.h" +#include "candidatetablewindow.h" +#include "ximcandidatewindow.h" - int page = 0; - - // get charset and create codec - QTextCodec *codec = 0; - if ( !list[ 1 ].isEmpty() - && list[ 1 ].startsWith( QLatin1String( "charset" ) ) ) - { - const QStringList l = list[ 1 ].split( '=', QString::SkipEmptyParts ); - codec = QTextCodec::codecForName( l[ 1 ].toAscii() ); - } - - // get page - if ( !list[ 2 ].isEmpty() - && list[ 2 ].startsWith( QLatin1String( "page" ) ) ) - { - const QStringList l = list[ 2 ].split( '=', QString::SkipEmptyParts ); - page = l[ 1 ].toInt(); - } - - int len = list.count(); - for ( int i = 3; i < len; i++ ) - { - // case list[i] = "" - if ( list[ i ].isEmpty() ) - break; - - // split heading_label and cand_str - QStringList l = list [ i ].split( '\a' ); - - // store data - CandData &d = stores[page * displayLimit + i - 3]; - QString headString; - if ( codec ) - headString = codec->toUnicode( l [ 0 ].toAscii() ); - else - headString = l [ 0 ]; - - d.label = headString; - - l.pop_front(); - QString candString = l [ 0 ]; - - if ( codec ) - d.str = codec->toUnicode( candString.toAscii() ); - else - d.str = candString; - - l.pop_front(); - QString annotString = l [ 0 ]; - } -} -void CandidateWindow::showPage( const QStringList &list ) -{ -#if defined(ENABLE_DEBUG) - qDebug( "uim-candwin-qt: showPage()" ); -#endif - const int page = list[ 1 ].toInt(); - - setPage( page ); - adjustCandidateWindowSize(); - show(); -} -void CandidateWindow::slotStdinActivated( int fd ) -{ - char buf[ 4096 ]; - char *read_buf = strdup( "" ); - int n; - - while (uim_helper_fd_readable( fd ) > 0) { - n = read( fd, buf, 4096 - 1 ); - if ( n == 0 ) - { - ::close( fd ); - exit( 1 ); - } - if ( n == -1 ) - return ; - buf[ n ] = '\0'; - read_buf = (char *)realloc( read_buf, strlen( read_buf ) + n + 1 ); - strcat( read_buf, buf ); - } - - QStringList msgList - = QString( read_buf ).split( "\f\f", QString::SkipEmptyParts ); - - QStringList::Iterator it = msgList.begin(); - const QStringList::Iterator end = msgList.end(); - for ( ; it != end; ++it ) - strParse( ( *it ) ); - free( read_buf ); -} - -void CandidateWindow::strParse( const QString& str ) -{ -#if defined(ENABLE_DEBUG) - qDebug( "str = %s", str.toLocal8Bit().constData() ); -#endif - QStringList list = str.split( '\f', QString::SkipEmptyParts ); - - QStringList::Iterator it = list.begin(); - const QStringList::Iterator end = list.end(); - for ( ; it != end; ++it ) - { - if ( QString::compare( "activate", ( *it ) ) == 0 ) - activateCand( list ); - else if ( QString::compare( "select", ( *it ) ) == 0 ) - selectCand( list ); - else if ( QString::compare( "show", ( *it ) ) == 0 ) - showCand(); - else if ( QString::compare( "hide", ( *it ) ) == 0 ) - hide(); - else if ( QString::compare( "move", ( *it ) ) == 0 ) - moveCand( list ); - else if ( QString::compare( "deactivate", ( *it ) ) == 0 ) - deactivateCand(); - else if ( QString::compare( "set_nr_candidates", ( *it ) ) == 0 ) - setNrCandidates( list ); - else if ( QString::compare( "set_page_candidates", ( *it ) ) == 0 ) - setPageCandidates( list ); - else if ( QString::compare( "show_page", ( *it ) ) == 0 ) - showPage( list ); - } -} - -void CandidateWindow::slotCandidateSelected( int row ) -{ - candidateIndex = ( pageIndex * displayLimit ) + row; - - // write message - fprintf( stdout, "index\n" ); - fprintf( stdout, "%d\n\n", candidateIndex ); - fflush( stdout ); - - updateLabel(); -} - -void CandidateWindow::adjustCandidateWindowSize() -{ -#if defined(ENABLE_DEBUG) - qDebug( "adjustCandidateWindowSize()" ); -#endif - // frame width - // According to the Qt4 documentation on the QFrame class, - // the frame width is 1 pixel. - int frame = 1 * 2 - + cList->style()->pixelMetric( QStyle::PM_DefaultFrameWidth ) * 2; - - const int rowNum = cList->rowCount(); - if ( rowNum == 0 ) { - resize( MIN_CAND_WIDTH, numLabel->height() + frame ); - return; - } - int width = frame; - // the size of the dummy column should be 0. - for ( int i = 0; i < cList->columnCount() - 1; i++ ) - width += cList->columnWidth( i ); - - resize( width, cList->rowHeight( 0 ) * rowNum + numLabel->height() - + frame ); -} - -void CandidateWindow::setPage( int page ) -{ - // clear items - cList->clearContents(); - - // calculate page - int newpage, lastpage; - if ( displayLimit ) - lastpage = nrCandidates / displayLimit; - else - lastpage = 0; - - if ( page < 0 ) - { - newpage = lastpage; - } - else if ( page > lastpage ) - { - newpage = 0; - } - else - { - newpage = page; - } - - pageIndex = newpage; - - // calculate index - int newindex; - if ( displayLimit ) - { - if ( candidateIndex >= 0 ) - newindex = ( newpage * displayLimit ) + ( candidateIndex % displayLimit ); - else - newindex = -1; - } - else - { - newindex = candidateIndex; - } - - if ( newindex >= nrCandidates ) - newindex = nrCandidates - 1; - - // set cand items - // - // If we switch to last page, the number of items to be added - // is lower than displayLimit. - // - // ex. if nrCandidate==14 and displayLimit==10, the number of - // last page's item==4 - int ncandidates = displayLimit; - if ( newpage == lastpage ) - ncandidates = nrCandidates - displayLimit * lastpage; - cList->setRowCount( ncandidates ); - for ( int i = 0; i < ncandidates ; i++ ) - { - QString headString = stores[ displayLimit * newpage + i ].label; - QString candString = stores[ displayLimit * newpage + i ].str; - - // insert new item to the candidate list - QTableWidgetItem *headItem = new QTableWidgetItem; - headItem->setText( headString ); - headItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled ); - QTableWidgetItem *candItem = new QTableWidgetItem; - candItem->setText( candString ); - candItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled ); - cList->setItem( i, HEADING_COLUMN, headItem ); - cList->setItem( i, CANDIDATE_COLUMN, candItem ); - cList->setRowHeight( i, QFontMetrics( cList->font() ).height() + 2 ); - } - - // set index - if ( newindex != candidateIndex ) - setIndex( newindex ); - else - updateLabel(); - - // set candwin size - adjustCandidateWindowSize(); -} - -void CandidateWindow::setIndex( int index ) -{ -#if defined(ENABLE_DEBUG) - qDebug( "setIndex : index = %d", index ); -#endif - // validity check - if ( index < 0 ) - candidateIndex = nrCandidates - 1; - else if ( index >= nrCandidates ) - candidateIndex = 0; - else - candidateIndex = index; - - // set page - int newpage = 0; - if ( displayLimit ) - newpage = candidateIndex / displayLimit; - if ( pageIndex != newpage ) - setPage( newpage ); - - // select item - if ( candidateIndex >= 0 && needHighlight ) - { - int pos = index; - if ( displayLimit ) - pos = candidateIndex % displayLimit; +#include "qtgettext.h" - if ( cList->item( pos, 0 ) && !cList->item( pos, 0 )->isSelected() ) - { - cList->clearSelection(); - cList->selectRow( pos ); +class Window +{ + public: + Window(int argc, char *argv[]); + ~Window(); + + private: + QWidget *widget; +}; + +Window::Window(int argc, char *argv[]) +{ + uim_init(); + if (argc > 1) { + // vertical + if (!strcmp(argv[1], "-v")) { + widget = new CandidateWindow(0, true); + // horizontal + } else if (!strcmp(argv[1], "-h")) { + widget = new CandidateWindow(0, false); + // table + } else if (!strcmp(argv[1], "-t")) { + widget = new CandidateTableWindow(0); + } else { + widget = new XimCandidateWindow; } + } else { + widget = new XimCandidateWindow; } - else - { - cList->clearSelection(); - } - - updateLabel(); } -void CandidateWindow::updateLabel() +Window::~Window() { - QString indexString; - if ( candidateIndex >= 0 && needHighlight ) - indexString = QString::number( candidateIndex + 1 ) + " / " + QString::number( nrCandidates ); - else - indexString = "- / " + QString::number( nrCandidates ); - - numLabel->setText( indexString ); + delete widget; + uim_quit(); } -int main( int argc, char *argv[] ) +int main(int argc, char *argv[]) { setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); bind_textdomain_codeset(PACKAGE, "UTF-8"); // ensure code encoding is UTF8- - QApplication a( argc, argv ); + QApplication app(argc, argv); - CandidateWindow b; + Window window(argc, argv); - return a.exec(); + return app.exec(); } diff --git a/qt4/immodule/subwindow.cpp b/qt4/candwin/subwindow.cpp similarity index 71% rename from qt4/immodule/subwindow.cpp rename to qt4/candwin/subwindow.cpp index bc15501e0..a81801b32 100644 --- a/qt4/immodule/subwindow.cpp +++ b/qt4/candwin/subwindow.cpp @@ -34,35 +34,42 @@ SUCH DAMAGE. #include #include -#include -#include -#include -#include +#if QT_VERSION < 0x050000 +# include +# include +# include +# include +#else +# include +# include +# include +# include +#endif -const Qt::WindowFlags subwindowFlag = ( Qt::Window +const Qt::WindowFlags subwindowFlag = (Qt::Window | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::Tool #if defined(Q_WS_X11) | Qt::X11BypassWindowManagerHint #endif - ); + ); static const int TIMER_INTERVAL = 1000; // 1000ms = 1second -SubWindow::SubWindow( QWidget *parent ) - : QFrame( parent, subwindowFlag ) +SubWindow::SubWindow(QWidget *parent) + : QFrame(parent, subwindowFlag) { - m_contentsEdit = new QTextBrowser( this ); + m_contentsEdit = new QTextBrowser(this); - m_hookTimer = new QTimer( this ); - connect( m_hookTimer, SIGNAL( timeout() ), this, SLOT( timerDone() ) ); + m_hookTimer = new QTimer(this); + connect(m_hookTimer, SIGNAL(timeout()), this, SLOT(timerDone())); QVBoxLayout *layout = new QVBoxLayout; - layout->setMargin( 0 ); - layout->addWidget( m_contentsEdit ); - setLayout( layout ); + layout->setMargin(0); + layout->addWidget(m_contentsEdit); + setLayout(layout); adjustSize(); @@ -72,16 +79,16 @@ SubWindow::SubWindow( QWidget *parent ) SubWindow::~SubWindow() {} -void SubWindow::hookPopup( const QString &contents ) +void SubWindow::hookPopup(const QString &contents) { // stop now running timer - if ( m_hookTimer->isActive() ) + if (m_hookTimer->isActive()) m_hookTimer->stop(); - m_contentsEdit->setText( contents ); + m_contentsEdit->setText(contents); - m_hookTimer->setSingleShot( true ); - m_hookTimer->start( TIMER_INTERVAL ); + m_hookTimer->setSingleShot(true); + m_hookTimer->start(TIMER_INTERVAL); } void SubWindow::popup() @@ -101,7 +108,7 @@ void SubWindow::timerDone() popup(); } -void SubWindow::layoutWindow( const QRect &rect, bool isVertical ) +void SubWindow::layoutWindow(const QRect &rect, bool isVertical) { const QRect screenRect = QApplication::desktop()->screenGeometry(); @@ -109,13 +116,13 @@ void SubWindow::layoutWindow( const QRect &rect, bool isVertical ) const int candX = rect.x(); const int screenW = screenRect.width(); int destX; - if ( isVertical ) { + if (isVertical) { destX = candX + rect.width(); - if ( destX + w > screenW ) + if (destX + w > screenW) destX = candX - w; } else { destX = candX; - if ( destX + w > screenW ) + if (destX + w > screenW) destX = screenW - w; } @@ -123,15 +130,15 @@ void SubWindow::layoutWindow( const QRect &rect, bool isVertical ) const int candY = rect.y(); const int screenH = screenRect.height(); int destY; - if ( isVertical ) { + if (isVertical) { destY = candY; - if ( destY + h > screenH ) + if (destY + h > screenH) destY = screenH - h; } else { destY = candY + rect.height(); - if ( destY + h > screenH ) + if (destY + h > screenH) destY = candY - h; } - move( destX, destY ); + move(destX, destY); } diff --git a/qt4/immodule/subwindow.h b/qt4/candwin/subwindow.h similarity index 89% rename from qt4/immodule/subwindow.h rename to qt4/candwin/subwindow.h index f238ea5e3..eeac660f5 100644 --- a/qt4/immodule/subwindow.h +++ b/qt4/candwin/subwindow.h @@ -34,7 +34,11 @@ SUCH DAMAGE. #define UIM_QT4_IMMODULE_SUBWINDOW_H #include -#include +#if QT_VERSION < 0x050000 +# include +#else +# include +#endif class QTextBrowser; @@ -43,10 +47,10 @@ class SubWindow : public QFrame Q_OBJECT public: - explicit SubWindow( QWidget *parent = 0 ); + explicit SubWindow(QWidget *parent = 0); ~SubWindow(); - void layoutWindow( const QRect &rect, bool isVertical ); + void layoutWindow(const QRect &rect, bool isVertical); bool isHooked() { @@ -54,7 +58,7 @@ class SubWindow : public QFrame } public slots: - void hookPopup( const QString &contents ); + void hookPopup(const QString &contents); void cancelHook(); protected: diff --git a/qt4/candwin/uim-candwin-qt4.pro.in b/qt4/candwin/uim-candwin-qt4.pro.in index 434ba4bf9..57734cb10 100644 --- a/qt4/candwin/uim-candwin-qt4.pro.in +++ b/qt4/candwin/uim-candwin-qt4.pro.in @@ -8,8 +8,19 @@ INCLUDEPATH += @srcdir@/.. LIBS += @LIBINTL@ # Input -HEADERS += @srcdir@/qt4.h -SOURCES += @srcdir@/qt4.cpp +HEADERS += @srcdir@/abstractcandidatewindow.h \ + @srcdir@/candidatetablewindow.h \ + @srcdir@/candidatewindow.h \ + @srcdir@/subwindow.h \ + @srcdir@/util.h \ + @srcdir@/ximcandidatewindow.h +SOURCES += @srcdir@/abstractcandidatewindow.cpp \ + @srcdir@/candidatetablewindow.cpp \ + @srcdir@/candidatewindow.cpp \ + @srcdir@/qt4.cpp \ + @srcdir@/subwindow.cpp \ + @srcdir@/util.cpp \ + @srcdir@/ximcandidatewindow.cpp TARGET = uim-candwin-qt4 diff --git a/qt4/candwin/util.cpp b/qt4/candwin/util.cpp new file mode 100644 index 000000000..077f828e4 --- /dev/null +++ b/qt4/candwin/util.cpp @@ -0,0 +1,67 @@ +/* + + Copyright (c) 2012 uim Project http://code.google.com/p/uim/ + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of authors nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +*/ +#include "util.h" + +#include + +#include + +#include +#include + +QString get_messages(int fd) +{ + char buf[4096]; + QString message; + while (uim_helper_fd_readable(fd) > 0) { + int n = read(fd, buf, 4096 - 1); + if (n == 0) { + ::close(fd); + ::exit(0); + } + if (n == -1) + return message; + buf[n] = '\0'; + message += QString::fromUtf8(buf); + } + return message; +} + +QList parse_messages(const QString &message) +{ + QStringList messageList = message.split("\f\f", QString::SkipEmptyParts); + QList result; + for (int i = 0, j = messageList.count(); i < j; i++) + result.append(messageList[i].split('\f', QString::SkipEmptyParts)); + return result; +} diff --git a/qt4/candwin/util.h b/qt4/candwin/util.h new file mode 100644 index 000000000..c70a09a03 --- /dev/null +++ b/qt4/candwin/util.h @@ -0,0 +1,55 @@ +/* + + Copyright (c) 2012 uim Project http://code.google.com/p/uim/ + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of authors nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +*/ +#ifndef UIM_QT4_UTIL_H +#define UIM_QT4_UTIL_H + +#include + +// enable per page candidates handling +#define UIM_QT_USE_NEW_PAGE_HANDLING 1 +// enable delay showing candidate window +#define UIM_QT_USE_DELAY 1 +// enable workaround for broken reset() behavior +#define WORKAROUND_BROKEN_RESET_IN_QT4 + +struct CandData +{ + QString str; + QString headingLabel; + QString annotation; +}; + +QString get_messages(int fd); +QList parse_messages(const QString &message); + +#endif /* UIM_QT4_UTIL_H */ diff --git a/qt4/candwin/ximcandidatewindow.cpp b/qt4/candwin/ximcandidatewindow.cpp new file mode 100644 index 000000000..72dcc61d7 --- /dev/null +++ b/qt4/candwin/ximcandidatewindow.cpp @@ -0,0 +1,572 @@ +/* + + Copyright (c) 2003-2012 uim Project http://code.google.com/p/uim/ + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of authors nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +*/ +#include + +#include "ximcandidatewindow.h" + +#include +#include +#include +#include + +#include +#include +#include +#if QT_VERSION < 0x050000 +# include +# include +# include +# include +# include +# include +#else +# include +# include +# include +# include +# include +# include +#endif + +#include +#include + +#include "util.h" + +static const int NR_CANDIDATES = 10; +static const int MIN_CAND_WIDTH = 80; + +static const int HEADING_COLUMN = 0; +static const int CANDIDATE_COLUMN = 1; + +const Qt::WindowFlags candidateFlag = (Qt::Window + | Qt::WindowStaysOnTopHint + | Qt::FramelessWindowHint + | Qt::Tool +#if defined(Q_WS_X11) + | Qt::X11BypassWindowManagerHint +#endif + ); +static QSocketNotifier *notifier = 0; + +XimCandidateWindow::XimCandidateWindow(QWidget *parent) +: QFrame(parent, candidateFlag), nrCandidates(0), candidateIndex(0), + displayLimit(NR_CANDIDATES), pageIndex(-1), isActive(false) +{ + setFrameStyle(Raised | NoFrame); + setFocusPolicy(Qt::NoFocus); + + //setup CandidateList + cList = new QTableWidget; + cList->setSelectionMode(QAbstractItemView::SingleSelection); + cList->setSelectionBehavior(QAbstractItemView::SelectRows); + // the last column is dummy for adjusting size. + cList->setColumnCount(3); + cList->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents); + cList->horizontalHeader()->setStretchLastSection(true); + cList->horizontalHeader()->hide(); + cList->verticalHeader()->hide(); + cList->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + cList->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + cList->setAutoScroll(false); + cList->setShowGrid(false); + cList->setMinimumWidth(MIN_CAND_WIDTH); + connect(cList, SIGNAL(cellClicked(int, int)), + this , SLOT(slotCandidateSelected(int))); + + //setup NumberLabel + numLabel = new QLabel; + numLabel->setFocusPolicy(Qt::NoFocus); + numLabel->adjustSize(); + + notifier = new QSocketNotifier(0, QSocketNotifier::Read); + connect(notifier, SIGNAL(activated(int)), + this, SLOT(slotStdinActivated(int))); + QVBoxLayout *layout = new QVBoxLayout; + layout->setMargin(0); + layout->setSpacing(0); + layout->addWidget(cList); + layout->addWidget(numLabel); + setLayout(layout); + + hide(); +} + +XimCandidateWindow::~XimCandidateWindow() +{ + if (!stores.isEmpty()) + stores.clear(); +} + +void XimCandidateWindow::activateCand(const QStringList &list) +{ +#if defined(ENABLE_DEBUG) + qDebug("uim-candwin-qt4: activateCand()"); +#endif + /** + * format: activate\fcharset=$charset\fdisplay_limit=$value\fhead1\acand1\aannot1\fhead2\acand2\aannot2\fhead3\acand3\aannot3\f + */ + + // remove old data + cList->clearContents(); + cList->setRowCount(0); + stores.clear(); + + // get charset and create codec + QTextCodec *codec = 0; + if (!list[1].isEmpty() + && list[1].startsWith(QLatin1String("charset"))) + { + const QStringList l = list[1].split('=', QString::SkipEmptyParts); + codec = QTextCodec::codecForName(l[1].toAscii()); + } + + // get display_limit + if (!list[2].isEmpty() + && list[2].startsWith(QLatin1String("display_limit"))) + { + const QStringList l = list[2].split('=', QString::SkipEmptyParts); + displayLimit = l[1].toInt(); + } + + for (int i = 3; i < list.count(); i++) + { + // case list[i] = "" + if (list[i].isEmpty()) + break; + + // split heading_label and cand_str + QStringList l = list[i].split('\a'); + int count = l.count(); + if (count < 2) + continue; + + // store data + CandData d; + QString headString; + if (codec) + headString = codec->toUnicode(l[0].toAscii()); + else + headString = l [0]; + + d.headingLabel = headString; + + l.pop_front(); + QString candString = l [0]; + + if (codec) + d.str = codec->toUnicode(candString.toAscii()); + else + d.str = candString; + + if (count >= 3) { + l.pop_front(); + QString annotString = l [0]; + } + + stores.append(d); + } + + // set default value + candidateIndex = -1; + nrCandidates = stores.count(); + + // shift to default page + setPage(0); + + adjustCandidateWindowSize(); + show(); + + isActive = true; +} +void XimCandidateWindow::selectCand(const QStringList &list) +{ +#if defined(ENABLE_DEBUG) + qDebug("uim-candwin-qt4: selectCand()"); +#endif + const int index = list[1].toInt(); + needHighlight = (list[2].toInt() == 1); + setIndex(index); + + updateLabel(); +} + +void XimCandidateWindow::moveCand(const QStringList &list) +{ +#if defined(ENABLE_DEBUG) + qDebug("uim-candwin-qt4: moveCand()"); +#endif + if (list[1].isEmpty() || list[2].isEmpty()) + return ; + + const int topwin_x = list[1].toInt(); + const int topwin_y = list[2].toInt(); + const int cw_wi = width(); + const int cw_he = height(); + const int sc_wi = QApplication::desktop()->screenGeometry().width(); + const int sc_he = QApplication::desktop()->screenGeometry().height(); + + int x, y; + if (sc_wi < topwin_x + cw_wi) + { + x = topwin_x - cw_wi; + } + else + { + x = topwin_x; + } + + if (sc_he < topwin_y + cw_he) + { + /* FIXME : How can I determine the preedit height? */ + y = topwin_y - cw_he - 20; + } + else + { + y = topwin_y; + } + + move(x, y); +} + +void XimCandidateWindow::showCand() +{ +#if defined(ENABLE_DEBUG) + qDebug("uim-candwin-qt4: showCand()"); +#endif + if (isActive) + show(); +} +void XimCandidateWindow::deactivateCand() +{ +#if defined(ENABLE_DEBUG) + qDebug("uim-candwin-qt4: deactivateCand()"); +#endif + hide(); + isActive = false; +} +void XimCandidateWindow::setNrCandidates(const QStringList &list) +{ +#if defined(ENABLE_DEBUG) + qDebug("uim-candwin-qt: setNrCandidates()"); +#endif + if (list[1].isEmpty() || list[2].isEmpty()) + return ; + + // remove old data + cList->clearContents(); + cList->setRowCount(0); + stores.clear(); + + // set default value + candidateIndex = -1; + nrCandidates = list[1].toInt(); + displayLimit = list[2].toInt(); + needHighlight = false; + isActive = true; + + // setup dummy stores + for (int i = 0; i < nrCandidates; i++) { + CandData d; + stores.append(d); + } +} +void XimCandidateWindow::setPageCandidates(const QStringList &list) +{ +#if defined(ENABLE_DEBUG) + qDebug("uim-candwin-qt: setPageCandidates()"); +#endif + /** + * format: set_page_candidates\fcharset=$charset\fpage=$value\fhead1\acand1\aannot1\fhead2\acand2\aannot2\fhead3\acand3\aannot3\f + */ + + int page = 0; + + // get charset and create codec + QTextCodec *codec = 0; + if (!list[1].isEmpty() + && list[1].startsWith(QLatin1String("charset"))) + { + const QStringList l = list[1].split('=', QString::SkipEmptyParts); + codec = QTextCodec::codecForName(l[1].toAscii()); + } + + // get page + if (!list[2].isEmpty() + && list[2].startsWith(QLatin1String("page"))) + { + const QStringList l = list[2].split('=', QString::SkipEmptyParts); + page = l[1].toInt(); + } + + int len = list.count(); + for (int i = 3; i < len; i++) + { + // case list[i] = "" + if (list[i].isEmpty()) + break; + + // split heading_label and cand_str + QStringList l = list [i].split('\a'); + + // store data + CandData &d = stores[page * displayLimit + i - 3]; + QString headString; + if (codec) + headString = codec->toUnicode(l [0].toAscii()); + else + headString = l [0]; + + d.headingLabel = headString; + + l.pop_front(); + QString candString = l [0]; + + if (codec) + d.str = codec->toUnicode(candString.toAscii()); + else + d.str = candString; + + l.pop_front(); + QString annotString = l [0]; + } +} +void XimCandidateWindow::showPage(const QStringList &list) +{ +#if defined(ENABLE_DEBUG) + qDebug("uim-candwin-qt: showPage()"); +#endif + const int page = list[1].toInt(); + + setPage(page); + adjustCandidateWindowSize(); + show(); +} + +void XimCandidateWindow::slotStdinActivated(int fd) +{ + QList messageList = parse_messages(get_messages(fd)); + for (int i = 0, j = messageList.count(); i < j; i++) { + QStringList message = messageList[i]; + QString command = message[0]; + if (command == "activate") + activateCand(message); + else if (command == "select") + selectCand(message); + else if (command == "show") + showCand(); + else if (command == "hide") + hide(); + else if (command == "move") + moveCand(message); + else if (command == "deactivate") + deactivateCand(); + else if (command == "set_nr_candidates") + setNrCandidates(message); + else if (command == "set_page_candidates") + setPageCandidates(message); + else if (command == "show_page") + showPage(message); + } +} + +void XimCandidateWindow::slotCandidateSelected(int row) +{ + candidateIndex = (pageIndex * displayLimit) + row; + + // write message + fprintf(stdout, "index\n"); + fprintf(stdout, "%d\n\n", candidateIndex); + fflush(stdout); + + updateLabel(); +} + +void XimCandidateWindow::adjustCandidateWindowSize() +{ +#if defined(ENABLE_DEBUG) + qDebug("adjustCandidateWindowSize()"); +#endif + // frame width + // According to the Qt4 documentation on the QFrame class, + // the frame width is 1 pixel. + int frame = 1 * 2 + + cList->style()->pixelMetric(QStyle::PM_DefaultFrameWidth) * 2; + + const int rowNum = cList->rowCount(); + if (rowNum == 0) { + resize(MIN_CAND_WIDTH, numLabel->height() + frame); + return; + } + int width = frame; + // the size of the dummy column should be 0. + for (int i = 0; i < cList->columnCount() - 1; i++) + width += cList->columnWidth(i); + + resize(width, cList->rowHeight(0) * rowNum + numLabel->height() + + frame); +} + +void XimCandidateWindow::setPage(int page) +{ + // clear items + cList->clearContents(); + + // calculate page + int newpage, lastpage; + if (displayLimit) + lastpage = nrCandidates / displayLimit; + else + lastpage = 0; + + if (page < 0) + { + newpage = lastpage; + } + else if (page > lastpage) + { + newpage = 0; + } + else + { + newpage = page; + } + + pageIndex = newpage; + + // calculate index + int newindex; + if (displayLimit) + { + if (candidateIndex >= 0) + newindex = (newpage * displayLimit) + (candidateIndex % displayLimit); + else + newindex = -1; + } + else + { + newindex = candidateIndex; + } + + if (newindex >= nrCandidates) + newindex = nrCandidates - 1; + + // set cand items + // + // If we switch to last page, the number of items to be added + // is lower than displayLimit. + // + // ex. if nrCandidate==14 and displayLimit==10, the number of + // last page's item==4 + int ncandidates = displayLimit; + if (newpage == lastpage) + ncandidates = nrCandidates - displayLimit * lastpage; + cList->setRowCount(ncandidates); + for (int i = 0; i < ncandidates ; i++) + { + QString headString = stores[displayLimit * newpage + i].headingLabel; + QString candString = stores[displayLimit * newpage + i].str; + + // insert new item to the candidate list + QTableWidgetItem *headItem = new QTableWidgetItem; + headItem->setText(headString); + headItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + QTableWidgetItem *candItem = new QTableWidgetItem; + candItem->setText(candString); + candItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + cList->setItem(i, HEADING_COLUMN, headItem); + cList->setItem(i, CANDIDATE_COLUMN, candItem); + cList->setRowHeight(i, QFontMetrics(cList->font()).height() + 2); + } + + // set index + if (newindex != candidateIndex) + setIndex(newindex); + else + updateLabel(); + + // set candwin size + adjustCandidateWindowSize(); +} + +void XimCandidateWindow::setIndex(int index) +{ +#if defined(ENABLE_DEBUG) + qDebug("setIndex : index = %d", index); +#endif + // validity check + if (index < 0) + candidateIndex = nrCandidates - 1; + else if (index >= nrCandidates) + candidateIndex = 0; + else + candidateIndex = index; + + // set page + int newpage = 0; + if (displayLimit) + newpage = candidateIndex / displayLimit; + if (pageIndex != newpage) + setPage(newpage); + + // select item + if (candidateIndex >= 0 && needHighlight) + { + int pos = index; + if (displayLimit) + pos = candidateIndex % displayLimit; + + if (cList->item(pos, 0) && !cList->item(pos, 0)->isSelected()) + { + cList->clearSelection(); + cList->selectRow(pos); + } + } + else + { + cList->clearSelection(); + } + + updateLabel(); +} + +void XimCandidateWindow::updateLabel() +{ + QString indexString; + if (candidateIndex >= 0 && needHighlight) + indexString = QString::number(candidateIndex + 1) + " / " + QString::number(nrCandidates); + else + indexString = "- / " + QString::number(nrCandidates); + + numLabel->setText(indexString); +} diff --git a/qt4/candwin/qt4.h b/qt4/candwin/ximcandidatewindow.h similarity index 72% rename from qt4/candwin/qt4.h rename to qt4/candwin/ximcandidatewindow.h index cd81bea47..5ccfba639 100644 --- a/qt4/candwin/qt4.h +++ b/qt4/candwin/ximcandidatewindow.h @@ -30,49 +30,49 @@ SUCH DAMAGE. */ -#ifndef UIM_QT4_CANDWIN_QT_H -#define UIM_QT4_CANDWIN_QT_H +#ifndef UIM_QT4_XIM_CANDWIN_QT_H +#define UIM_QT4_XIM_CANDWIN_QT_H #include -#include +#if QT_VERSION < 0x050000 +# include +#else +# include +#endif + +#include "util.h" class QLabel; class QStringList; class QTableWidget; -struct CandData -{ - QString label; - QString str; -}; - -class CandidateWindow : public QFrame +class XimCandidateWindow : public QFrame { Q_OBJECT + public: - explicit CandidateWindow( QWidget *parent = 0 ); - ~CandidateWindow(); + explicit XimCandidateWindow(QWidget *parent = 0); + ~XimCandidateWindow(); - void activateCand( const QStringList &list ); - void selectCand( const QStringList &list ); - void moveCand( const QStringList &list ); + void activateCand(const QStringList &list); + void selectCand(const QStringList &list); + void moveCand(const QStringList &list); void showCand(); void deactivateCand(); - void setNrCandidates( const QStringList &list ); - void setPageCandidates( const QStringList &list ); - void showPage( const QStringList &list ); + void setNrCandidates(const QStringList &list); + void setPageCandidates(const QStringList &list); + void showPage(const QStringList &list); public slots: - void slotStdinActivated( int ); - void slotCandidateSelected( int row ); + void slotStdinActivated(int); + void slotCandidateSelected(int row); protected: - void strParse( const QString& str ); void adjustCandidateWindowSize(); - void setPage( int page ); - void setIndex( int index ); + void setPage(int page); + void setIndex(int index); void updateLabel(); @@ -91,4 +91,4 @@ public slots: bool needHighlight; }; -#endif /* UIM_QT4_CANDWIN_QT_H */ +#endif /* UIM_QT4_XIM_CANDWIN_QT_H */ diff --git a/qt4/chardict/bushuviewwidget.cpp b/qt4/chardict/bushuviewwidget.cpp index 28e63983e..b1b95737b 100644 --- a/qt4/chardict/bushuviewwidget.cpp +++ b/qt4/chardict/bushuviewwidget.cpp @@ -40,13 +40,23 @@ SUCH DAMAGE. #include #include #include -#include -#include -#include -#include -#include -#include -#include +#if QT_VERSION < 0x050000 +# include +# include +# include +# include +# include +# include +# include +#else +# include +# include +# include +# include +# include +# include +# include +#endif static const char BUSHUDICT[] = DATADIR "/uim/helperdata/bushu.t"; static const char BUSHUDICT_ENCODING[] = "EUC-JP"; diff --git a/qt4/chardict/chargridview.cpp b/qt4/chardict/chargridview.cpp index d35025e3b..391d8a067 100644 --- a/qt4/chardict/chargridview.cpp +++ b/qt4/chardict/chargridview.cpp @@ -33,10 +33,15 @@ SUCH DAMAGE. #include "chargridview.h" #include -#include #include #include -#include +#if QT_VERSION < 0x050000 +# include +# include +#else +# include +# include +#endif static const int COLS = 10; diff --git a/qt4/chardict/chargridview.h b/qt4/chardict/chargridview.h index 6def350de..1018c8d87 100644 --- a/qt4/chardict/chargridview.h +++ b/qt4/chardict/chargridview.h @@ -33,7 +33,12 @@ SUCH DAMAGE. #ifndef UIM_QT4_CHARDICT_CHAR_GRID_VIEW_H #define UIM_QT4_CHARDICT_CHAR_GRID_VIEW_H -#include +#include +#if QT_VERSION < 0x050000 +# include +#else +# include +#endif class QFont; class QMouseEvent; diff --git a/qt4/chardict/qt4.cpp b/qt4/chardict/qt4.cpp index 071373b2b..6424b1cfd 100644 --- a/qt4/chardict/qt4.cpp +++ b/qt4/chardict/qt4.cpp @@ -35,17 +35,31 @@ SUCH DAMAGE. #include "unicodeviewwidget.h" #include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include +#if QT_VERSION < 0x050000 +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#else +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +#endif #ifdef Q_WS_X11 #include diff --git a/qt4/chardict/qt4.h b/qt4/chardict/qt4.h index 7952d6130..b0a5bc552 100644 --- a/qt4/chardict/qt4.h +++ b/qt4/chardict/qt4.h @@ -33,7 +33,12 @@ SUCH DAMAGE. #ifndef UIM_QT4_CHARDICT_CHARDICT_QT_H #define UIM_QT4_CHARDICT_CHARDICT_QT_H -#include +#include +#if QT_VERSION < 0x050000 +# include +#else +# include +#endif class QComboBox; class QLineEdit; diff --git a/qt4/chardict/unicodeviewwidget.cpp b/qt4/chardict/unicodeviewwidget.cpp index 95c2f2069..59d530f50 100644 --- a/qt4/chardict/unicodeviewwidget.cpp +++ b/qt4/chardict/unicodeviewwidget.cpp @@ -36,13 +36,23 @@ SUCH DAMAGE. #include #include -#include -#include -#include -#include -#include -#include -#include +#if QT_VERSION < 0x050000 +# include +# include +# include +# include +# include +# include +# include +#else +# include +# include +# include +# include +# include +# include +# include +#endif class UnicodeBlock { diff --git a/qt4/common.pro.in b/qt4/common.pro.in index f8991bfb5..586f88efe 100644 --- a/qt4/common.pro.in +++ b/qt4/common.pro.in @@ -9,6 +9,10 @@ LIBS += -lreplace -luim -luim-scm !win32:!embedded:!mac { LIBS += -luim-x-util } + +greaterThan(QT_MAJOR_VERSION, 4) { + QT += widgets +} QMAKE_CC = @CC@ QMAKE_CFLAGS_DEBUG += @CFLAGS@ @X_CFLAGS@ diff --git a/qt4/edittest/edittest.pro b/qt4/edittest/edittest.pro index 1bbb33aed..db2e1f650 100644 --- a/qt4/edittest/edittest.pro +++ b/qt4/edittest/edittest.pro @@ -4,6 +4,10 @@ DEPENDPATH += . INCLUDEPATH += . CONFIG += qt warn_on debug +greaterThan(QT_MAJOR_VERSION, 4) { + QT += widgets +} + QMAKE_STRIP = # Input diff --git a/qt4/edittest/main.cpp b/qt4/edittest/main.cpp index b02bcc6a8..a2333821f 100644 --- a/qt4/edittest/main.cpp +++ b/qt4/edittest/main.cpp @@ -32,12 +32,22 @@ */ -#include -#include -#include -#include -#include -#include +#include +#if QT_VERSION < 0x050000 +# include +# include +# include +# include +# include +# include +#else +# include +# include +# include +# include +# include +# include +#endif int main(int argc, char *argv[]) { diff --git a/qt4/immodule/Makefile.am b/qt4/immodule/Makefile.am index 323ca70f6..ee8243dcd 100644 --- a/qt4/immodule/Makefile.am +++ b/qt4/immodule/Makefile.am @@ -21,26 +21,18 @@ EXTRA_DIST = INDENT \ quiminputcontext_with_slave.h \ quiminputcontext_with_slave.cpp -EXTRA_DIST += abstractcandidatewindow.h \ - candidatetablewindow.h \ - candidatewindow.h \ - caretstateindicator.h \ +EXTRA_DIST += caretstateindicator.h \ plugin.h \ qhelpermanager.h \ qtextutil.h \ quiminfomanager.h \ quiminputcontext.h \ - quiminputcontext_compose.h \ - subwindow.h + quiminputcontext_compose.h -EXTRA_DIST += abstractcandidatewindow.cpp \ - candidatetablewindow.cpp \ - candidatewindow.cpp \ - caretstateindicator.cpp \ +EXTRA_DIST += caretstateindicator.cpp \ plugin.cpp \ qhelpermanager.cpp \ qtextutil.cpp \ quiminfomanager.cpp \ quiminputcontext.cpp \ - quiminputcontext_compose.cpp \ - subwindow.cpp + quiminputcontext_compose.cpp diff --git a/qt4/immodule/candidatewindow.cpp b/qt4/immodule/candidatewindow.cpp deleted file mode 100644 index 38501a8f3..000000000 --- a/qt4/immodule/candidatewindow.cpp +++ /dev/null @@ -1,339 +0,0 @@ -/* - -Copyright (c) 2003-2012 uim Project http://code.google.com/p/uim/ - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -1. Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. -3. Neither the name of authors nor the names of its contributors -may be used to endorse or promote products derived from this software -without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. - -*/ -#include "candidatewindow.h" - -#include -#include -#include -#include - -#include - -#include "quiminputcontext.h" -#include "subwindow.h" - -static const int MIN_CAND_WIDTH = 80; - -static const int HEADING_COLUMN = 0; -static const int CANDIDATE_COLUMN = 1; -static const int ANNOTATION_COLUMN = 2; - -CandidateWindow::CandidateWindow( QWidget *parent, bool vertical ) -: AbstractCandidateWindow( parent ), subWin( 0 ), - hasAnnotation( uim_scm_symbol_value_bool( "enable-annotation?" ) ), - isVertical( vertical ) -{ - //setup CandidateList - cList = new CandidateListView( 0, isVertical ); - cList->setSelectionMode( QAbstractItemView::SingleSelection ); - cList->setSelectionBehavior( isVertical - ? QAbstractItemView::SelectRows : QAbstractItemView::SelectColumns ); - cList->setMinimumWidth( MIN_CAND_WIDTH ); - if ( isVertical ) - // the last column is dummy for adjusting size. - cList->setColumnCount( hasAnnotation ? 4 : 3 ); - else - cList->setRowCount( 2 ); - cList->horizontalHeader()->setResizeMode( QHeaderView::ResizeToContents ); - cList->horizontalHeader()->setStretchLastSection( true ); - if ( !isVertical ) { - cList->verticalHeader() - ->setResizeMode( QHeaderView::ResizeToContents ); - cList->verticalHeader()->setStretchLastSection( true ); - } - cList->horizontalHeader()->hide(); - cList->verticalHeader()->hide(); - cList->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); - cList->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); - cList->setAutoScroll( false ); - cList->setShowGrid( false ); - connect( cList, SIGNAL( cellClicked( int, int ) ), - this , SLOT( slotCandidateSelected( int, int ) ) ); - connect( cList, SIGNAL( itemSelectionChanged() ), - this , SLOT( slotHookSubwindow() ) ); - - QVBoxLayout *layout = new QVBoxLayout; - layout->setMargin( 0 ); - layout->setSpacing( 0 ); - layout->addWidget( cList ); - layout->addWidget( numLabel ); - setLayout( layout ); -} - -void CandidateWindow::activateCandwin( int dLimit ) -{ - AbstractCandidateWindow::activateCandwin( dLimit ); - - if ( !subWin ) - subWin = new SubWindow( this ); -} - -#if UIM_QT_USE_NEW_PAGE_HANDLING -void CandidateWindow::setNrCandidates( int nrCands, int dLimit ) -{ - AbstractCandidateWindow::setNrCandidates( nrCands, dLimit ); - - if ( !subWin ) - subWin = new SubWindow( this ); -} -#endif /* UIM_QT_USE_NEW_PAGE_HANDLING */ - -void CandidateWindow::updateView( int newpage, int ncandidates ) -{ - cList->clearContents(); - annotations.clear(); - - if ( isVertical ) - cList->setRowCount( ncandidates ); - else - // the last column is dummy for adjusting size. - cList->setColumnCount( ncandidates + 1 ); - for ( int i = 0; i < ncandidates ; i++ ) { - uim_candidate cand = stores[ displayLimit * newpage + i ]; - QString headString - = QString::fromUtf8( uim_candidate_get_heading_label( cand ) ); - QString candString - = QString::fromUtf8( uim_candidate_get_cand_str( cand ) ); - QString annotationString; - if ( hasAnnotation ) { - annotationString - = QString::fromUtf8( uim_candidate_get_annotation_str( cand ) ); - annotations.append( annotationString ); - } - - // insert new item to the candidate list - if ( isVertical ) { - QTableWidgetItem *headItem = new QTableWidgetItem; - headItem->setText( headString ); - headItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled ); - - QTableWidgetItem *candItem = new QTableWidgetItem; - candItem->setText( candString ); - candItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled ); - - cList->setItem( i, HEADING_COLUMN, headItem ); - cList->setItem( i, CANDIDATE_COLUMN, candItem ); - - if ( hasAnnotation ) { - QTableWidgetItem *annotationItem = new QTableWidgetItem; - annotationItem->setFlags( - Qt::ItemIsSelectable | Qt::ItemIsEnabled ); - if ( !annotationString.isEmpty() ) - annotationItem->setText( "..." ); - - cList->setItem( i, ANNOTATION_COLUMN, annotationItem ); - } - cList->setRowHeight( i, - QFontMetrics( cList->font() ).height() + 2 ); - } else { - QTableWidgetItem *candItem = new QTableWidgetItem; - candItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled ); - - QString candText = headString + ": " + candString; - if ( hasAnnotation && !annotationString.isEmpty() ) - candText += "..."; - candItem->setText( candText ); - - cList->setItem( 0, i, candItem ); - } - } - if ( !isVertical ) - cList->setRowHeight( 0, QFontMetrics( cList->font() ).height() + 2 ); -} - -void CandidateWindow::updateSize() -{ - // size adjustment - cList->updateGeometry(); - setFixedSize(sizeHint()); -} - -void CandidateWindow::setIndex( int totalindex ) -{ - AbstractCandidateWindow::setIndex( totalindex ); - - // select item - if ( candidateIndex >= 0 ) { - int pos = totalindex; - if ( displayLimit ) - pos = candidateIndex % displayLimit; - - int row; - int column; - if ( isVertical ) { - row = pos; - column = 0; - } else { - row = 0; - column = pos; - } - if ( cList->item( row, column ) - && !cList->item( row, column )->isSelected() ) { - cList->clearSelection(); - if ( isVertical ) - cList->selectRow( pos ); - else - cList->selectColumn( pos ); - } - } else { - cList->clearSelection(); - } - - updateLabel(); -} - -void CandidateWindow::slotCandidateSelected( int row, int column ) -{ - candidateIndex = ( pageIndex * displayLimit ) - + ( isVertical ? row : column ); - if ( ic && ic->uimContext() ) - uim_set_candidate_index( ic->uimContext(), candidateIndex ); - updateLabel(); -} - -void CandidateWindow::shiftPage( bool forward ) -{ - AbstractCandidateWindow::shiftPage( forward ); - if ( candidateIndex != -1 ) { - cList->clearSelection(); - int idx = displayLimit ? candidateIndex % displayLimit : candidateIndex; - if ( isVertical ) - cList->selectRow( idx ); - else - cList->selectColumn( idx ); - } -} - - -#if UIM_QT_USE_NEW_PAGE_HANDLING -#endif /* UIM_QT_USE_NEW_PAGE_HANDLING */ - -void CandidateWindow::slotHookSubwindow() -{ - if ( !hasAnnotation || !subWin ) - return; - - QList list = cList->selectedItems(); - if ( list.isEmpty() ) - return; - QTableWidgetItem *item = list[0]; - - // cancel previous hook - subWin->cancelHook(); - - // hook annotation - QString annotationString - = annotations.at( isVertical ? item->row() : item->column() ); - if ( !annotationString.isEmpty() ) { - subWin->layoutWindow( subWindowRect( frameGeometry(), item ), - isVertical ); - subWin->hookPopup( annotationString ); - } -} - -// Moving and Resizing affects the position of Subwindow -void CandidateWindow::moveEvent( QMoveEvent *e ) -{ - // move subwindow - if ( subWin ) - subWin->layoutWindow( subWindowRect( QRect( e->pos(), size() ) ), - isVertical ); -} - -void CandidateWindow::resizeEvent( QResizeEvent *e ) -{ - // move subwindow - if ( subWin ) - subWin->layoutWindow( subWindowRect( QRect( pos(), e->size() ) ), - isVertical ); -} - -void CandidateWindow::hideEvent( QHideEvent *event ) -{ - QFrame::hideEvent( event ); - if ( subWin ) - subWin->cancelHook(); -} - -QRect CandidateWindow::subWindowRect( const QRect &rect, - const QTableWidgetItem *item ) -{ - if ( !item ) { - QList list = cList->selectedItems(); - if ( list.isEmpty() ) - return rect; - item = list[0]; - } - QRect r = rect; - if ( isVertical ) { - r.setY( rect.y() + cList->rowHeight( 0 ) * item->row() ); - } else { - int xdiff = 0; - for ( int i = 0, j = item->column(); i < j; i++ ) { - xdiff += cList->columnWidth( i ); - } - r.setX( rect.x() + xdiff ); - } - return r; -} - -QSize CandidateWindow::sizeHint() const -{ - QSize cListSizeHint = cList->sizeHint(); - - // According to the Qt4 documentation on the QFrame class, - // the frame width is 1 pixel. - int frame = 1 * 2; - int width = cListSizeHint.width() + frame; - int height = cListSizeHint.height() + numLabel->height() + frame; - - return QSize( width, height ); -} - -QSize CandidateListView::sizeHint() const -{ - // frame width - int frame = style()->pixelMetric( QStyle::PM_DefaultFrameWidth ) * 2; - - // the size of the dummy row should be 0. - const int rowNum = isVertical ? rowCount() : rowCount() - 1; - if ( rowNum == 0 ) { - return QSize( MIN_CAND_WIDTH, frame ); - } - int width = frame; - // the size of the dummy column should be 0. - for ( int i = 0; i < columnCount() - 1; i++ ) - width += columnWidth( i ); - - return QSize( width, rowHeight( 0 ) * rowNum + frame ); -} diff --git a/qt4/immodule/abstractcandidatewindow.cpp b/qt4/immodule/candidatewindowproxy.cpp similarity index 58% rename from qt4/immodule/abstractcandidatewindow.cpp rename to qt4/immodule/candidatewindowproxy.cpp index fb04a656e..4bf471ce8 100644 --- a/qt4/immodule/abstractcandidatewindow.cpp +++ b/qt4/immodule/candidatewindowproxy.cpp @@ -1,6 +1,6 @@ /* - copyright (c) 2010-2012 uim Project http://code.google.com/p/uim/ + copyright (c) 2012 uim Project http://code.google.com/p/uim/ All rights reserved. @@ -30,43 +30,52 @@ SUCH DAMAGE. */ -#include "abstractcandidatewindow.h" +#include +#include "candidatewindowproxy.h" + +#include +#include #include -#include -#include -#include #include +#if QT_VERSION < 0x050000 +# include +# include +# include +#else +# include +# include +# include +#endif -#include "quiminputcontext.h" +#include -const Qt::WindowFlags candidateFlag = (Qt::Window - | Qt::WindowStaysOnTopHint - | Qt::FramelessWindowHint - | Qt::Tool -#if defined(Q_WS_X11) - | Qt::X11BypassWindowManagerHint +#if QT_VERSION < 0x050000 +# include "quiminputcontext.h" +#else +# include "quimplatforminputcontext.h" #endif - ); -AbstractCandidateWindow::AbstractCandidateWindow(QWidget *parent) -: QFrame(parent, candidateFlag), ic(0), nrCandidates(0), displayLimit(0), - candidateIndex(-1), pageIndex(-1), window(0), isAlwaysLeft(false) +CandidateWindowProxy::CandidateWindowProxy() +: ic(0), nrCandidates(0), displayLimit(0), candidateIndex(-1), pageIndex(-1), + window(0), isAlwaysLeft(false) +#ifdef WORKAROUND_BROKEN_RESET_IN_QT4 +, m_isVisible(false) +#endif { - setFrameStyle(Raised|NoFrame); - - // setup NumberLabel - numLabel = new QLabel; - numLabel->adjustSize(); - #ifdef UIM_QT_USE_DELAY m_delayTimer = new QTimer(this); m_delayTimer->setSingleShot(true); connect(m_delayTimer, SIGNAL(timeout()), this, SLOT(timerDone())); #endif /* !UIM_QT_USE_DELAY */ + + process = new QProcess; + initializeProcess(); + connect(process, SIGNAL(readyReadStandardOutput()), + this, SLOT(slotReadyStandardOutput())); } -AbstractCandidateWindow::~AbstractCandidateWindow() +CandidateWindowProxy::~CandidateWindowProxy() { // clear stored candidate data while (!stores.isEmpty()) { @@ -74,19 +83,20 @@ AbstractCandidateWindow::~AbstractCandidateWindow() if (cand) uim_candidate_free(cand); } + process->close(); } -void AbstractCandidateWindow::deactivateCandwin() +void CandidateWindowProxy::deactivateCandwin() { #ifdef UIM_QT_USE_DELAY m_delayTimer->stop(); #endif /* !UIM_QT_USE_DELAY */ - hide(); + execute("hide"); clearCandidates(); } -void AbstractCandidateWindow::clearCandidates() +void CandidateWindowProxy::clearCandidates() { #ifdef ENABLE_DEBUG qDebug("clear Candidates"); @@ -104,50 +114,42 @@ void AbstractCandidateWindow::clearCandidates() } } -void AbstractCandidateWindow::popup() +void CandidateWindowProxy::popup() { - window = QApplication::focusWidget()->window(); - window->installEventFilter(this); - raise(); - show(); + execute("popup"); } -void AbstractCandidateWindow::layoutWindow(const QPoint &point, - const QRect &rect) +void CandidateWindowProxy::hide() { - const int x = point.x(); - const int y = point.y(); - const int h = rect.height(); - int destX = x; - int destY = y + h; - - int screenW = QApplication::desktop()->screenGeometry().width(); - int screenH = QApplication::desktop()->screenGeometry().height(); - - if (destX + width() > screenW) - destX = screenW - width(); + execute("hide"); +} - if (destY + height() > screenH) - destY = y - height(); +#ifdef WORKAROUND_BROKEN_RESET_IN_QT4 +bool CandidateWindowProxy::isVisible() +{ + return m_isVisible; +} +#endif - move(destX, destY); +void CandidateWindowProxy::layoutWindow(int x, int y, int height) +{ + execute("layout_window\f" + QString::number(x) + '\f' + + QString::number(y) + '\f' + QString::number(height)); } -void AbstractCandidateWindow::candidateActivate(int nr, int displayLimit) +void CandidateWindowProxy::candidateActivate(int nr, int displayLimit) { #ifdef UIM_QT_USE_DELAY m_delayTimer->stop(); #endif /* !UIM_QT_USE_DELAY */ - QList list; + QList list; #if !UIM_QT_USE_NEW_PAGE_HANDLING activateCandwin(displayLimit); // set candidates - uim_candidate cand; - for (int i = 0; i < nr; i++) - { + for (int i = 0; i < nr; i++) { cand = uim_get_candidate(ic->uimContext(), i, displayLimit ? i % displayLimit : i); list.append(cand); @@ -166,26 +168,25 @@ void AbstractCandidateWindow::candidateActivate(int nr, int displayLimit) preparePageCandidates(0); setPage(0); #endif /* !UIM_QT_USE_NEW_PAGE_HANDLING */ - popup(); - ic->setCandwinActive(); + + execute("candidate_activate"); } #ifdef UIM_QT_USE_DELAY -void AbstractCandidateWindow::candidateActivateWithDelay(int delay) +void CandidateWindowProxy::candidateActivateWithDelay(int delay) { m_delayTimer->stop(); (delay > 0) ? m_delayTimer->start(delay * 1000) : timerDone(); } #endif /* !UIM_QT_USE_DELAY */ -void AbstractCandidateWindow::candidateSelect(int index) +void CandidateWindowProxy::candidateSelect(int index) { #if UIM_QT_USE_NEW_PAGE_HANDLING - int new_page; - if (index >= nrCandidates) index = 0; + int new_page; if (index >= 0 && displayLimit) new_page = index / displayLimit; else @@ -196,7 +197,7 @@ void AbstractCandidateWindow::candidateSelect(int index) setIndex(index); } -void AbstractCandidateWindow::candidateShiftPage(bool forward) +void CandidateWindowProxy::candidateShiftPage(bool forward) { #if UIM_QT_USE_NEW_PAGE_HANDLING int new_page, index; @@ -214,41 +215,142 @@ void AbstractCandidateWindow::candidateShiftPage(bool forward) shiftPage(forward); } -void AbstractCandidateWindow::activateCandwin(int dLimit) +// -v -> vertical +// -h -> horizontal +// -t -> table +QString CandidateWindowProxy::candidateWindowStyle() +{ + QString windowStyle; + // uim-candwin-prog is deprecated + char *candwinprog = uim_scm_symbol_value_str("uim-candwin-prog"); + if (candwinprog) { + if (!strncmp(candwinprog, "uim-candwin-tbl", 15)) + windowStyle = "-t"; + else if (!strncmp(candwinprog, "uim-candwin-horizontal", 22)) + windowStyle = "-h"; + } else { + char *style = uim_scm_symbol_value_str("candidate-window-style"); + if (style) { + if (!strcmp(style, "table")) + windowStyle = "-t"; + else if (!strcmp(style, "horizontal")) + windowStyle = "-h"; + } + free(style); + } + free(candwinprog); + + if (windowStyle.isEmpty()) + return "-v"; + return windowStyle; +} + +void CandidateWindowProxy::slotReadyStandardOutput() +{ + QByteArray output = process->readAllStandardOutput(); + QList messageList = parse_messages(QString(output)); + for (int i = 0, j = messageList.count(); i < j; i++) { + QStringList message = messageList[i]; + QString command = message[0]; + if (command == "set_candidate_index") { + uim_set_candidate_index(ic->uimContext(), message[1].toInt()); + } else if (command == "set_candidate_index_2") { + candidateIndex = pageIndex * displayLimit + message[1].toInt(); + uim_set_candidate_index(ic->uimContext(), candidateIndex); + } else if (command == "set_candwin_active") { + ic->setCandwinActive(); + } else if (command == "set_focus_widget") { + setFocusWidget(); + } else if (command == "update_label") { + updateLabel(); + } +#ifdef WORKAROUND_BROKEN_RESET_IN_QT4 + else if (command == "shown") { + m_isVisible = true; + } else if (command == "hidden") { + m_isVisible = false; + } +#endif + } +} + +#ifdef UIM_QT_USE_DELAY +void CandidateWindowProxy::timerDone() +{ + int nr = -1; + int display_limit = -1; + int selected_index = -1; + uim_delay_activating(ic->uimContext(), &nr, &display_limit, + &selected_index); + if (nr <= 0) { + return; + } + candidateActivate(nr, display_limit); + if (selected_index >= 0) { + candidateSelect(selected_index); + } +} +#endif /* !UIM_QT_USE_DELAY */ + +void CandidateWindowProxy::initializeProcess() +{ + if (process->state() != QProcess::NotRunning) { + return; + } + process->close(); + QString style = candidateWindowStyle(); +#if QT_VERSION < 0x050000 + process->start(UIM_LIBEXECDIR "/uim-candwin-qt4", QStringList() << style); +#else + process->start(UIM_LIBEXECDIR "/uim-candwin-qt5", QStringList() << style); +#endif + process->waitForStarted(); +} + +void CandidateWindowProxy::execute(const QString &command) +{ + initializeProcess(); + process->write((command + "\f\f").toUtf8()); +} + +void CandidateWindowProxy::activateCandwin(int dLimit) { candidateIndex = -1; displayLimit = dLimit; pageIndex = 0; + execute("setup_sub_window"); } -void AbstractCandidateWindow::shiftPage(bool forward) +void CandidateWindowProxy::shiftPage(bool forward) { #ifdef ENABLE_DEBUG qDebug("candidateIndex = %d", candidateIndex); #endif - if (forward) - { + if (forward) { if (candidateIndex != -1) candidateIndex += displayLimit; setPage(pageIndex + 1); - } - else - { + } else { if (candidateIndex != -1) { if (candidateIndex < displayLimit) - candidateIndex = displayLimit * (nrCandidates / displayLimit) + candidateIndex; + candidateIndex = displayLimit * (nrCandidates / displayLimit) + + candidateIndex; else candidateIndex -= displayLimit; } - setPage(pageIndex - 1); } if (ic && ic->uimContext() && candidateIndex != -1) uim_set_candidate_index(ic->uimContext(), candidateIndex); + // for CandidateWindow + if (candidateIndex != -1) { + int idx = displayLimit ? candidateIndex % displayLimit : candidateIndex; + execute("shift_page\f" + QString::number(idx)); + } } -void AbstractCandidateWindow::setIndex(int totalindex) +void CandidateWindowProxy::setIndex(int totalindex) { #ifdef ENABLE_DEBUG qDebug("setIndex : totalindex = %d", totalindex); @@ -268,10 +370,13 @@ void AbstractCandidateWindow::setIndex(int totalindex) newpage = candidateIndex / displayLimit; if (pageIndex != newpage) setPage(newpage); + execute("set_index\f" + QString::number(totalindex) + + '\f' + QString::number(displayLimit) + + '\f' + QString::number(candidateIndex)); } #if UIM_QT_USE_NEW_PAGE_HANDLING -void AbstractCandidateWindow::setNrCandidates(int nrCands, int dLimit) +void CandidateWindowProxy::setNrCandidates(int nrCands, int dLimit) { #ifdef ENABLE_DEBUG qDebug("setNrCandidates"); @@ -288,32 +393,25 @@ void AbstractCandidateWindow::setNrCandidates(int nrCands, int dLimit) // setup dummy candidate for (int i = 0; i < nrCandidates; i++) - { - uim_candidate d = 0; - stores.append(d); - } + stores.append(0); + + execute("setup_sub_window"); } #endif /* UIM_QT_USE_NEW_PAGE_HANDLING */ -#ifdef UIM_QT_USE_DELAY -void AbstractCandidateWindow::timerDone() +void CandidateWindowProxy::updateLabel() { - int nr = -1; - int display_limit = -1; - int selected_index = -1; - uim_delay_activating(ic->uimContext(), &nr, &display_limit, - &selected_index); - if (nr <= 0) { - return; - } - candidateActivate(nr, display_limit); - if (selected_index >= 0) { - candidateSelect(selected_index); - } + QString indexString; + if (candidateIndex >= 0) + indexString = QString::number(candidateIndex + 1) + " / " + + QString::number(nrCandidates); + else + indexString = "- / " + QString::number(nrCandidates); + + execute("update_label\f" + indexString); } -#endif /* !UIM_QT_USE_DELAY */ -void AbstractCandidateWindow::setCandidates(int dl, +void CandidateWindowProxy::setCandidates(int dl, const QList &candidates) { #ifdef ENABLE_DEBUG @@ -339,7 +437,7 @@ void AbstractCandidateWindow::setCandidates(int dl, setPage(0); } -void AbstractCandidateWindow::setPage(int page) +void CandidateWindowProxy::setPage(int page) { #ifdef ENABLE_DEBUG qDebug("setPage : page = %d", page); @@ -381,7 +479,17 @@ void AbstractCandidateWindow::setPage(int page) if (newpage == lastpage) ncandidates = nrCandidates - displayLimit * lastpage; - updateView(newpage, ncandidates); + QString candidateMessage; + for (int i = 0; i < ncandidates; i++) { + uim_candidate cand = stores.at(displayLimit * newpage + i); + candidateMessage += + QString::fromUtf8(uim_candidate_get_heading_label(cand)) + '\a' + + QString::fromUtf8(uim_candidate_get_cand_str(cand)) + '\a' + + QString::fromUtf8(uim_candidate_get_annotation_str(cand)) + '\f'; + } + + execute("update_view\f" + QString::number(ncandidates) + "\f" + + candidateMessage); // set index if (newindex != candidateIndex) @@ -389,11 +497,11 @@ void AbstractCandidateWindow::setPage(int page) else updateLabel(); - updateSize(); + execute("update_size"); } #if UIM_QT_USE_NEW_PAGE_HANDLING -void AbstractCandidateWindow::setPageCandidates(int page, +void CandidateWindowProxy::setPageCandidates(int page, const QList &candidates) { #ifdef ENABLE_DEBUG @@ -416,7 +524,7 @@ void AbstractCandidateWindow::setPageCandidates(int page, stores[start + i] = candidates[i]; } -void AbstractCandidateWindow::preparePageCandidates(int page) +void CandidateWindowProxy::preparePageCandidates(int page) { QList list; @@ -427,8 +535,6 @@ void AbstractCandidateWindow::preparePageCandidates(int page) return; // set page candidates - uim_candidate cand; - int start = page * displayLimit; int pageNr; @@ -437,9 +543,9 @@ void AbstractCandidateWindow::preparePageCandidates(int page) else pageNr = nrCandidates - start; - for (int i = start; i < pageNr + start; i++) - { - cand = uim_get_candidate(ic->uimContext(), i, + for (int i = start; i < pageNr + start; i++) { + // set page candidates + uim_candidate cand = uim_get_candidate(ic->uimContext(), i, displayLimit ? i % displayLimit : i); list.append(cand); } @@ -448,19 +554,13 @@ void AbstractCandidateWindow::preparePageCandidates(int page) } #endif /* UIM_QT_USE_NEW_PAGE_HANDLING */ -void AbstractCandidateWindow::updateLabel() +void CandidateWindowProxy::setFocusWidget() { - QString indexString; - if (candidateIndex >= 0) - indexString = QString::number(candidateIndex + 1) + " / " - + QString::number(nrCandidates); - else - indexString = "- / " + QString::number(nrCandidates); - - numLabel->setText(indexString); + window = QApplication::focusWidget()->window(); + window->installEventFilter(this); } -bool AbstractCandidateWindow::eventFilter(QObject *obj, QEvent *event) +bool CandidateWindowProxy::eventFilter(QObject *obj, QEvent *event) { if (obj == window) { if (event->type() == QEvent::Move) { @@ -469,13 +569,17 @@ bool AbstractCandidateWindow::eventFilter(QObject *obj, QEvent *event) QRect rect = widget->inputMethodQuery(Qt::ImMicroFocus).toRect(); QPoint p = widget->mapToGlobal(rect.topLeft()); - layoutWindow(p, rect); + execute("layout_window\f" + QString::number(p.x()) + '\f' + + QString::number(p.y()) + '\f' + + QString::number(rect.height())); } else { QMoveEvent *moveEvent = static_cast(event); - move(pos() + moveEvent->pos() - moveEvent->oldPos()); + QPoint p = moveEvent->pos() - moveEvent->oldPos(); + execute("move_candwin\f" + QString::number(p.x()) + '\f' + + QString::number(p.y())); } } return false; } - return QFrame::eventFilter(obj, event); + return QObject::eventFilter(obj, event); } diff --git a/qt4/immodule/abstractcandidatewindow.h b/qt4/immodule/candidatewindowproxy.h similarity index 70% rename from qt4/immodule/abstractcandidatewindow.h rename to qt4/immodule/candidatewindowproxy.h index 208cdd93f..54fb0ccb8 100644 --- a/qt4/immodule/abstractcandidatewindow.h +++ b/qt4/immodule/candidatewindowproxy.h @@ -1,6 +1,6 @@ /* - copyright (c) 2010-2012 uim Project http://code.google.com/p/uim/ + copyright (c) 2012 uim Project http://code.google.com/p/uim/ All rights reserved. @@ -30,42 +30,54 @@ SUCH DAMAGE. */ -#ifndef UIM_QT4_IMMODULE_ABSTRACT_CANDIDATE_WINDOW_H -#define UIM_QT4_IMMODULE_ABSTRACT_CANDIDATE_WINDOW_H +#ifndef UIM_QT4_IMMODULE_CANDIDATE_WINDOW_PROXY_H +#define UIM_QT4_IMMODULE_CANDIDATE_WINDOW_PROXY_H -#include -#include +#include -#include +#include -// enable per page candidates handling -#define UIM_QT_USE_NEW_PAGE_HANDLING 1 -// enable delay showing candidate window -#define UIM_QT_USE_DELAY 1 +#include "util.h" -class QLabel; +class QPoint; +class QProcess; +class QRect; class QTimer; +#if QT_VERSION < 0x050000 class QUimInputContext; +#else +class QUimPlatformInputContext; +#endif -class AbstractCandidateWindow : public QFrame +class CandidateWindowProxy : public QObject { Q_OBJECT public: - explicit AbstractCandidateWindow(QWidget *parent); - virtual ~AbstractCandidateWindow(); + explicit CandidateWindowProxy(); + virtual ~CandidateWindowProxy(); void deactivateCandwin(); void clearCandidates(); + void popup(); + void hide(); +#ifdef WORKAROUND_BROKEN_RESET_IN_QT4 + bool isVisible(); +#endif void setAlwaysLeftPosition(bool left) { isAlwaysLeft = left; } bool isAlwaysLeftPosition() const { return isAlwaysLeft; } - void layoutWindow(const QPoint &point, const QRect &rect); + void layoutWindow(int x, int y, int height); +#if QT_VERSION < 0x050000 void setQUimInputContext(QUimInputContext *m_ic) { ic = m_ic; } +#else + void setQUimPlatformInputContext(QUimPlatformInputContext *m_ic) + { ic = m_ic; } +#endif void candidateActivate(int nr, int displayLimit); #ifdef UIM_QT_USE_DELAY @@ -74,22 +86,44 @@ class AbstractCandidateWindow : public QFrame void candidateSelect(int index); void candidateShiftPage(bool forward); - protected: - virtual void activateCandwin(int dLimit); + QString candidateWindowStyle(); + + private slots: + void slotReadyStandardOutput(); +#ifdef UIM_QT_USE_DELAY + void timerDone(); +#endif /* !UIM_QT_USE_DELAY */ + + private: + void initializeProcess(); + void execute(const QString &command); + + void activateCandwin(int dLimit); - virtual void shiftPage(bool forward); - virtual void setIndex(int totalindex); + void shiftPage(bool forward); + void setIndex(int totalindex); #ifdef UIM_QT_USE_NEW_PAGE_HANDLING - virtual void setNrCandidates(int nrCands, int dLimit); + void setNrCandidates(int nrCands, int dLimit); #endif - virtual void updateView(int newpage, int ncandidates) = 0; - virtual void updateSize() = 0; void updateLabel(); + void setCandidates(int displayLimit, + const QList &candidates); + void setPage(int page); +#ifdef UIM_QT_USE_NEW_PAGE_HANDLING + void setPageCandidates(int page, + const QList &candidates); + void preparePageCandidates(int page); +#endif - QUimInputContext *ic; + void setFocusWidget(); + bool eventFilter(QObject *obj, QEvent *event); - // widget - QLabel *numLabel; + QProcess *process; +#if QT_VERSION < 0x050000 + QUimInputContext *ic; +#else + QUimPlatformInputContext *ic; +#endif // candidate data QList stores; @@ -101,36 +135,25 @@ class AbstractCandidateWindow : public QFrame QList pageFilled; #endif -#ifdef UIM_QT_USE_DELAY - private slots: - void timerDone(); -#endif /* !UIM_QT_USE_DELAY */ - - private: - void setCandidates(int displayLimit, - const QList &candidates); - void setPage(int page); -#ifdef UIM_QT_USE_NEW_PAGE_HANDLING - void setPageCandidates(int page, - const QList &candidates); - void preparePageCandidates(int page); -#endif - bool eventFilter(QObject *obj, QEvent *event); - - // widget + // widget to follow movement QWidget *window; // candidate data #ifdef UIM_QT_USE_NEW_PAGE_HANDLING int nrPages; #endif + // config bool isAlwaysLeft; +#ifdef WORKAROUND_BROKEN_RESET_IN_QT4 + bool m_isVisible; +#endif + #ifdef UIM_QT_USE_DELAY // timer for delay API QTimer *m_delayTimer; #endif /* !UIM_QT_USE_DELAY */ }; -#endif /* Not def: UIM_QT4_IMMODULE_ABSTRACT_CANDIDATE_WINDOW_H */ +#endif /* Not def: UIM_QT4_IMMODULE_CANDIDATE_WINDOW_PROXY_H */ diff --git a/qt4/immodule/caretstateindicator.cpp b/qt4/immodule/caretstateindicator.cpp index a42f9ea7a..801f4e949 100644 --- a/qt4/immodule/caretstateindicator.cpp +++ b/qt4/immodule/caretstateindicator.cpp @@ -35,10 +35,16 @@ #include #include #include -#include -#include -#include #include +#if QT_VERSION < 0x050000 +# include +# include +# include +#else +# include +# include +# include +#endif #include diff --git a/qt4/immodule/caretstateindicator.h b/qt4/immodule/caretstateindicator.h index c3c53f135..a940ec8fa 100644 --- a/qt4/immodule/caretstateindicator.h +++ b/qt4/immodule/caretstateindicator.h @@ -32,7 +32,12 @@ #ifndef UIM_QT4_CARET_STATE_INDICATOR_H #define UIM_QT4_CARET_STATE_INDICATOR_H -#include +#include +#if QT_VERSION < 0x050000 +# include +#else +# include +#endif class QLabel; class QTimer; diff --git a/qt4/immodule/plugin.cpp b/qt4/immodule/plugin.cpp index b582ea485..0f76b8711 100644 --- a/qt4/immodule/plugin.cpp +++ b/qt4/immodule/plugin.cpp @@ -35,9 +35,13 @@ #include "plugin.h" #include -#include #ifdef Q_WS_X11 -#include +# include +#endif +#if QT_VERSION < 0x050000 +# include +#else +# include #endif #include "uim/uim.h" @@ -45,6 +49,16 @@ #include "uim/counted-init.h" #include "quiminfomanager.h" +#if QT_VERSION >= 0x050000 +# undef Bool +# undef Expose +# undef FocusIn +# undef FocusOut +# undef FontChange +# undef KeyPress +# undef KeyRelease +# undef None +#endif #include "quiminputcontext_with_slave.h" #define UIM_QT_LIST_SUBIM_AS_QTIM 0 @@ -68,8 +82,15 @@ QStringList UimInputContextPlugin::keys() const return createImList(); } +#if QT_VERSION < 0x050000 QInputContext *UimInputContextPlugin::create( const QString & key ) +#else +QPlatformInputContext *UimInputContextPlugin::create( const QString & key, const QStringList & paramList ) +#endif { +#if QT_VERSION >= 0x050000 + Q_UNUSED(paramList); +#endif QString imname; #if UIM_QT_LIST_SUBIM_AS_QTIM @@ -80,11 +101,17 @@ QInputContext *UimInputContextPlugin::create( const QString & key ) if ( key == "uim" ) imname = uim_get_default_im_name( setlocale( LC_CTYPE, 0 ) ); +#if QT_VERSION < 0x050000 QUimInputContext *uic = new QUimInputContext( imname.toUtf8().data() ); +#else + QUimPlatformInputContext *uic + = new QUimPlatformInputContext( imname.toUtf8().data() ); +#endif return uic; } +#if QT_VERSION < 0x050000 QStringList UimInputContextPlugin::languages( const QString & key ) { return createLanguageList( key ); @@ -99,6 +126,7 @@ QString UimInputContextPlugin::description( const QString & key ) { return displayName( key ) + ": an input method provided via the uim input method framework"; } +#endif QUimInfoManager * UimInputContextPlugin::getQUimInfoManager() @@ -164,6 +192,7 @@ QStringList UimInputContextPlugin::createImList() const return lst; } +#if QT_VERSION < 0x050000 QStringList UimInputContextPlugin::createLanguageList( const QString &key ) const { if ( key == "uim" ) @@ -193,5 +222,8 @@ QStringList UimInputContextPlugin::createLanguageList( const QString &key ) cons return QStringList( "" ); } +#endif +#if QT_VERSION < 0x050000 Q_EXPORT_PLUGIN2( uiminputcontextplugin, UimInputContextPlugin ) +#endif diff --git a/qt4/immodule/plugin.h b/qt4/immodule/plugin.h index d6f791cdd..410a74a6c 100644 --- a/qt4/immodule/plugin.h +++ b/qt4/immodule/plugin.h @@ -34,24 +34,43 @@ #ifndef UIM_QT4_IMMODULE_PLUGIN_H #define UIM_QT4_IMMODULE_PLUGIN_H -#include +#include +#if QT_VERSION < 0x050000 +# include +#else +# include +#endif class QStringList; class QUimInfoManager; +#if QT_VERSION < 0x050000 class UimInputContextPlugin : public QInputContextPlugin +#else +class UimInputContextPlugin : public QPlatformInputContextPlugin +#endif { Q_OBJECT +#if QT_VERSION >= 0x050000 + Q_PLUGIN_METADATA(IID + "org.qt-project.Qt.QPlatformInputContextFactoryInterface" + FILE "../../qt5/immodule/uim.json") +#endif public: UimInputContextPlugin(); ~UimInputContextPlugin(); QStringList keys() const; +#if QT_VERSION < 0x050000 QInputContext *create( const QString &key ); QStringList languages( const QString &key ); QString displayName( const QString &key ); QString description( const QString &key ); +#else + QPlatformInputContext *create( const QString &key, + const QStringList ¶mList ); +#endif static QUimInfoManager *getQUimInfoManager(); @@ -60,7 +79,9 @@ class UimInputContextPlugin : public QInputContextPlugin void uimQuit(); QStringList createImList() const; +#if QT_VERSION < 0x050000 QStringList createLanguageList( const QString &key ) const; +#endif static QUimInfoManager *infoManager; bool uimReady; diff --git a/qt4/immodule/qhelpermanager.cpp b/qt4/immodule/qhelpermanager.cpp index 45ad20165..47416d711 100644 --- a/qt4/immodule/qhelpermanager.cpp +++ b/qt4/immodule/qhelpermanager.cpp @@ -43,15 +43,27 @@ SUCH DAMAGE. #include "plugin.h" #include "quiminfomanager.h" -#include "quiminputcontext.h" +#if QT_VERSION < 0x050000 +# include "quiminputcontext.h" +#else +# include "quimplatforminputcontext.h" +#endif static int im_uim_fd = 0; static QSocketNotifier *notifier = 0; +#if QT_VERSION < 0x050000 extern QUimInputContext *focusedInputContext; +#else +extern QUimPlatformInputContext *focusedInputContext; +#endif extern bool disableFocusedContext; +#if QT_VERSION < 0x050000 extern QList contextList; +#else +extern QList contextList; +#endif QUimHelperManager::QUimHelperManager( QObject *parent ) : QObject( parent ) @@ -153,7 +165,11 @@ void QUimHelperManager::parseHelperStr( const QString &str ) if ( !list.isEmpty() && !list[ 0 ].isEmpty() && !list[ 1 ].isEmpty() && !list[ 2 ].isEmpty() ) { +#if QT_VERSION < 0x050000 QList::iterator it; +#else + QList::iterator it; +#endif for ( it = contextList.begin(); it != contextList.end(); ++it ) { uim_prop_update_custom( ( *it )->uimContext(), @@ -177,7 +193,11 @@ void QUimHelperManager::parseHelperStr( const QString &str ) UimInputContextPlugin::getQUimInfoManager(); infoManager->initUimInfo(); +#if QT_VERSION < 0x050000 QList::iterator it; +#else + QList::iterator it; +#endif for ( it = contextList.begin(); it != contextList.end(); ++it ) { ( *it )->updatePosition(); ( *it )->updateStyle(); @@ -203,7 +223,11 @@ void QUimHelperManager::parseHelperStrImChange( const QString &str ) } else if ( str.startsWith( QLatin1String( "im_change_whole_desktop" ) ) ) { +#if QT_VERSION < 0x050000 QList::iterator it; +#else + QList::iterator it; +#endif for ( it = contextList.begin(); it != contextList.end(); ++it ) { uim_switch_im( ( *it )->uimContext(), im_name.toUtf8().data() ); @@ -218,7 +242,11 @@ void QUimHelperManager::parseHelperStrImChange( const QString &str ) { if ( focusedInputContext ) { +#if QT_VERSION < 0x050000 QList::iterator it; +#else + QList::iterator it; +#endif for ( it = contextList.begin(); it != contextList.end(); ++it ) { uim_switch_im( ( *it )->uimContext(), im_name.toUtf8().data() ); @@ -283,7 +311,11 @@ void QUimHelperManager::helper_disconnect_cb() void QUimHelperManager::update_prop_list_cb( void *ptr, const char *str ) { +#if QT_VERSION < 0x050000 QUimInputContext *ic = static_cast( ptr ); +#else + QUimPlatformInputContext *ic = static_cast( ptr ); +#endif if ( ic != focusedInputContext || disableFocusedContext ) return; @@ -298,7 +330,11 @@ void QUimHelperManager::update_prop_list_cb( void *ptr, const char *str ) void QUimHelperManager::update_prop_label_cb( void *ptr, const char *str ) { +#if QT_VERSION < 0x050000 QUimInputContext *ic = static_cast( ptr ); +#else + QUimPlatformInputContext *ic = static_cast( ptr ); +#endif if ( ic != focusedInputContext || disableFocusedContext ) return; diff --git a/qt4/immodule/qtextutil.cpp b/qt4/immodule/qtextutil.cpp index 91552dad0..c56aa1762 100644 --- a/qt4/immodule/qtextutil.cpp +++ b/qt4/immodule/qtextutil.cpp @@ -35,20 +35,34 @@ SUCH DAMAGE. #include -#include #include -#include -#include -#ifdef ENABLE_QT4_QT3SUPPORT -# include +#if QT_VERSION < 0x050000 +# include +# include +# include +# ifdef ENABLE_QT4_QT3SUPPORT +# include +# endif +#else +# include +# include +# include #endif +#if QT_VERSION < 0x050000 #include "quiminputcontext.h" +#else +#include "quimplatforminputcontext.h" +#endif QUimTextUtil::QUimTextUtil( QObject *parent ) : QObject( parent ) { +#if QT_VERSION < 0x050000 mIc = static_cast( parent ); +#else + mIc = static_cast( parent ); +#endif mPreeditSaved = false; } @@ -63,7 +77,12 @@ QUimTextUtil::acquire_text_cb( void *ptr, enum UTextArea text_id, char **former, char **latter ) { int err; +#if QT_VERSION < 0x050000 QUimInputContext *ic = static_cast( ptr ); +#else + QUimPlatformInputContext *ic + = static_cast( ptr ); +#endif QUimTextUtil *tu = ic->textUtil(); switch ( text_id ) { @@ -93,7 +112,12 @@ QUimTextUtil::delete_text_cb( void *ptr, enum UTextArea text_id, int former_req_len, int latter_req_len ) { int err; +#if QT_VERSION < 0x050000 QUimInputContext *ic = static_cast( ptr ); +#else + QUimPlatformInputContext *ic + = static_cast( ptr ); +#endif QUimTextUtil *tu = ic->textUtil(); switch ( text_id ) { diff --git a/qt4/immodule/qtextutil.h b/qt4/immodule/qtextutil.h index db997f8e1..b853963d7 100644 --- a/qt4/immodule/qtextutil.h +++ b/qt4/immodule/qtextutil.h @@ -37,7 +37,11 @@ SUCH DAMAGE. #include "uim/uim.h" +#if QT_VERSION < 0x050000 class QUimInputContext; +#else +class QUimPlatformInputContext; +#endif class QUimTextUtil : QObject { @@ -118,7 +122,11 @@ class QUimTextUtil : QObject void restorePreedit(); QWidget *mWidget; +#if QT_VERSION < 0x050000 QUimInputContext *mIc; +#else + QUimPlatformInputContext *mIc; +#endif bool mPreeditSaved; }; diff --git a/qt4/immodule/quiminputcontext.cpp b/qt4/immodule/quiminputcontext.cpp index 73ade64a6..0f265dd9a 100644 --- a/qt4/immodule/quiminputcontext.cpp +++ b/qt4/immodule/quiminputcontext.cpp @@ -46,8 +46,7 @@ #include #include -#include "candidatetablewindow.h" -#include "candidatewindow.h" +#include "candidatewindowproxy.h" #include "caretstateindicator.h" #include "plugin.h" #include "qhelpermanager.h" @@ -123,12 +122,12 @@ QUimInputContext::~QUimInputContext() if ( m_uc ) uim_release_context( m_uc ); - delete cwin; + delete proxy; #ifdef WORKAROUND_BROKEN_RESET_IN_QT4 foreach ( const uim_context uc, m_ucHash ) if ( uc ) uim_release_context( uc ); - foreach ( const AbstractCandidateWindow* window, cwinHash ) + foreach ( const CandidateWindowProxy* window, proxyHash ) delete window; #endif @@ -188,31 +187,9 @@ uim_context QUimInputContext::createUimContext( const char *imname ) void QUimInputContext::createCandidateWindow() { - cwin = 0; - // uim-candwin-prog is deprecated - char *candwinprog = uim_scm_symbol_value_str( "uim-candwin-prog" ); - if ( candwinprog ) { - if ( !strncmp( candwinprog, "uim-candwin-tbl", 15 ) ) - cwin = new CandidateTableWindow( 0 ); - else if ( !strncmp( candwinprog, "uim-candwin-horizontal", 22 ) ) - cwin = new CandidateWindow( 0, false ); - } else { - char *style = uim_scm_symbol_value_str( "candidate-window-style" ); - if ( style ) { - if ( !strcmp( style, "table" ) ) - cwin = new CandidateTableWindow( 0 ); - else if ( !strcmp( style, "horizontal" ) ) - cwin = new CandidateWindow( 0, false ); - } - free( style ); - } - free( candwinprog ); - - if ( !cwin ) - cwin = new CandidateWindow( 0 ); - - cwin->setQUimInputContext( this ); - cwin->hide(); + proxy = new CandidateWindowProxy; + proxy->setQUimInputContext( this ); + proxy->hide(); } #ifdef Q_WS_X11 @@ -419,7 +396,7 @@ void QUimInputContext::setFocus() else #endif if ( candwinIsActive ) - cwin->popup(); + proxy->popup(); m_HelperManager->checkHelperConnection(); @@ -439,7 +416,7 @@ void QUimInputContext::unsetFocus() uim_focus_out_context( m_uc ); - cwin->hide(); + proxy->hide(); m_indicator->hide(); m_HelperManager->checkHelperConnection(); @@ -487,11 +464,11 @@ void QUimInputContext::reset() // until focused again. if ( isPreeditPreservationEnabled() && !m_ucHash.contains( focusedWidget ) ) { - psegs.isEmpty() ? cwin->hide() : savePreedit(); + psegs.isEmpty() ? proxy->hide() : savePreedit(); return; } #endif - cwin->hide(); + proxy->hide(); uim_reset_context( m_uc ); #ifdef Q_WS_X11 mCompose->reset(); @@ -511,7 +488,7 @@ void QUimInputContext::update() if ( w ) { QRect mf = w->inputMethodQuery( Qt::ImMicroFocus ).toRect(); QPoint p = w->mapToGlobal( mf.topLeft() ); - cwin->layoutWindow( p, mf ); + proxy->layoutWindow( p.x(), p.y(), mf.height() ); m_indicator->move( w->mapToGlobal( mf.bottomLeft() ) + QPoint( 0, CaretStateIndicator::SPACING ) ); } @@ -588,7 +565,7 @@ void QUimInputContext::cand_activate_cb( void *ptr, int nr, int displayLimit ) #endif QUimInputContext *ic = static_cast( ptr ); - ic->cwin->candidateActivate( nr, displayLimit ); + ic->proxy->candidateActivate( nr, displayLimit ); } void QUimInputContext::cand_select_cb( void *ptr, int index ) @@ -598,7 +575,7 @@ void QUimInputContext::cand_select_cb( void *ptr, int index ) #endif QUimInputContext *ic = static_cast( ptr ); - ic->cwin->candidateSelect( index ); + ic->proxy->candidateSelect( index ); } void QUimInputContext::cand_shift_page_cb( void *ptr, int forward ) @@ -608,7 +585,7 @@ void QUimInputContext::cand_shift_page_cb( void *ptr, int forward ) #endif QUimInputContext *ic = static_cast( ptr ); - ic->cwin->candidateShiftPage( forward ); + ic->proxy->candidateShiftPage( forward ); } void QUimInputContext::cand_deactivate_cb( void *ptr ) @@ -618,7 +595,7 @@ void QUimInputContext::cand_deactivate_cb( void *ptr ) #endif QUimInputContext *ic = static_cast( ptr ); - ic->cwin->deactivateCandwin(); + ic->proxy->deactivateCandwin(); ic->candwinIsActive = false; } @@ -638,7 +615,7 @@ void QUimInputContext::switch_system_global_im_cb( void *ptr, const char *name ) void QUimInputContext::cand_activate_with_delay_cb( void *ptr, int delay ) { QUimInputContext *ic = static_cast( ptr ); - ic->cwin->candidateActivateWithDelay( delay ); + ic->proxy->candidateActivateWithDelay( delay ); } #endif /* !UIM_QT_USE_DELAY */ @@ -690,9 +667,9 @@ void QUimInputContext::savePreedit() { m_ucHash.insert( focusedWidget, m_uc ); psegsHash.insert( focusedWidget, psegs ); - cwinHash.insert( focusedWidget, cwin ); - visibleHash.insert( focusedWidget, cwin->isVisible() ); - cwin->hide(); + proxyHash.insert( focusedWidget, proxy ); + visibleHash.insert( focusedWidget, proxy->isVisible() ); + proxy->hide(); const char *imname = uim_get_current_im_name( m_uc ); if ( imname ) @@ -703,7 +680,7 @@ void QUimInputContext::savePreedit() void QUimInputContext::restorePreedit() { - AbstractCandidateWindow *window = cwinHash.take( focusedWidget ); + CandidateWindowProxy *window = proxyHash.take( focusedWidget ); // if window is 0, updateStyle() was called. if ( !window ) { psegs = psegsHash.take( focusedWidget ); @@ -721,12 +698,12 @@ void QUimInputContext::restorePreedit() } if ( m_uc ) uim_release_context( m_uc ); - delete cwin; + delete proxy; m_uc = m_ucHash.take( focusedWidget ); psegs = psegsHash.take( focusedWidget ); - cwin = window; + proxy = window; if ( visibleHash.take( focusedWidget ) ) - cwin->popup(); + proxy->popup(); } #endif @@ -770,7 +747,7 @@ QString QUimInputContext::getPreeditString() int QUimInputContext::getPreeditCursorPosition() { - if ( cwin->isAlwaysLeftPosition() ) + if ( proxy->isAlwaysLeftPosition() ) return 0; int cursorPos = 0; @@ -933,7 +910,7 @@ void QUimInputContext::switch_system_global_im( const char *name ) void QUimInputContext::updatePosition() { char * leftp = uim_scm_symbol_value_str( "candidate-window-position" ); - cwin->setAlwaysLeftPosition( leftp && !strcmp( leftp, "left" ) ); + proxy->setAlwaysLeftPosition( leftp && !strcmp( leftp, "left" ) ); free( leftp ); } @@ -945,16 +922,16 @@ void QUimInputContext::updateStyle() free( candwinprog ); return; } - delete cwin; + delete proxy; createCandidateWindow(); #ifdef WORKAROUND_BROKEN_RESET_IN_QT4 - // invalidate all the candidate windows stored in cwinHash - QHashIterator i( cwinHash ); + // invalidate all the candidate windows stored in proxyHash + QHashIterator i( proxyHash ); while ( i.hasNext() ) { i.next(); QWidget *widget = i.key(); - delete cwinHash[ widget ]; - cwinHash[ widget ] = 0; + delete proxyHash[ widget ]; + proxyHash[ widget ] = 0; } #endif } diff --git a/qt4/immodule/quiminputcontext.h b/qt4/immodule/quiminputcontext.h index b0258232f..351b98cca 100644 --- a/qt4/immodule/quiminputcontext.h +++ b/qt4/immodule/quiminputcontext.h @@ -35,6 +35,7 @@ #ifndef UIM_QT4_IMMODULE_QUIMINPUTCONTEXT_H #define UIM_QT4_IMMODULE_QUIMINPUTCONTEXT_H +#include #include #ifdef Q_WS_X11 @@ -44,9 +45,11 @@ #include #include +#include "util.h" // for WORKAROUND_BROKEN_RESET_IN_QT4 + class QEvent; -class AbstractCandidateWindow; +class CandidateWindowProxy; class CaretStateIndicator; class QUimHelperManager; class QUimTextUtil; @@ -67,8 +70,6 @@ struct PreeditSegment QString str; }; -#define WORKAROUND_BROKEN_RESET_IN_QT4 - class QUimInputContext : public QInputContext { Q_OBJECT @@ -175,12 +176,12 @@ class QUimInputContext : public QInputContext uim_context m_uc; QList psegs; - AbstractCandidateWindow *cwin; + CandidateWindowProxy *proxy; #ifdef WORKAROUND_BROKEN_RESET_IN_QT4 QHash m_ucHash; QHash > psegsHash; - QHash cwinHash; + QHash proxyHash; QHash visibleHash; QWidget *focusedWidget; diff --git a/qt4/immodule/quiminputcontext_compose.cpp b/qt4/immodule/quiminputcontext_compose.cpp index 999514027..9b3e1120f 100644 --- a/qt4/immodule/quiminputcontext_compose.cpp +++ b/qt4/immodule/quiminputcontext_compose.cpp @@ -46,6 +46,9 @@ #endif #include +#if QT_VERSION >= 0x050000 +# undef Expose +#endif #include #include @@ -54,7 +57,11 @@ #include "uim/uim.h" +#if QT_VERSION < 0x050000 #include "quiminputcontext.h" +#else +#include "quimplatforminputcontext.h" +#endif static const char COMPOSE_FILE[] = "Compose"; static const char COMPOSE_DIR_FILE[] = "X11/locale/compose.dir"; @@ -70,7 +77,11 @@ static inline bool iscomment(char ch) static int parse_line(char *line, char **argv, int argsize); static unsigned int KeySymToUcs4(KeySym keysym); +#if QT_VERSION < 0x050000 Compose::Compose(DefTree *top, QUimInputContext *ic) +#else +Compose::Compose(DefTree *top, QUimPlatformInputContext *ic) +#endif { m_ic = ic; m_composed = 0; @@ -515,6 +526,7 @@ modmask(char *name) return(mask); } +#ifdef Q_WS_X11 int QUimInputContext::TransFileName(char *transname, const char *name, size_t len) { @@ -958,6 +970,7 @@ int QUimInputContext::get_compose_filename(char *filename, size_t len) return 1; } +#endif static int parse_line(char *line, char **argv, int argsize) diff --git a/qt4/immodule/quiminputcontext_compose.h b/qt4/immodule/quiminputcontext_compose.h index 02d442b34..5b2c76b19 100644 --- a/qt4/immodule/quiminputcontext_compose.h +++ b/qt4/immodule/quiminputcontext_compose.h @@ -59,16 +59,30 @@ typedef struct _DefTree { KeySym ks; } DefTree; +#include + +#if QT_VERSION < 0x050000 class QUimInputContext; +#else +class QUimPlatformInputContext; +#endif class Compose { public: +#if QT_VERSION < 0x050000 Compose(DefTree *, QUimInputContext *); +#else + Compose(DefTree *, QUimPlatformInputContext *); +#endif ~Compose(); bool handle_qkey(const QKeyEvent *event); void reset(); private: bool handleKey(KeySym xkeysym, int xstate, bool is_push); +#if QT_VERSION < 0x050000 QUimInputContext *m_ic; +#else + QUimPlatformInputContext *m_ic; +#endif DefTree *m_top; DefTree *m_context; DefTree *m_composed; diff --git a/qt4/immodule/quiminputcontext_with_slave.h b/qt4/immodule/quiminputcontext_with_slave.h index 65ce8ae2a..56216a604 100644 --- a/qt4/immodule/quiminputcontext_with_slave.h +++ b/qt4/immodule/quiminputcontext_with_slave.h @@ -35,13 +35,21 @@ #ifndef UIM_QT4_IMMODULE_QUIMINPUTCONTEXT_WITH_SLAVE_H #define UIM_QT4_IMMODULE_QUIMINPUTCONTEXT_WITH_SLAVE_H -#include "quiminputcontext.h" +#if QT_VERSION < 0x050000 +# include "quiminputcontext.h" +#else +# include "quimplatforminputcontext.h" +#endif // This class is for dealing with Dead/Multi key composing. // Have QSimpleInputContext as slave and forward event to the // slave when isComposing==false. +#if QT_VERSION < 0x050000 class QUimInputContextWithSlave : public QUimInputContext +#else +class QUimInputContextWithSlave : public QUimPlatformInputContext +#endif { Q_OBJECT public: @@ -68,7 +76,11 @@ protected slots: virtual void destroyInputContext(); protected: +#if QT_VERSION < 0x050000 QInputContext *slave; +#else + QPlatformInputContext *slave; +#endif }; #endif /* Not def: UIM_QT4_IMMODULE_QUIMINPUTCONTEXT_WITH_SLAVE_H */ diff --git a/qt4/immodule/quiminputcontextplugin.pro.in b/qt4/immodule/quiminputcontextplugin.pro.in index 3dcab048b..2d8081284 100644 --- a/qt4/immodule/quiminputcontextplugin.pro.in +++ b/qt4/immodule/quiminputcontextplugin.pro.in @@ -3,30 +3,29 @@ include(../common.pro) TEMPLATE = lib CONFIG += plugin +# to include util.h +INCLUDEPATH += @srcdir@/../candwin + LIBS += @X11_LIBS@ -luim-counted-init # Input -HEADERS += @srcdir@/abstractcandidatewindow.h \ - @srcdir@/candidatetablewindow.h \ - @srcdir@/candidatewindow.h \ +HEADERS += @srcdir@/candidatewindowproxy.h \ @srcdir@/caretstateindicator.h \ @srcdir@/plugin.h \ @srcdir@/qhelpermanager.h \ @srcdir@/qtextutil.h \ @srcdir@/quiminfomanager.h \ @srcdir@/quiminputcontext.h \ - @srcdir@/subwindow.h + @srcdir@/../candwin/util.h -SOURCES += @srcdir@/abstractcandidatewindow.cpp \ - @srcdir@/candidatetablewindow.cpp \ - @srcdir@/candidatewindow.cpp \ +SOURCES += @srcdir@/candidatewindowproxy.cpp \ @srcdir@/caretstateindicator.cpp \ @srcdir@/plugin.cpp \ @srcdir@/qhelpermanager.cpp \ @srcdir@/qtextutil.cpp \ @srcdir@/quiminfomanager.cpp \ @srcdir@/quiminputcontext.cpp \ - @srcdir@/subwindow.cpp + @srcdir@/../candwin/util.cpp !win32:!embedded:!mac { HEADERS += @srcdir@/quiminputcontext_compose.h diff --git a/qt4/pref/customwidgets.cpp b/qt4/pref/customwidgets.cpp index c981950e3..11502389f 100644 --- a/qt4/pref/customwidgets.cpp +++ b/qt4/pref/customwidgets.cpp @@ -38,14 +38,25 @@ #include "qtgettext.h" #include -#include -#include -#include -#include -#include -#include -#include -#include +#if QT_VERSION < 0x050000 +# include +# include +# include +# include +# include +# include +# include +# include +#else +# include +# include +# include +# include +# include +# include +# include +# include +#endif inline static QString _FU8( const char string[] ) { diff --git a/qt4/pref/customwidgets.h b/qt4/pref/customwidgets.h index a75c94180..b8a2aec14 100644 --- a/qt4/pref/customwidgets.h +++ b/qt4/pref/customwidgets.h @@ -37,12 +37,20 @@ #include #include -#include -#include -#include #include -#include -#include +#if QT_VERSION < 0x050000 +# include +# include +# include +# include +# include +#else +# include +# include +# include +# include +# include +#endif #include "keyeditformbase.h" #include "olisteditformbase.h" diff --git a/qt4/pref/keyeditformbase.cpp b/qt4/pref/keyeditformbase.cpp index e54c46f23..2fe46d593 100644 --- a/qt4/pref/keyeditformbase.cpp +++ b/qt4/pref/keyeditformbase.cpp @@ -32,13 +32,22 @@ */ #include "keyeditformbase.h" -#include -#include -#include -#include -#include -#include -#include +#if QT_VERSION < 0x050000 +# include +# include +# include +# include +# include +# include +# include +#else +# include +# include +# include +# include +# include +# include +#endif #include "qtgettext.h" diff --git a/qt4/pref/keyeditformbase.h b/qt4/pref/keyeditformbase.h index 3593c1a9b..bdabfb0ba 100644 --- a/qt4/pref/keyeditformbase.h +++ b/qt4/pref/keyeditformbase.h @@ -33,7 +33,12 @@ #ifndef UIM_QT4_PREF_KEYEDITFORMBASE_H #define UIM_QT4_PREF_KEYEDITFORMBASE_H -#include +#include +#if QT_VERSION < 0x050000 +# include +#else +# include +#endif class QPushButton; class QTreeWidget; diff --git a/qt4/pref/olisteditformbase.cpp b/qt4/pref/olisteditformbase.cpp index 9be7e17c7..10f0c3dc4 100644 --- a/qt4/pref/olisteditformbase.cpp +++ b/qt4/pref/olisteditformbase.cpp @@ -32,13 +32,22 @@ */ #include "olisteditformbase.h" -#include -#include -#include -#include -#include -#include -#include +#if QT_VERSION < 0x050000 +# include +# include +# include +# include +# include +# include +# include +#else +# include +# include +# include +# include +# include +# include +#endif #include "qtgettext.h" diff --git a/qt4/pref/olisteditformbase.h b/qt4/pref/olisteditformbase.h index 02ad90b72..814081836 100644 --- a/qt4/pref/olisteditformbase.h +++ b/qt4/pref/olisteditformbase.h @@ -33,7 +33,12 @@ #ifndef UIM_QT4_PREF_OLISTEDITFORMBASE_H #define UIM_QT4_PREF_OLISTEDITFORMBASE_H -#include +#include +#if QT_VERSION < 0x050000 +# include +#else +# include +#endif class QTreeWidget; class QPushButton; diff --git a/qt4/pref/qt4.cpp b/qt4/pref/qt4.cpp index ff392eb57..ff86e870e 100644 --- a/qt4/pref/qt4.cpp +++ b/qt4/pref/qt4.cpp @@ -37,19 +37,35 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#if QT_VERSION < 0x050000 +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#else +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#endif #include "uim/counted-init.h" #include "qtgettext.h" diff --git a/qt4/pref/qt4.h b/qt4/pref/qt4.h index f1e2878ab..83c5606e3 100644 --- a/qt4/pref/qt4.h +++ b/qt4/pref/qt4.h @@ -35,7 +35,11 @@ #include #include -#include +#if QT_VERSION < 0x050000 +# include +#else +# include +#endif #include #include diff --git a/qt4/switcher/qt4.cpp b/qt4/switcher/qt4.cpp index 7b9de349f..878852428 100644 --- a/qt4/switcher/qt4.cpp +++ b/qt4/switcher/qt4.cpp @@ -37,16 +37,27 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#if QT_VERSION < 0x050000 +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#else +# include +# include +# include +# include +# include +# include +# include +# include +#endif #include #include diff --git a/qt4/switcher/qt4.h b/qt4/switcher/qt4.h index 98b4d9ce8..942eed996 100644 --- a/qt4/switcher/qt4.h +++ b/qt4/switcher/qt4.h @@ -36,8 +36,12 @@ #include #include -#include #include +#if QT_VERSION < 0x050000 +# include +#else +# include +#endif class QFocusEvent; class QPushButton; diff --git a/qt4/toolbar/common-quimhelpertoolbar.cpp b/qt4/toolbar/common-quimhelpertoolbar.cpp index 1c266370a..9df64fb55 100644 --- a/qt4/toolbar/common-quimhelpertoolbar.cpp +++ b/qt4/toolbar/common-quimhelpertoolbar.cpp @@ -37,10 +37,17 @@ #include #include -#include -#include -#include -#include +#if QT_VERSION < 0x050000 +# include +# include +# include +# include +#else +# include +# include +# include +# include +#endif #include "uim/uim-scm.h" #include "qtgettext.h" diff --git a/qt4/toolbar/common-quimhelpertoolbar.h b/qt4/toolbar/common-quimhelpertoolbar.h index f70205bec..4bb9d4a88 100644 --- a/qt4/toolbar/common-quimhelpertoolbar.h +++ b/qt4/toolbar/common-quimhelpertoolbar.h @@ -33,8 +33,12 @@ #ifndef UIM_QT4_TOOLBAR_COMMON_QUIMHELPERTOOLBAR_H #define UIM_QT4_TOOLBAR_COMMON_QUIMHELPERTOOLBAR_H -#include #include +#if QT_VERSION < 0x050000 +# include +#else +# include +#endif class UimStateIndicator; diff --git a/qt4/toolbar/common-uimstateindicator.cpp b/qt4/toolbar/common-uimstateindicator.cpp index 6b02f8b49..ce9788acc 100644 --- a/qt4/toolbar/common-uimstateindicator.cpp +++ b/qt4/toolbar/common-uimstateindicator.cpp @@ -40,10 +40,15 @@ #include #include #include -#include -#include #include #include +#if QT_VERSION < 0x050000 +# include +# include +#else +# include +# include +#endif #include #include diff --git a/qt4/toolbar/common-uimstateindicator.h b/qt4/toolbar/common-uimstateindicator.h index d19fd9345..f99929958 100644 --- a/qt4/toolbar/common-uimstateindicator.h +++ b/qt4/toolbar/common-uimstateindicator.h @@ -35,9 +35,15 @@ #include #include -#include -#include -#include +#if QT_VERSION < 0x050000 +# include +# include +# include +#else +# include +# include +# include +#endif #include #include diff --git a/qt4/toolbar/standalone-qt4.cpp b/qt4/toolbar/standalone-qt4.cpp index c628a5d6e..a139019d8 100644 --- a/qt4/toolbar/standalone-qt4.cpp +++ b/qt4/toolbar/standalone-qt4.cpp @@ -37,12 +37,18 @@ #include "common-uimstateindicator.h" #include -#include #include -#include -#include #include #include +#if QT_VERSION < 0x050000 +# include +# include +# include +#else +# include +# include +# include +#endif #include @@ -184,8 +190,13 @@ void UimToolbarDraggingHandler::paintEvent( QPaintEvent *e ) QPainter painter( this ); int w = width(); int h = height(); +#if QT_VERSION < 0x050000 qDrawShadeLine( &painter, w / 2, TOOLBAR_MARGIN_SIZE, w / 2, h - TOOLBAR_MARGIN_SIZE, palette() ); +#else + painter.drawLine( w / 2, TOOLBAR_MARGIN_SIZE, + w / 2, h - TOOLBAR_MARGIN_SIZE ); +#endif } int main( int argc, char *argv[] ) diff --git a/qt4/toolbar/standalone-qt4.h b/qt4/toolbar/standalone-qt4.h index 0e8a576a3..16b1b2a10 100644 --- a/qt4/toolbar/standalone-qt4.h +++ b/qt4/toolbar/standalone-qt4.h @@ -33,8 +33,12 @@ #ifndef UIM_QT4_STANDALONE_QT4_H #define UIM_QT4_STANDALONE_QT4_H -#include #include +#if QT_VERSION < 0x050000 +# include +#else +# include +#endif class QUimHelperToolbar; class UimToolbarDraggingHandler; diff --git a/qt5/Makefile.am b/qt5/Makefile.am new file mode 100644 index 000000000..c5548cbca --- /dev/null +++ b/qt5/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = candwin chardict edittest immodule pref switcher toolbar diff --git a/qt5/candwin/Makefile.am b/qt5/candwin/Makefile.am new file mode 100644 index 000000000..38f223388 --- /dev/null +++ b/qt5/candwin/Makefile.am @@ -0,0 +1,19 @@ +.PHONY: mocclean FORCE + +# Makefile.qmake is only exist when --enable-qt5 +if QT5 +all clean mocclean install uninstall: + $(MAKE) $(AM_MAKEFLAGS) -f Makefile.qmake INSTALL_ROOT=$(DESTDIR) $@ +endif + +# *.pro is required to run Makefile.qmake. So distclean-am is deferred. +distclean: +if QT5 + $(MAKE) $(AM_MAKEFLAGS) -f Makefile.qmake $@ + $(MAKE) $(AM_MAKEFLAGS) distclean-am +endif + -rm -f Makefile + +FORCE: + +EXTRA_DIST = uim-candwin-qt5.pro.in diff --git a/qt5/candwin/uim-candwin-qt5.pro.in b/qt5/candwin/uim-candwin-qt5.pro.in new file mode 100644 index 000000000..0c5d0ea49 --- /dev/null +++ b/qt5/candwin/uim-candwin-qt5.pro.in @@ -0,0 +1,27 @@ +include(../../qt4/common.pro) + +TEMPLATE = app + +# to include qtgettext.h +INCLUDEPATH += @srcdir@/../../qt4 + +LIBS += @LIBINTL@ + +# Input +HEADERS += @srcdir@/../../qt4/candwin/abstractcandidatewindow.h \ + @srcdir@/../../qt4/candwin/candidatetablewindow.h \ + @srcdir@/../../qt4/candwin/candidatewindow.h \ + @srcdir@/../../qt4/candwin/subwindow.h \ + @srcdir@/../../qt4/candwin/util.h \ + @srcdir@/../../qt4/candwin/ximcandidatewindow.h +SOURCES += @srcdir@/../../qt4/candwin/abstractcandidatewindow.cpp \ + @srcdir@/../../qt4/candwin/candidatetablewindow.cpp \ + @srcdir@/../../qt4/candwin/candidatewindow.cpp \ + @srcdir@/../../qt4/candwin/qt4.cpp \ + @srcdir@/../../qt4/candwin/subwindow.cpp \ + @srcdir@/../../qt4/candwin/util.cpp \ + @srcdir@/../../qt4/candwin/ximcandidatewindow.cpp + +TARGET = uim-candwin-qt5 + +target.path += @DESTDIR@@UIM_LIBEXECDIR@ diff --git a/qt5/chardict/Makefile.am b/qt5/chardict/Makefile.am new file mode 100644 index 000000000..a6be56a31 --- /dev/null +++ b/qt5/chardict/Makefile.am @@ -0,0 +1,18 @@ +.PHONY: mocclean FORCE + +# Makefile.qmake is only exist when --enable-qt5 +if QT5 + +all clean mocclean install uninstall: + $(MAKE) $(AM_MAKEFLAGS) -f Makefile.qmake INSTALL_ROOT=$(DESTDIR) $@ +endif + +# *.pro is required to run Makefile.qmake. So distclean-am is deferred. +distclean: +if QT5 + $(MAKE) $(AM_MAKEFLAGS) -f Makefile.qmake $@ + $(MAKE) $(AM_MAKEFLAGS) distclean-am +endif + -rm -f Makefile + +EXTRA_DIST = uim-chardict-qt5.pro.in diff --git a/qt5/chardict/uim-chardict-qt5.pro.in b/qt5/chardict/uim-chardict-qt5.pro.in new file mode 100644 index 000000000..34231287f --- /dev/null +++ b/qt5/chardict/uim-chardict-qt5.pro.in @@ -0,0 +1,19 @@ +include(../../qt4/common.pro) + +# to include qtgettext.h +INCLUDEPATH += @srcdir@/../../qt4 +LIBS += @LIBINTL@ @X11_LIBS@ + +# Input +HEADERS += @srcdir@/../../qt4/chardict/bushuviewwidget.h \ + @srcdir@/../../qt4/chardict/chargridview.h \ + @srcdir@/../../qt4/chardict/qt4.h \ + @srcdir@/../../qt4/chardict/unicodeviewwidget.h +SOURCES += @srcdir@/../../qt4/chardict/bushuviewwidget.cpp \ + @srcdir@/../../qt4/chardict/chargridview.cpp \ + @srcdir@/../../qt4/chardict/qt4.cpp \ + @srcdir@/../../qt4/chardict/unicodeviewwidget.cpp + +TARGET = uim-chardict-qt5 + +target.path += @DESTDIR@@exec_prefix@/bin diff --git a/qt5/edittest/Makefile.am b/qt5/edittest/Makefile.am new file mode 100644 index 000000000..3f892d537 --- /dev/null +++ b/qt5/edittest/Makefile.am @@ -0,0 +1,15 @@ +.PHONY: mocclean FORCE + +# Makefile.qmake is only exist when --enable-qt5-immodule +if QT5_IMMODULE +all clean mocclean install uninstall: + $(MAKE) $(AM_MAKEFLAGS) -f Makefile.qmake $@ +endif + +# *.pro is required to run Makefile.qmake. So distclean-am is deferred. +distclean: +if QT5_IMMODULE + $(MAKE) $(AM_MAKEFLAGS) -f Makefile.qmake $@ + $(MAKE) $(AM_MAKEFLAGS) distclean-am +endif + -rm -f Makefile diff --git a/qt5/immodule/Makefile.am b/qt5/immodule/Makefile.am new file mode 100644 index 000000000..1a6191400 --- /dev/null +++ b/qt5/immodule/Makefile.am @@ -0,0 +1,19 @@ +.PHONY: mocclean FORCE + +# Makefile.qmake is only exist when --enable-qt5-immodule +if QT5_IMMODULE +all clean mocclean install uninstall: + $(MAKE) $(AM_MAKEFLAGS) -f Makefile.qmake INSTALL_ROOT=$(DESTDIR) $@ +endif + +# *.pro is required to run Makefile.qmake. So distclean-am is deferred. +distclean: +if QT5_IMMODULE + $(MAKE) $(AM_MAKEFLAGS) -f Makefile.qmake $@ + $(MAKE) $(AM_MAKEFLAGS) distclean-am +endif + -rm -f Makefile + +FORCE: + +EXTRA_DIST = quiminputcontextplugin.pro.in diff --git a/qt5/immodule/quimplatforminputcontext.cpp b/qt5/immodule/quimplatforminputcontext.cpp new file mode 100644 index 000000000..d445055f7 --- /dev/null +++ b/qt5/immodule/quimplatforminputcontext.cpp @@ -0,0 +1,941 @@ +/* + + Copyright (c) 2012 uim Project http://code.google.com/p/uim/ + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of authors nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +*/ +#include "quimplatforminputcontext.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "candidatewindowproxy.h" +#include "plugin.h" +#include "qhelpermanager.h" +#include "qtextutil.h" +#include "quiminfomanager.h" + +static const char DEFAULT_SEPARATOR_STR[] = "|"; + +QUimPlatformInputContext *focusedInputContext = 0; +bool disableFocusedContext = false; + +QList contextList; + +QUimHelperManager *QUimPlatformInputContext::m_helperManager = 0; + +static int unicodeToUKey(ushort c); + +#define ENABLE_DEBUG + +QUimPlatformInputContext::QUimPlatformInputContext(const char *imname) +: candwinIsActive(false), m_isAnimating(false), m_uc(0) +{ +#ifdef ENABLE_DEBUG + qDebug("QUimPlatformInputContext()"); +#endif + + contextList.append(this); + + // must be initialized before createUimContext() call + if (!m_helperManager) + m_helperManager = new QUimHelperManager; + + if (imname) + m_uc = createUimContext(imname); + + proxy = new CandidateWindowProxy; + proxy->setQUimPlatformInputContext(this); + proxy->hide(); + + m_textUtil = new QUimTextUtil(this); + + // read configuration + updatePosition(); + + connect(qApp->inputMethod(), SIGNAL(inputItemChanged()), + this, SLOT(slotInputItemChanged())); +} + +QUimPlatformInputContext::~QUimPlatformInputContext() +{ +#ifdef ENABLE_DEBUG + qDebug("~QUimPlatformInputContext()"); +#endif + contextList.removeAll(this); + + if (m_uc) + uim_release_context(m_uc); + delete proxy; + + if (focusedInputContext == this) { + focusedInputContext = 0; + disableFocusedContext = true; + } +} + +void QUimPlatformInputContext::slotInputItemChanged() +{ + if (qApp->inputMethod()->inputItem()) + setFocus(); + else + unsetFocus(); +} + +uim_context QUimPlatformInputContext::createUimContext(const char *imname) +{ + uim_context uc = uim_create_context(this, "UTF-8", 0, imname, 0, + QUimPlatformInputContext::commit_cb); + + m_helperManager->checkHelperConnection(); + + /**/ + + uim_set_preedit_cb(uc, QUimPlatformInputContext::clear_cb, + QUimPlatformInputContext::pushback_cb, + QUimPlatformInputContext::update_cb); + + uim_set_candidate_selector_cb(uc, + QUimPlatformInputContext::cand_activate_cb, + QUimPlatformInputContext::cand_select_cb, + QUimPlatformInputContext::cand_shift_page_cb, + QUimPlatformInputContext::cand_deactivate_cb); + + uim_set_prop_list_update_cb(uc, QUimHelperManager::update_prop_list_cb); + uim_set_prop_label_update_cb(uc, QUimHelperManager::update_prop_label_cb); + + uim_set_im_switch_request_cb(uc, + QUimPlatformInputContext::switch_app_global_im_cb, + QUimPlatformInputContext::switch_system_global_im_cb); + + uim_set_text_acquisition_cb(uc, QUimTextUtil::acquire_text_cb, + QUimTextUtil::delete_text_cb); + +#if UIM_QT_USE_DELAY + uim_set_delay_candidate_selector_cb(uc, + QUimPlatformInputContext::cand_activate_with_delay_cb); +#endif /* !UIM_QT_USE_DELAY */ + + uim_prop_list_update(uc); + + return uc; +} + +void QUimPlatformInputContext::setFocus() +{ +#ifdef ENABLE_DEBUG + qDebug("QUimPlatformInputContext: %p->setFocus(), focusWidget()=%p", + this, QApplication::focusWidget()); +#endif + + focusedInputContext = this; + disableFocusedContext = false; + + if (candwinIsActive) + proxy->popup(); + + m_helperManager->checkHelperConnection(); + + uim_helper_client_focus_in(m_uc); + uim_prop_list_update(m_uc); + + uim_focus_in_context(m_uc); +} + +void QUimPlatformInputContext::unsetFocus() +{ +#ifdef ENABLE_DEBUG + qDebug("QUimPlatformInputContext: %p->unsetFocus(), focusWidget()=%p", + this, QApplication::focusWidget()); +#endif + + uim_focus_out_context(m_uc); + + proxy->hide(); + + m_helperManager->checkHelperConnection(); + + uim_helper_client_focus_out(m_uc); +} + +void QUimPlatformInputContext::commit() +{ +#ifdef ENABLE_DEBUG + qDebug("commit()"); +#endif +} + +bool QUimPlatformInputContext::filterEvent(const QEvent *event) +{ +#ifdef ENABLE_DEBUG + qDebug("filterEvent"); +#endif + + int type = event->type(); + + if (type != QEvent::KeyPress && + type != QEvent::KeyRelease) + return false; + + const QKeyEvent *keyevent = static_cast(event); + int qkey = keyevent->key(); + + int modifier = 0; + if (keyevent->modifiers() & Qt::ShiftModifier) + modifier |= UMod_Shift; + if (keyevent->modifiers() & Qt::ControlModifier) + modifier |= UMod_Control; + if (keyevent->modifiers() & Qt::AltModifier) + modifier |= UMod_Alt; +#if defined(Q_WS_X11) + if (keyevent->modifiers() & Qt::MetaModifier) + modifier |= UMod_Meta; +#endif + + int key = 0; + if (isascii(qkey) && isprint(qkey)) { + int ascii = keyevent->text()[0].toAscii(); + if (isalpha(ascii)) { + key = ascii; // uim needs lower/upper encoded key + } else { + if (keyevent->modifiers() & Qt::ControlModifier && + (ascii >= 0x01 && ascii <= 0x1a)) + if (keyevent->modifiers() & Qt::ShiftModifier) + key = ascii + 0x40; + else + key = ascii + 0x60; + else + key = qkey; + } + } else if (qkey == Qt::Key_unknown) { + QString text = keyevent->text(); + if (!text.isNull()) { + QChar s = text.at(0); + key = unicodeToUKey (s.unicode()); + } else { + key = UKey_Other; + } + } else { + if (qkey >= Qt::Key_F1 && qkey <= Qt::Key_F35) { + key = qkey - Qt::Key_F1 + UKey_F1; + } else if (qkey >= Qt::Key_Dead_Grave && qkey <= Qt::Key_Dead_Horn) { + key = qkey - Qt::Key_Dead_Grave + UKey_Dead_Grave; + } else if (qkey >= Qt::Key_Kanji && qkey <= Qt::Key_Eisu_toggle) { + key = qkey - Qt::Key_Kanji + UKey_Kanji; + } else if (qkey >= Qt::Key_Hangul && qkey <= Qt::Key_Hangul_Special) { + key = qkey - Qt::Key_Hangul + UKey_Hangul; + } else { + switch (qkey) { + case Qt::Key_Tab: + key = UKey_Tab; + break; + case Qt::Key_Backspace: + key = UKey_Backspace; + break; + case Qt::Key_Escape: + key = UKey_Escape; + break; + case Qt::Key_Delete: + key = UKey_Delete; + break; + case Qt::Key_Return: + key = UKey_Return; + break; + case Qt::Key_Left: + key = UKey_Left; + break; + case Qt::Key_Up: + key = UKey_Up; + break; + case Qt::Key_Right: + key = UKey_Right; + break; + case Qt::Key_Down: + key = UKey_Down; + break; + case Qt::Key_PageUp: + key = UKey_Prior; + break; + case Qt::Key_PageDown: + key = UKey_Next; + break; + case Qt::Key_Home: + key = UKey_Home; + break; + case Qt::Key_End: + key = UKey_End; + break; + case Qt::Key_Multi_key: + key = UKey_Multi_key; + break; + case Qt::Key_Mode_switch: + key = UKey_Mode_switch; + break; + case Qt::Key_Codeinput: + key = UKey_Codeinput; + break; + case Qt::Key_SingleCandidate: + key = UKey_SingleCandidate; + break; + case Qt::Key_MultipleCandidate: + key = UKey_MultipleCandidate; + break; + case Qt::Key_PreviousCandidate: + key = UKey_PreviousCandidate; + break; + // Qt4 seems to add its own modifier even the event is + // KeyPress, which differs from ordinary model. So remove + // them for uim. + case Qt::Key_Shift: key = UKey_Shift_key; + if (type == QEvent::KeyPress) + modifier &= ~UMod_Shift; + break; + case Qt::Key_Control: key = UKey_Control_key; + if (type == QEvent::KeyPress) + modifier &= ~UMod_Control; + break; + case Qt::Key_Alt: key = UKey_Alt_key; + if (type == QEvent::KeyPress) + modifier &= ~UMod_Alt; + break; + case Qt::Key_Meta: key = UKey_Meta_key; +#ifdef Q_WS_X11 + if (type == QEvent::KeyPress) + modifier &= ~UMod_Meta; +#endif + break; + case Qt::Key_CapsLock: + key = UKey_Caps_Lock; + break; + case Qt::Key_NumLock: + key = UKey_Num_Lock; + break; + case Qt::Key_ScrollLock: + key = UKey_Scroll_Lock; + break; + default: + key = UKey_Other; + } + } + } + + int notFiltered; + if (type == QEvent::KeyPress) { + notFiltered = uim_press_key(m_uc, key, modifier); +#ifdef Q_WS_X11 + if (notFiltered) + return mCompose->handle_qkey(keyevent); +#else + if (notFiltered) + return false; +#endif + } else if (type == QEvent::KeyRelease) { + notFiltered = uim_release_key(m_uc, key, modifier); +#ifdef Q_WS_X11 + if (notFiltered) + return mCompose->handle_qkey(keyevent); +#else + if (notFiltered) + return false; +#endif + } + return true; + +} + +void QUimPlatformInputContext::hideInputPanel() +{ +#ifdef ENABLE_DEBUG + qDebug("hideInputPanel()"); +#endif +} + +Qt::LayoutDirection QUimPlatformInputContext::inputDirection() const +{ +#ifdef ENABLE_DEBUG + qDebug("inputDirection()"); +#endif + return Qt::LayoutDirectionAuto; +} + +void QUimPlatformInputContext::invokeAction(QInputMethod::Action action, + int cursorPosition) +{ +#ifdef ENABLE_DEBUG + qDebug("invokeAction()"); +#endif + Q_UNUSED(action) + Q_UNUSED(cursorPosition) +} + +bool QUimPlatformInputContext::isInputPanelVisible() const +{ +#ifdef ENABLE_DEBUG + qDebug("isInputPanelVisible()"); +#endif + return false; +} + +bool QUimPlatformInputContext::isValid() const +{ +#ifdef ENABLE_DEBUG + qDebug("isValid()"); +#endif + return true; +} + +QRectF QUimPlatformInputContext::keyboardRect() const +{ +#ifdef ENABLE_DEBUG + qDebug("keyboardRect()"); +#endif + return QRectF(); +} + +QLocale QUimPlatformInputContext::locale() const +{ +#ifdef ENABLE_DEBUG + qDebug("locale()"); +#endif + return QLocale(); +} + +void QUimPlatformInputContext::reset() +{ +#ifdef ENABLE_DEBUG + qDebug("reset()"); +#endif + candwinIsActive = false; + + proxy->hide(); + uim_reset_context(m_uc); + clearPreedit(); + updatePreedit(); +} + +void QUimPlatformInputContext::showInputPanel() +{ +#ifdef ENABLE_DEBUG + qDebug("showInputPanel()"); +#endif +} + +void QUimPlatformInputContext::update(Qt::InputMethodQueries) +{ +#ifdef ENABLE_DEBUG + qDebug("update()"); +#endif +} + +void QUimPlatformInputContext::update() +{ + QWidget *w = QApplication::focusWidget(); + +#ifdef ENABLE_DEBUG + qDebug("QUimPlatformInputContext::update() w = %p", w); +#endif + + if (w) { + QRect mf = w->inputMethodQuery(Qt::ImMicroFocus).toRect(); + QPoint p = w->mapToGlobal(mf.topLeft()); + proxy->layoutWindow(p.x(), p.y(), mf.height()); + } +} + +// callbacks for uim +void QUimPlatformInputContext::commit_cb(void *ptr, const char *str) +{ + QString qs = QString::fromUtf8(str); +#ifdef ENABLE_DEBUG + qDebug("commit_cb : str = |%s|", qs.toLocal8Bit().constData()); +#endif + + QUimPlatformInputContext *ic = static_cast(ptr); + ic->commitString(qs); +} + +void QUimPlatformInputContext::clear_cb(void *ptr) +{ +#ifdef ENABLE_DEBUG + qDebug("clear_cb"); +#endif + + QUimPlatformInputContext* ic = static_cast(ptr); + ic->clearPreedit(); +} + +void QUimPlatformInputContext::pushback_cb(void *ptr, int attr, const char *str) +{ + QString qs = QString::fromUtf8(str); +#ifdef ENABLE_DEBUG + qDebug("pushback_cb : str = |%s|", qs.toLocal8Bit().data()); +#endif + + if (!str) + return ; + // Reject invalid empty string. UPreeditAttr_Cursor or + // UPreeditAttr_Separator with empty string is *valid* and + // required to work properly. + if (!strcmp(str, "") + && !(attr & (UPreeditAttr_Cursor | UPreeditAttr_Separator))) + return ; + + QUimPlatformInputContext* ic = static_cast(ptr); + ic->pushbackPreeditString(attr, qs); +} + +void QUimPlatformInputContext::update_cb(void *ptr) +{ +#ifdef ENABLE_DEBUG + qDebug("update_cb"); +#endif + + QUimPlatformInputContext *ic = static_cast(ptr); + ic->updatePreedit(); +} + +void QUimPlatformInputContext::cand_activate_cb(void *ptr, int nr, int displayLimit) +{ +#ifdef ENABLE_DEBUG + qDebug("cand_activate_cb"); +#endif + + QUimPlatformInputContext *ic = static_cast(ptr); + ic->proxy->candidateActivate(nr, displayLimit); +} + +void QUimPlatformInputContext::cand_select_cb(void *ptr, int index) +{ +#ifdef ENABLE_DEBUG + qDebug("cand_select_cb"); +#endif + + QUimPlatformInputContext *ic = static_cast(ptr); + ic->proxy->candidateSelect(index); +} + +void QUimPlatformInputContext::cand_shift_page_cb(void *ptr, int forward) +{ +#ifdef ENABLE_DEBUG + qDebug("cand_shift_page_cb"); +#endif + + QUimPlatformInputContext *ic = static_cast(ptr); + ic->proxy->candidateShiftPage(forward); +} + +void QUimPlatformInputContext::cand_deactivate_cb(void *ptr) +{ +#ifdef ENABLE_DEBUG + qDebug("cand_deactivate_cb"); +#endif + + QUimPlatformInputContext *ic = static_cast(ptr); + ic->proxy->deactivateCandwin(); + ic->candwinIsActive = false; +} + +void QUimPlatformInputContext::switch_app_global_im_cb(void *ptr, + const char *name) +{ + QUimPlatformInputContext *ic = static_cast(ptr); + ic->switch_app_global_im(name); +} + +void QUimPlatformInputContext::switch_system_global_im_cb(void *ptr, + const char *name) +{ + QUimPlatformInputContext *ic = static_cast(ptr); + ic->switch_system_global_im(name); +} + +#if UIM_QT_USE_DELAY +void QUimPlatformInputContext::cand_activate_with_delay_cb(void *ptr, int delay) +{ + QUimPlatformInputContext *ic = static_cast(ptr); + ic->proxy->candidateActivateWithDelay(delay); +} +#endif /* !UIM_QT_USE_DELAY */ + +void QUimPlatformInputContext::commitString(const QString& str) +{ + QInputMethodEvent e; + e.setCommitString(str); + QCoreApplication::sendEvent(qApp->inputMethod()->inputItem(), &e); + + m_isAnimating = false; +} + +void QUimPlatformInputContext::clearPreedit() +{ + preeditSegments.clear(); +} + +void QUimPlatformInputContext::pushbackPreeditString(int attr, + const QString &str) +{ + PreeditSegment ps(attr, str); + preeditSegments.append(ps); +} + +void QUimPlatformInputContext::updatePreedit() +{ + QString newString = getPreeditString(); + + if (!m_isAnimating) { + if (newString.isEmpty()) + return; + + // Start conversion + m_isAnimating = true; + } + + if (!newString.isEmpty()) { + QInputMethodEvent e(newString, getPreeditAttrs()); + QCoreApplication::sendEvent(qApp->inputMethod()->inputItem(), &e); + // Qt4.3.1 does not call back update() here + update(); + } else { + // Complete conversion implicitly since the preedit is empty + commitString(""); + } +} + +QString QUimPlatformInputContext::getPreeditString() +{ + QString pstr; + for (int i = 0, j = preeditSegments.count() ; i < j; i++) { + if (preeditSegments[i].attr & UPreeditAttr_Separator + && preeditSegments[i].str.isEmpty()) { + pstr += DEFAULT_SEPARATOR_STR; + } else { + pstr += preeditSegments[i].str; + } + } + return pstr; +} + +static QColor getUserDefinedColor(const char *symbol) +{ + char *literal = uim_scm_symbol_value_str(symbol); + QColor color(QString::fromAscii(literal)); + free(literal); + return color; +} + +QList QUimPlatformInputContext::getPreeditAttrs() +{ + const int HIDE_CARET = 0; + const int SHOW_CARET = 1; + const int DUMMY = 0; + QList attrs; + + int segPos = 0; + for (int i = 0, j = preeditSegments.count(); i < j; i++) { + int uimAttr = preeditSegments.at(i).attr; + int segStrLen = preeditSegments.at(i).str.length(); + QTextCharFormat segFmt; + + if (uimAttr & UPreeditAttr_Cursor) { + // Transparent cursor is required to set microfocus even + // if the caret is invisible to user. + // + // FIXME: Segment string may be outframed if the cursor is + // located near the right frame. + int visibility = (segStrLen) ? HIDE_CARET : SHOW_CARET; + QInputMethodEvent::Attribute cursor(QInputMethodEvent::Cursor, + segPos, visibility, DUMMY); + attrs << cursor; + } else if (uimAttr & UPreeditAttr_Separator) { + if (!segStrLen) + segStrLen = QString(DEFAULT_SEPARATOR_STR).length(); + if (!(uimAttr & UPreeditAttr_Reverse)) { + QColor color = getUserDefinedColor("separator-foreground"); + if (color.isValid()) + segFmt.setForeground(color); + color = getUserDefinedColor("separator-background"); + if (color.isValid()) + segFmt.setBackground(color); + + } + } + if (segStrLen) { + if (uimAttr & UPreeditAttr_Reverse) { + // foreground symbol + const char *fgSymbol; + // background symbol + const char *bgSymbol; + if (uimAttr & UPreeditAttr_Separator) { + fgSymbol = "reversed-separator-foreground"; + bgSymbol = "reversed-separator-background"; + } else { + fgSymbol = "reversed-preedit-foreground"; + bgSymbol = "reversed-preedit-background"; + } + QColor color = getUserDefinedColor(fgSymbol); + segFmt.setForeground(color.isValid() ? color : Qt::black); + color = getUserDefinedColor(bgSymbol); + segFmt.setBackground(color.isValid() ? color : Qt::white); + } + if (uimAttr & UPreeditAttr_UnderLine) { + segFmt.setFontUnderline(true); + } + QInputMethodEvent::Attribute segAttr(QInputMethodEvent::TextFormat, + segPos, segStrLen, segFmt); + attrs << segAttr; + segPos += segStrLen; + } + } + + return attrs; +} + +void QUimPlatformInputContext::updatePosition() +{ + char * leftp = uim_scm_symbol_value_str("candidate-window-position"); + proxy->setAlwaysLeftPosition(leftp && !strcmp(leftp, "left")); + free(leftp); +} + +void QUimPlatformInputContext::updateIndicator(const QString &str) +{ + Q_UNUSED(str); +} + +static int unicodeToUKey (ushort c) { + int sym; + switch (c) { + case 0x00A5: + sym = UKey_Yen; + break; + case 0x3002: + sym = UKey_Kana_Fullstop; + break; + case 0x300C: + sym = UKey_Kana_OpeningBracket; + break; + case 0x300D: + sym = UKey_Kana_ClosingBracket; + break; + case 0x3001: + sym = UKey_Kana_Comma; + break; + case 0x30FB: + sym = UKey_Kana_Conjunctive; + break; + case 0x30F2: + sym = UKey_Kana_WO; + break; + case 0x30A1: + sym = UKey_Kana_a; + break; + case 0x30A3: + sym = UKey_Kana_i; + break; + case 0x30A5: + sym = UKey_Kana_u; + break; + case 0x30A7: + sym = UKey_Kana_e; + break; + case 0x30A9: + sym = UKey_Kana_o; + break; + case 0x30E3: + sym = UKey_Kana_ya; + break; + case 0x30E5: + sym = UKey_Kana_yu; + break; + case 0x30E7: + sym = UKey_Kana_yo; + break; + case 0x30C3: + sym = UKey_Kana_tsu; + break; + case 0x30FC: + sym = UKey_Kana_ProlongedSound; + break; + case 0x30A2: + sym = UKey_Kana_A; + break; + case 0x30A4: + sym = UKey_Kana_I; + break; + case 0x30A6: + sym = UKey_Kana_U; + break; + case 0x30A8: + sym = UKey_Kana_E; + break; + case 0x30AA: + sym = UKey_Kana_O; + break; + case 0x30AB: + sym = UKey_Kana_KA; + break; + case 0x30AD: + sym = UKey_Kana_KI; + break; + case 0x30AF: + sym = UKey_Kana_KU; + break; + case 0x30B1: + sym = UKey_Kana_KE; + break; + case 0x30B3: + sym = UKey_Kana_KO; + break; + case 0x30B5: + sym = UKey_Kana_SA; + break; + case 0x30B7: + sym = UKey_Kana_SHI; + break; + case 0x30B9: + sym = UKey_Kana_SU; + break; + case 0x30BB: + sym = UKey_Kana_SE; + break; + case 0x30BD: + sym = UKey_Kana_SO; + break; + case 0x30BF: + sym = UKey_Kana_TA; + break; + case 0x30C1: + sym = UKey_Kana_CHI; + break; + case 0x30C4: + sym = UKey_Kana_TSU; + break; + case 0x30C6: + sym = UKey_Kana_TE; + break; + case 0x30C8: + sym = UKey_Kana_TO; + break; + case 0x30CA: + sym = UKey_Kana_NA; + break; + case 0x30CB: + sym = UKey_Kana_NI; + break; + case 0x30CC: + sym = UKey_Kana_NU; + break; + case 0x30CD: + sym = UKey_Kana_NE; + break; + case 0x30CE: + sym = UKey_Kana_NO; + break; + case 0x30CF: + sym = UKey_Kana_HA; + break; + case 0x30D2: + sym = UKey_Kana_HI; + break; + case 0x30D5: + sym = UKey_Kana_FU; + break; + case 0x30D8: + sym = UKey_Kana_HE; + break; + case 0x30DB: + sym = UKey_Kana_HO; + break; + case 0x30DE: + sym = UKey_Kana_MA; + break; + case 0x30DF: + sym = UKey_Kana_MI; + break; + case 0x30E0: + sym = UKey_Kana_MU; + break; + case 0x30E1: + sym = UKey_Kana_ME; + break; + case 0x30E2: + sym = UKey_Kana_MO; + break; + case 0x30E4: + sym = UKey_Kana_YA; + break; + case 0x30E6: + sym = UKey_Kana_YU; + break; + case 0x30E8: + sym = UKey_Kana_YO; + break; + case 0x30E9: + sym = UKey_Kana_RA; + break; + case 0x30EA: + sym = UKey_Kana_RI; + break; + case 0x30EB: + sym = UKey_Kana_RU; + break; + case 0x30EC: + sym = UKey_Kana_RE; + break; + case 0x30ED: + sym = UKey_Kana_RO; + break; + case 0x30EF: + sym = UKey_Kana_WA; + break; + case 0x30F3: + sym = UKey_Kana_N; + break; + case 0x309B: + sym = UKey_Kana_VoicedSound; + break; + case 0x309C: + sym = UKey_Kana_SemivoicedSound; + break; + default: + sym = UKey_Other; + break; + } + + return sym; +} diff --git a/qt5/immodule/quimplatforminputcontext.h b/qt5/immodule/quimplatforminputcontext.h new file mode 100644 index 000000000..acecaa9f7 --- /dev/null +++ b/qt5/immodule/quimplatforminputcontext.h @@ -0,0 +1,146 @@ +/* + + Copyright (c) 2012 uim Project http://code.google.com/p/uim/ + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of authors nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +*/ + +#ifndef UIM_QT5_IMMODULE_QUIMPLATFORMINPUTCONTEXT_H +#define UIM_QT5_IMMODULE_QUIMPLATFORMINPUTCONTEXT_H + +#include +#include + +#include + +class CandidateWindowProxy; +class QUimTextUtil; +class QUimHelperManager; + +struct PreeditSegment +{ + PreeditSegment(int attr, const QString &str) { + this->attr = attr; + this->str = str; + } + int attr; + QString str; +}; + +class QUimPlatformInputContext : public QPlatformInputContext +{ + Q_OBJECT + +public: + explicit QUimPlatformInputContext(const char *imname = 0); + ~QUimPlatformInputContext(); + + + virtual void commit(); + virtual bool filterEvent(const QEvent *event); + virtual void hideInputPanel(); + virtual Qt::LayoutDirection inputDirection() const; + virtual void invokeAction(QInputMethod::Action action, int cursorPosition); + virtual bool isAnimating() const { return m_isAnimating; } + virtual bool isInputPanelVisible() const; + virtual bool isValid() const; + virtual QRectF keyboardRect() const; + virtual QLocale locale() const; + virtual void reset(); + virtual void showInputPanel(); + virtual void update(Qt::InputMethodQueries); + + uim_context uimContext() { return m_uc; } + + void commitString(const QString& str); + + void updatePosition(); + void updateStyle(); + + QUimTextUtil *textUtil() { return m_textUtil; } + + QString getPreeditString(); + int getPreeditCursorPosition(); + + void saveContext(); + void restoreContext(); + + void updateIndicator(const QString &str); + + void setCandwinActive() { candwinIsActive = true; } + +private slots: + void slotInputItemChanged(); + +private: + uim_context createUimContext(const char *imname); + void setFocus(); + void unsetFocus(); + + QList getPreeditAttrs(); + + void update(); + + /// callbacks for uim + static void commit_cb(void *ptr, const char *str); + // preedit + static void clear_cb(void *ptr); + static void pushback_cb(void *ptr, int attr, const char *str); + static void update_cb(void *ptr); + // candidate + static void cand_activate_cb(void *ptr, int nr, int displayLimit); + static void cand_select_cb(void *ptr, int index); + static void cand_shift_page_cb(void* ptr, int index); + static void cand_deactivate_cb(void *ptr); + // imsw + static void switch_app_global_im_cb(void *ptr, const char *str); + static void switch_system_global_im_cb(void *ptr, const char *str); + // delay + static void cand_activate_with_delay_cb(void *ptr, int delay); + /// real functions for callbacks (correspond order) + // preedit + void clearPreedit(); + void pushbackPreeditString(int attr, const QString& str); + void updatePreedit(); + // imsw + void switch_app_global_im(const char *str); + void switch_system_global_im(const char *str); + + QUimTextUtil *m_textUtil; + bool candwinIsActive; + bool m_isAnimating; + + uim_context m_uc; + QList preeditSegments; + CandidateWindowProxy *proxy; + + static QUimHelperManager *m_helperManager; +}; + +#endif /* Not def: UIM_QT5_IMMODULE_QUIMPLATFORMINPUTCONTEXT_H */ diff --git a/qt5/immodule/quimplatforminputcontextplugin.pro.in b/qt5/immodule/quimplatforminputcontextplugin.pro.in new file mode 100644 index 000000000..e5dcfb7dd --- /dev/null +++ b/qt5/immodule/quimplatforminputcontextplugin.pro.in @@ -0,0 +1,40 @@ +include(../../qt4/common.pro) +load(qt_plugin) + +# to include util.h and for quimplatforminputcontext.cpp +INCLUDEPATH += @srcdir@/../../qt4/candwin \ + @srcdir@/../../qt4/immodule + +LIBS += @X11_LIBS@ -luim-counted-init + +QT += platformsupport-private + +# Input +HEADERS += @srcdir@/quimplatforminputcontext.h \ + @srcdir@/../../qt4/immodule/candidatewindowproxy.h \ + @srcdir@/../../qt4/immodule/caretstateindicator.h \ + @srcdir@/../../qt4/immodule/plugin.h \ + @srcdir@/../../qt4/immodule/qhelpermanager.h \ + @srcdir@/../../qt4/immodule/qtextutil.h \ + @srcdir@/../../qt4/immodule/quiminfomanager.h \ + @srcdir@/../../qt4/candwin/util.h + +SOURCES += @srcdir@/quimplatforminputcontext.cpp \ + @srcdir@/../../qt4/immodule/candidatewindowproxy.cpp \ + @srcdir@/../../qt4/immodule/caretstateindicator.cpp \ + @srcdir@/../../qt4/immodule/plugin.cpp \ + @srcdir@/../../qt4/immodule/qhelpermanager.cpp \ + @srcdir@/../../qt4/immodule/qtextutil.cpp \ + @srcdir@/../../qt4/immodule/quiminfomanager.cpp \ + @srcdir@/../../qt4/candwin/util.cpp + +!win32:!embedded:!mac { + HEADERS += @srcdir@/../../qt4/immodule/quiminputcontext_compose.h + SOURCES += @srcdir@/../../qt4/immodule/quiminputcontext_compose.cpp +} + +OTHER_FILES += uim.json + +TARGET = uimplatforminputcontextplugin + +target.path += @DESTDIR@$$[QT_INSTALL_PLUGINS]/platforminputcontexts diff --git a/qt5/immodule/uim.json b/qt5/immodule/uim.json new file mode 100644 index 000000000..3ac99f83c --- /dev/null +++ b/qt5/immodule/uim.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "uim" ] +} diff --git a/qt5/pref/Makefile.am b/qt5/pref/Makefile.am new file mode 100644 index 000000000..baff81d63 --- /dev/null +++ b/qt5/pref/Makefile.am @@ -0,0 +1,19 @@ +.PHONY: mocclean FORCE + +# Makefile.qmake is only exist when --enable-qt5 +if QT5 +all clean mocclean install uninstall: + $(MAKE) $(AM_MAKEFLAGS) -f Makefile.qmake INSTALL_ROOT=$(DESTDIR) $@ +endif + +# *.pro is required to run Makefile.qmake. So distclean-am is deferred. +distclean: +if QT5 + $(MAKE) $(AM_MAKEFLAGS) -f Makefile.qmake $@ + $(MAKE) $(AM_MAKEFLAGS) distclean-am +endif + -rm -f Makefile + +FORCE: + +EXTRA_DIST = uim-pref-qt5.pro.in diff --git a/qt5/pref/uim-pref-qt5.pro.in b/qt5/pref/uim-pref-qt5.pro.in new file mode 100644 index 000000000..49d3700b2 --- /dev/null +++ b/qt5/pref/uim-pref-qt5.pro.in @@ -0,0 +1,21 @@ +include(../../qt4/common.pro) + +TEMPLATE = app + +# to include qtgettext.h +INCLUDEPATH += @srcdir@/../../qt4 +LIBS += -luim-custom -luim-counted-init -luim @LIBINTL@ + +# Input +HEADERS += @srcdir@/../../qt4/pref/customwidgets.h \ + @srcdir@/../../qt4/pref/qt4.h \ + @srcdir@/../../qt4/pref/keyeditformbase.h \ + @srcdir@/../../qt4/pref/olisteditformbase.h +SOURCES += @srcdir@/../../qt4/pref/customwidgets.cpp \ + @srcdir@/../../qt4/pref/qt4.cpp \ + @srcdir@/../../qt4/pref/keyeditformbase.cpp \ + @srcdir@/../../qt4/pref/olisteditformbase.cpp + +TARGET = uim-pref-qt5 + +target.path += @DESTDIR@@exec_prefix@/bin diff --git a/qt5/switcher/Makefile.am b/qt5/switcher/Makefile.am new file mode 100644 index 000000000..4f2e613b6 --- /dev/null +++ b/qt5/switcher/Makefile.am @@ -0,0 +1,19 @@ +.PHONY: mocclean FORCE + +# Makefile.qmake is only exist when --enable-qt5 +if QT5 +all clean mocclean install uninstall: + $(MAKE) $(AM_MAKEFLAGS) -f Makefile.qmake INSTALL_ROOT=$(DESTDIR) $@ +endif + +# *.pro is required to run Makefile.qmake. So distclean-am is deferred. +distclean: +if QT5 + $(MAKE) $(AM_MAKEFLAGS) -f Makefile.qmake $@ + $(MAKE) $(AM_MAKEFLAGS) distclean-am +endif + -rm -f Makefile + +FORCE: + +EXTRA_DIST = uim-im-switcher-qt5.pro.in diff --git a/qt5/switcher/uim-im-switcher-qt5.pro.in b/qt5/switcher/uim-im-switcher-qt5.pro.in new file mode 100644 index 000000000..3083ee524 --- /dev/null +++ b/qt5/switcher/uim-im-switcher-qt5.pro.in @@ -0,0 +1,15 @@ +include(../../qt4/common.pro) + +TEMPLATE = app + +# to include qtgettext.h +INCLUDEPATH += @srcdir@/../../qt4 +LIBS += -lreplace -luim -luim-scm -luim-custom @LIBINTL@ + +# Input +HEADERS += @srcdir@/../../qt4/switcher/qt4.h +SOURCES += @srcdir@/../../qt4/switcher/qt4.cpp + +TARGET = uim-im-switcher-qt5 + +target.path += @DESTDIR@@exec_prefix@/bin diff --git a/qt5/toolbar/Makefile.am b/qt5/toolbar/Makefile.am new file mode 100644 index 000000000..039bd466d --- /dev/null +++ b/qt5/toolbar/Makefile.am @@ -0,0 +1,19 @@ +.PHONY: mocclean FORCE + +# Makefile.qmake is only exist when --enable-qt5 +if QT5 +all clean mocclean install uninstall: + $(MAKE) $(AM_MAKEFLAGS) -f Makefile.qmake INSTALL_ROOT=$(DESTDIR) $@ +endif + +# *.pro is required to run Makefile.qmake. So distclean-am is deferred. +distclean: +if QT5 + $(MAKE) $(AM_MAKEFLAGS) -f Makefile.qmake $@ + $(MAKE) $(AM_MAKEFLAGS) distclean-am +endif + -rm -f Makefile + +FORCE: + +EXTRA_DIST = uim-toolbar-qt5.pro.in diff --git a/qt5/toolbar/uim-toolbar-qt5.pro.in b/qt5/toolbar/uim-toolbar-qt5.pro.in new file mode 100644 index 000000000..2d7b654ea --- /dev/null +++ b/qt5/toolbar/uim-toolbar-qt5.pro.in @@ -0,0 +1,19 @@ +include(../../qt4/common.pro) + +TEMPLATE = app + +# to include qtgettext.h +INCLUDEPATH += @srcdir@/../../qt4 +LIBS += @LIBINTL@ + +# Input +HEADERS += @srcdir@/../../qt4/toolbar/common-quimhelpertoolbar.h \ + @srcdir@/../../qt4/toolbar/common-uimstateindicator.h \ + @srcdir@/../../qt4/toolbar/standalone-qt4.h +SOURCES += @srcdir@/../../qt4/toolbar/common-quimhelpertoolbar.cpp \ + @srcdir@/../../qt4/toolbar/common-uimstateindicator.cpp \ + @srcdir@/../../qt4/toolbar/standalone-qt4.cpp + +TARGET = uim-toolbar-qt5 + +target.path += @DESTDIR@@exec_prefix@/bin