hluk / FakeVim

Vim emulation in QTextEdit, QPlainTextEdit and similar Qt widgets
GNU Lesser General Public License v2.1
173 stars 30 forks source link

Provide sip bindings to use FakeVim with PyQt #5

Closed cognifloyd closed 10 years ago

cognifloyd commented 11 years ago

More apps could take advantage of FakeVim if it had sip bindings to work with PyQt.

I'm not proficient enough at C or python to do this, but I would love to use FakeVim from within ReText (see https://sourceforge.net/p/retext/tickets/90/ ). I'm not even sure how to compile this since it doesn't have makefiles.

I looked at the sip docs but I'm not really sure which (or all?) header files need to be copied/converted into sip files. And I'm not quite sure which variables are private or protected.

The utils headers are short, but would anyone using FakeVim need access to them? or are they just for internal FakeVim use...? what about actions and handlers? It looks like there are 2 classes in actions and 1 class in handlers... but that doesn't really tell me anything useful (afaict).

Could you please create the sip files that are needed to run this through sip so that it can be used from python (with PyQt)? I'm hoping that once there are sip files, I (or someone) can figure out how to create the configure.py file.

hluk commented 11 years ago

Interesting, I'll take a look at that.

hluk commented 11 years ago

OK, that was illuminating :).

Check out: https://github.com/hluk/FakeVim/tree/master/python

Those are just quick bindings for PyQt. Few Qt signals are missing because I don't know how to expose some structs and enums.

FakeVim code is exact copy of the plugin from Qt Creator -- I want to keep it that way it's easier that way -- also Qt Creator has code reviews and lot of users. The downside is that there are now (could be easy to fix) additional names and headers from Qt Creator.

There is still lot of work to do to make the standalone version of FakeVim easy to use.

cognifloyd commented 11 years ago

Behold the power of open source.

Thanks for working on this hluk! Hopefully this makes it's way into (a branch of?) ReText.

mitya57 commented 11 years ago

Thanks a lot for this!

It currently fails to build here with:

g++ -L../../build/fakevim -shared -o FakeVim.so sipFakeVimcmodule.o sipFakeVimFakeVimInternalFakeVimHandler.o sipFakeVimFakeVimInternal.o sipFakeVimFakeVim.o -L/usr/lib -L/usr/X11R6/lib -lfakevim -lQtCore -lQtGui
/usr/bin/ld: cannot find -lfakevim

Replacing -L../../build/fakevim with -L../../fakevim solves the problem for me.

Also, can you please support PyQt5 (as in ReText we have moved to PyQt5 in the latest release)?

hluk commented 11 years ago

I haven't tested it yet, but I think it should work with PyQt5 if you compile FakeVim with Qt 5 (using qmake for Qt 5 should be enough) and change "PyQt4" to "PyQt5" in configure.py and fakevimconfig.py.in.

The problem with the -L flag exists because there is currently no way to point the configure.py script to correct location where FakeVim was build. This path and Qt version should be configurable or detectable by the script.

Right now I'm just implementing new functionality and fixing the FakeVim library, but feel free to create pull requests or send me patches for the Python stuff.

mitya57 commented 11 years ago

I haven't tested it yet, but I think it should work with PyQt5 if you compile FakeVim with Qt 5 (using qmake for Qt 5 should be enough) and change "PyQt4" to "PyQt5" in configure.py and fakevimconfig.py.in.

It's not so simple because PyQt5 doesn't have pyqtconfig module. The only thing we can get is SIP flags:

from PyQt5.QtCore import PYQT_CONFIGURATION
pyqt_sip_flags = PYQT_CONFIGURATION['sip_flags']

For all other things, we should probably use sysconfig module. I don't have time to look at that now, so I've just commented here :)

cognifloyd commented 10 years ago

I tried copying the qscintilla configure.py to see if that would get us any closer. They support both PyQt4 and PyQt5. See: https://github.com/cognifloyd/FakeVim/tree/python/qscintilla (once this is working, then it'll go in the python folder)

Testing with PyQt4 (I don't have PyQt5 installed):

If you work with this, be sure to change the configure options in build.sh

hluk commented 10 years ago

The new configure.py file has over 1600 lines. This starts to be overly complicated.

For me this seems to work only with python 2.x and Qt 4 (with minor changes). With Qt 5, the script cannot find QtWidgets/QtWidgetsmod.sip. With python 3.4.1, the build library is incorrectly linked (doesn't link with /usr/lib/libpython3.4m.so).

There must be simpler way to do this, otherwise it would be hell to maintain.

cognifloyd commented 10 years ago

Here's a sed script to create what I did from the QScintilla configure files:

# copy QScintilla's Python/configure*.py then:
sed -i \
    -e 's/QSCINTILLA/FAKEVIM/g' \
    -e 's/qscintilla2\?/fakevim/g' \
    -e 's/QScintilla2\?/FakeVim/g' \
    -e 's/QSCI/FAKEVIM/g' \
    -e 's/Qsci/FakeVim/g' \
    -e 's/qsci/fakevim/g' \
    -e 's/_API_MAJOR = 11/_API_MAJOR = 0/g' \
    -e "s/version *= *['\"].\..\..*['\"]/version=None/" \
    -e "s/minimum_sip_version *= *'.\...'/minimum_sip_version = '4.15'/" \
    -e "s/support@riverbankcomputing.com//" \
    -e "s/protected_is_public_is_supported = True/protected_is_public_is_supported = False/" \
    -e 's_sip/.*[345]\.sip_sip/fakevim.sip_' \
    configure*.py
sed -i \
    -e '/# Find .* header files/,/target_configuration.fakevim_version = fakevim_version/d' \
    configure.py
sed -i \
    -e '/# Find .* header files/,/sipconfig.error.*global\.h/d' \
    configure-old.py
cognifloyd commented 10 years ago

All of the docs that I can find on how to build with PyQt5 treat QScintilla like a shining star. That's why I copied what they did. I started to expand your script, and I had all the pyqtconfig.* replaced except for the Makefile creation stuff.

Sadly, I reset/cleaned my git repo without realizing I hadn't committed those changes, so I would have to recreate it if it's needed. It shouldn't be as difficult if I have to do it again, but that doesn't solve the issue of: how do we replace pyqtconfig.QtGuiModuleMakefile?

cognifloyd commented 10 years ago

So, how did you get the test to work with python2 and Qt4? ie What were the minor changes you made?

cognifloyd commented 10 years ago

FYI: I sent a request for help to the PyQt mailing list: http://www.riverbankcomputing.com/pipermail/pyqt/2014-July/034547.html

@kovidgoyal suggested we can do something like what calibre's build system does:

hluk commented 10 years ago

So, how did you get the test to work with python2 and Qt4? ie What were the minor changes you made?

I needed to change the qmake executable. On my system qmake is symlinked to qmake-qt5. But the config script didn't set proper Qt version according to qmake -query. I had to add --qmake /usr/bin/qmake-qt4 parameters to the config script.

Also python executable is Python 3.4.1 for me so I need to use python2.

I'll check out the python scripts for Calibre. Thanks!

hluk commented 10 years ago

I've updated scripts to generate the bindings. Can you check it out? The commit is d16acacdec58f09d98a86e7c1815f640d7003f46.

The default script variables should be sane enough for most people to run it -- right now it works fine on Arch Linux. It should be possible to build the bindings with any combination of Qt 4, Qt 5, Python 2.x and Python 3.x.

cognifloyd commented 10 years ago

Awesome! That works well for me so far. Both compilation and testing works on my system:

This next setup does not compile for me because PyQt4 can only use one version of Qt at a time. I need to install another python interpreter to have a separate version of PyQt4 built against Qt5.

When I had issues with a Segmentation fault, I had to fix these two issues: 1) Qt5 wasn't really working anyway, so everything built with it segfaulted. 2) FakeVim itself, not just the python bindings, needs to be built with the Qt5 qmake. (doh!)

To run these tests I had to set the PyQt include path to gentoo's non-standard location for PyQt4. Thanks to your clean build script, that wasn't a problem :+1: Thanks!

PYQT_INCLUDE_PATH=/usr/share/sip PYTHON=`which python2` python/build.sh

EDIT: I've been updating this comment as I've got more tests to run

hluk commented 10 years ago

Great. I guess there will be some issues when trying to use the scripts on OS X and Windows (or other compilers), but someone else will have to test that.

mitya57 commented 10 years ago

This line:

pythonLibrary = sysconfig.get_config_var('LIBDIR') + "/" + sysconfig.get_config_var('LDLIBRARY'),

does not work on Debian/Ubuntu, where LIBDIR is /usr/lib/, however Python libraries are in /usr/lib/ARCH-OS-TRIPLET (i.e. /usr/lib/x86_64-linux-gnu). I think you should insert sysconfig.get_config_var('MULTIARCH') in the middle, if that is available.

hluk commented 10 years ago

Thanks, fixed: 9a5592b7021ddc4e41c4eed307f411b6453de059 (tested on Ubuntu 14.04)

hluk commented 10 years ago

I'm closing this. Open new issue if there are some problems.

I'm trying to improve FakeVim Python text (test.py) to see if it's possible to fully use FakeVim.

hluk commented 10 years ago

I've improved the test.py script. It opens simple text editor which supports among others:

Patches are welcome.