jerous86 / nimqt

Qt bindings for nim
GNU General Public License v2.0
101 stars 7 forks source link

How to modularize custom widgets? #26

Closed matkuki closed 1 year ago

matkuki commented 1 year ago

Hi,

I would like to define a custom widget in a separate module and import it into the main module. I tried putting a widget like this:

# gui/tabwidget.nim

import nimqt
import nimqt / [
    qtabwidget,
]

## Custom tab-widget
inheritQObject(CustomTabWidget, QTabWidget):
    override mousePressEvent(e: ptr QMouseEvent):
        echo "Pressed the mouse! ", e.button
        this.parent_mousePressEvent(e)

    override mouseReleaseEvent(e: ptr QMouseEvent):
        echo "Released the mouse! ", e.button
        this.parent_mouseReleaseEvent(e)

then importing it in the main module:

# exco.nim

import nimqt
import gui/tabwidget

nimqt.init

proc main() =
    # some code ...

    var tab_widget = newCustomTabWidget()

    # some more code ...

but that doesn't work. Then I tried exporting the creating proc in gui/tabwidget.nim with:

export newCustomTabWidget

but that makes it only compile in Nim, but the C++ compilation fails with:

cl : Command line warning D9002 : ignoring unknown option '-std=c++17'
cl : Command line warning D9027 : source file 'shell32.lib' ignored
@mexco.nim.cpp
cl : Command line warning D9002 : ignoring unknown option '-std=c++17'
cl : Command line warning D9027 : source file 'shell32.lib' ignored
@mgui@stabwidget.nim.cpp
C:\Users\matic\nimcache\exco_d\@mgui@stabwidget.nim.cpp(108): error C2143: syntax error: missing ';' before 'public'
C:\Users\matic\nimcache\exco_d\@mgui@stabwidget.nim.cpp(108): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
C:\Users\matic\nimcache\exco_d\@mgui@stabwidget.nim.cpp(108): warning C4183: 'W_OBJECT': missing return type; assumed to be a member function returning 'int'
C:\Users\matic\nimcache\exco_d\@mgui@stabwidget.nim.cpp(118): error C2144: syntax error: 'void' should be preceded by ';'
C:\Users\matic\nimcache\exco_d\@mgui@stabwidget.nim.cpp(118): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
C:\Users\matic\nimcache\exco_d\@mexco.nim.cpp(683): error C2065: 'CustomTabWidget': undeclared identifier
C:\Users\matic\nimcache\exco_d\@mexco.nim.cpp(683): error C2065: 'tab_widget': undeclared identifier
C:\Users\matic\nimcache\exco_d\@mexco.nim.cpp(683): error C2061: syntax error: identifier 'CustomTabWidget'
C:\Users\matic\nimcache\exco_d\@mexco.nim.cpp(727): error C2065: 'tab_widget': undeclared identifier
C:\Users\matic\nimcache\exco_d\@mexco.nim.cpp(729): error C2065: 'tab_widget': undeclared identifier
C:\Users\matic\nimcache\exco_d\@mexco.nim.cpp(731): error C2065: 'tab_widget': undeclared identifier
C:\Users\matic\nimcache\exco_d\@mexco.nim.cpp(788): error C2065: 'tab_widget': undeclared identifier
Error: execution of an external compiler program 'vccexe.exe /c --platform:amd64  /nologo ...

What is the nimqt way of doing this modularization?

jerous86 commented 1 year ago

Good question. I did not consider this yet, or naively thought it would be trivial :)

Currently, a c++ struct is emitted by the inheritQObject macro. This struct is not imported into exco.nim, hence it will give some undeclared identifier errors. I will see if I can fix this using some additional macro in the module that's importing the custom widget.

Will keep you updated.

matkuki commented 1 year ago

Excellent πŸ‘ Can't wait for the update, thanks!

jerous86 commented 1 year ago

Still looking into it, but don't have much time these days. And there seem to always be some small thing that doesn't work when I think I find something :)

matkuki commented 1 year ago

No worries, you're doing great πŸ‘πŸ‘πŸ‘ I'm very impressed that you made it this far with nimqt! Sorry to have brought this issue up, but I am porting a big app (ExCo) from PyQt to nimqt, and this is one of the fundamentals that I need for the porting to work.

jerous86 commented 1 year ago

Thank you :) No worries, it's indeed a very good and important issue that you raise.

I think I might have found something: in examples/custom_widget_*.nim you can find examples, but basically I think you should be able to do

import tabwidget
tabwidget.import_CustomTabWidget()

and then you can proceed as if the custom widget was made in the module itself. This works for the simple example in examples, but I will not be surprised if there are many other scenarios where it will not work :)

In any case let me know how it works out for you

matkuki commented 1 year ago

Very good! Trying to test, but the nimble file needs to be updated, I think, it points to the wrong qt/6... directory for the source. I manually changed that and installed, but compiling now throws:

Hint: used config file 'J:\Nim\nimqt\ExCo2\src\exco.nim.cfg' [Conf]
.............................................................................................................................
C:\Users\matic\.nimble\pkgs\nimqt-0.1\nimqt\qtcore\qstring.nim(189, 1) Error: redefinition of 'arg'; previous declaration here: C:\Users\matic\.nimble\pkgs\nimqt-0.1\nimqt\qtcore\qstring.nim(179, 6)
stack trace: (most recent call last)
jerous86 commented 1 year ago

Right, I updated the directory structure a bit, added some more modules and moved from Qt 6.4.2 to 6.4.3, but forgot to update it indeed. Should be now ok?

matkuki commented 1 year ago

nimble install still doesn't install any files (I'm on Windows): image

jerous86 commented 1 year ago

Ah, maybe because I'm using symlinks. That works on unix systems, but didn't try it on windows yet and might be causing troubles ... Can you try again?

matkuki commented 1 year ago

Yes, installation works πŸ‘

But the compilation error is still there:

...
Hint: used config file 'C:\Users\matic\.choosenim\toolchains\nim-1.6.12\config\nim.cfg' [Conf]
Hint: used config file 'C:\Users\matic\.choosenim\toolchains\nim-1.6.12\config\config.nims' [Conf]
Hint: used config file 'J:\Nim\nimqt\ExCo2\src\exco.nim.cfg' [Conf]
.............................................................................................................................
C:\Users\matic\.nimble\pkgs\nimqt-0.1\nimqt\qtcore\qstring.nim(189, 1) Error: redefinition of 'arg'; previous declaration here: C:\Users\matic\.nimble\pkgs\nimqt-0.1\nimqt\qtcore\qstring.nim(179, 6)
stack trace: (most recent call last)
J:\Nim\nimqt\ExCo2\exco_build.nims(91, 9)
C:\Users\matic\.choosenim\toolchains\nim-1.6.12\lib\system\nimscript.nim(273, 7) exec
...
jerous86 commented 1 year ago

I think that's because on windows clong and cint are the same type. I will fix that later, but if you want to move on, you can try to remove line 189 (and possibly other duplicates), and then it should hopefully work :)

matkuki commented 1 year ago

Commenting out lines in qstring.nim 189-191 and 195-197, makes the error go away πŸ‘

I'm using now tabwidget.import_CustomTabWidget() and the Nim compilation succeeds, but the MSVC++ compilation throws:

Hint: used config file 'C:\Users\matic\.choosenim\toolchains\nim-1.6.12\config\nim.cfg' [Conf]
Hint: used config file 'C:\Users\matic\.choosenim\toolchains\nim-1.6.12\config\config.nims' [Conf]
Hint: used config file 'J:\Nim\nimqt\ExCo2\src\exco.nim.cfg' [Conf]
.............................................................................................................................................................................................................................................................................
CC: gui/tabwidget.nim
cl : Command line warning D9002 : ignoring unknown option '-std=c++17'
cl : Command line warning D9027 : source file 'shell32.lib' ignored
@mgui@stabwidget.nim.cpp
C:\Users\matic\nimcache\exco_d\@mgui@stabwidget.nim.cpp(119): error C2143: syntax error: missing ';' before 'public'
C:\Users\matic\nimcache\exco_d\@mgui@stabwidget.nim.cpp(119): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
C:\Users\matic\nimcache\exco_d\@mgui@stabwidget.nim.cpp(119): warning C4183: 'W_OBJECT': missing return type; assumed to be a member function returning 'int'
C:\Users\matic\nimcache\exco_d\@mgui@stabwidget.nim.cpp(135): error C2143: syntax error: missing ';' before '<class-head>'
C:\Users\matic\nimcache\exco_d\@mgui@stabwidget.nim.cpp(135): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
Error: execution of an external compiler program 'vccexe.exe /c --platform:amd64  /nologo /EHsc -DWIN32_LEAN_AND_MEAN -std=c++17 -IC:\Users\matic\.nimble\pkgs\nimqt-0.1 -permissive- -Zc:__cplusplus -std:c++17 -IJ:/Qt6/6.3.1/msvc2019_64/include -IJ:/Qt6/6.3.1/msvc2019_64/include\QtWidgets -IJ:/Qt6/6.3.1/msvc2019_64/include\QtGui -IJ:/Qt6/6.3.1/msvc2019_64/include\QtCore -IJ:/Qt6/6.3.1/msvc2019_64/include\..\mkspecs\win32-msvc /Zc:strictStrings- shell32.lib -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:throwingNew -permissive- -Zc:__cplusplus -Zc:externConstexpr -O2 -MD -utf-8 -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -EHsc -DUNICODE -D_UNICODE -DWIN32 -D_ENABLE_EXTENDED_ALIGNED_STORAGE -DWIN64 -DNDEBUG -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -IC:\Nim\lib -I..\..\Qt6\6.3.1\msvc2019_64\include -I..\..\Qt6\6.3.1\msvc2019_64\include\QtWidgets -I..\..\Qt6\6.3.1\msvc2019_64\include\QtGui -I..\..\Qt6\6.3.1\msvc2019_64\include\QtCore -I/include -I..\..\Qt6\6.3.1\msvc2019_64\mkspecs\win32-msvc /Zc:strictStrings-   /IC:\Users\matic\.choosenim\toolchains\nim-1.6.12\lib /IJ:\Nim\nimqt\ExCo2\src /nologo /FoC:\Users\matic\nimcache\exco_d\@mgui@stabwidget.nim.cpp.obj C:\Users\matic\nimcache\exco_d\@mgui@stabwidget.nim.cpp' failed with exit code: 2

stack trace: (most recent call last)
J:\Nim\nimqt\ExCo2\exco_build.nims(91, 9)
C:\Users\matic\.choosenim\toolchains\nim-1.6.12\lib\system\nimscript.nim(273, 7) exec
C:\Users\matic\.choosenim\toolchains\nim-1.6.12\lib\system\nimscript.nim(273, 7) Error: unhandled exception: FAILED: nim cpp --cc:vcc --outdir:build --mm:orc --passC:" -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:throwingNew -permissive- -Zc:__cplusplus -Zc:externConstexpr -O2 -MD -utf-8 -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -EHsc -DUNICODE -D_UNICODE -DWIN32 -D_ENABLE_EXTENDED_ALIGNED_STORAGE -DWIN64 -DNDEBUG -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -IC:\Nim\lib -I..\..\Qt6\6.3.1\msvc2019_64\include -I..\..\Qt6\6.3.1\msvc2019_64\include\QtWidgets -I..\..\Qt6\6.3.1\msvc2019_64\include\QtGui -I..\..\Qt6\6.3.1\msvc2019_64\include\QtCore -I/include -I..\..\Qt6\6.3.1\msvc2019_64\mkspecs\win32-msvc /Zc:strictStrings-" --passL:"/link /NOLOGO /DYNAMICBASE /NXCOMPAT /OPT:REF /OPT:ICF /INCREMENTAL:NO /SUBSYSTEM:CONSOLE shell32.lib" --clib:J:\Qt6\6.3.1\msvc2019_64\lib\Qt6Widgets --clib:J:\Qt6\6.3.1\msvc2019_64\lib\Qt6Gui --clib:J:\Qt6\6.3.1\msvc2019_64\lib\Qt6Core --clib:J:\Qt6\6.3.1\msvc2019_64\lib\Qt6EntryPoint src/exco.nim [OSError]
matkuki commented 1 year ago

Compiling the custom_widget_main.nim example works πŸ‘πŸ‘πŸ‘ So the problem with my CustomTabWidget has something to do with my code.

matkuki commented 1 year ago

Got it to compile! Had to insert the nimqt.init and nimqt.insertAllSlotImplementations into the gui/tabwidget.nim module.

jerous86 commented 1 year ago

Nice! Good to hear it's working!

Then I think this issue can be closed, for now, until you find something else? :)

matkuki commented 1 year ago

Yes, thanks 😊

If you are able to, please also add some documentation about nimqt.init and nimqt.insertAllSlotImplementations somewhere, thanks.