jerous86 / nimqt

Qt bindings for nim
GNU General Public License v2.0
93 stars 6 forks source link

dialog call dialog modal. #19

Closed Martinix75 closed 1 year ago

Martinix75 commented 1 year ago

hello here we are! I ask you so many questions because I am trying to redo the written exercises on the book "Rapid Gui Programming Whit Python Eand Pyqt" with Nimqt so being an unexplored topic the questions are many. But I think it is also very instructive on how it works (or it will work nimqt). Today's question is giving me many problems, it is like recalling a "gui" from a "gui", for now in "Modal" mode. I have already tried some strategy (as per book first mentioned) the first working is:

mother_fx.nim

import std/[strformat, os]
import nimqt
import nimqt/qdialog
import nimqt/[qgridlayout,qboxlayout, qlabel, qlineedit, qpushbutton, qdialogbuttonbox]

nimqt.init
let app1 = newQApplication(commandLineParams())

let label_1 = newQLabel(Q "Text Origin")
let linedit_1 = newQLineEdit()
linedit_1.setReadOnly(true)

inheritQObject(Bottone, QPushButton):
  slot_defer funzione():
    echo "--> enter in fx"
    let label_10 = newQLabel(Q "Foo Text")
    let linedit_10 = newQLineEdit()
    linedit_10.setText(linedit_1.text())
    let pippo: ptr Qdialog = newQdialog()
    pippo.makelayout:
      - newQWidget():
        - newQHBoxLayout():
          - useObject label_10
          - useObject linedit_10

      - newQDialogButtonBox(newQFlags(QDialogButtonBox_StandardButton.Ok)|newQFlags(QDialogButtonBox_StandardButton.Cancel), pippo):
        connect(SIGNAL "rejected()", pippo, SLOT "close()")
        connect(SIGNAL "accepted()", pippo, SLOT "accept()")

    pippo.resize(250, 250)
    pippo.setWindowTitle(Q "Children Fx")
    if pippo.exec() == 1:
      echo "salvato"
      linedit_1.setText(linedit_10.text())

let bottone_1 = newBottone()
bottone_1.setText(Q "Config Fx")

let finestra: ptr QDialog = newQDialog() 
finestra.makelayout:
  - newQWidget():
    - newQHBoxLayout():
      - useObject label_1
      - useObject linedit_1
  - useObject bottone_1:
    connect(SIGNAL "clicked()", bottone_1, SLOT "funzione()")

nimqt.insertSlotImplementations("Bottone")

finestra.resize(250, 250)
finestra.setWindowTitle(Q "Mother")
finestra.show()
discard app1.exec() 

As said it works, but if you have many dialogs to recall the code it soon becomes very heavy and difficult to read. I prefer for each window to make a file (easier to write, read and debug/change). Here, however, the problems are born because everything either partially works or does not work. Here there will be 2 files of course:

mother-Class.nim

import std/[strformat, os]
import nimqt
import nimqt/qdialog
import nimqt/[qgridlayout,qboxlayout, qlabel, qlineedit, qpushbutton, qdialogbuttonbox]
import gui2_6_childrenClass

nimqt.init
let app1 = newQApplication(commandLineParams())

let label_1 = newQLabel(Q "Text Origin")
let linedit_1 = newQLineEdit()
linedit_1.setReadOnly(true)

inheritQObject(Bottone, QPushButton):
  slot_defer classExt():
    echo("--> Win Class")
    let kk = newDialog(linedit_1.text())
    if kk.dialogExt.exec() == 1:
      echo("ok")

let bottone_1 = newBottone()
bottone_1.setText(Q "Config Fx")

let finestra: ptr QDialog = newQDialog() 
finestra.makelayout:
  - newQWidget():
    - newQHBoxLayout():
      - useObject label_1
      - useObject linedit_1
  - useObject bottone_1:
    connect(SIGNAL "clicked()", bottone_1, SLOT "classExt()")

nimqt.insertSlotImplementations("Bottone")

finestra.resize(250, 250)
finestra.setWindowTitle(Q "Mother --> Class")
finestra.show()
discard app1.exec()

The following file ("class") works, but does not report the changes made to the mother window (I think the Accept function () in some way but there is a problem that you will see in the second attempt) must be reimpleted.

gui2_6_childrenClass.nim

import std/[strformat, os]
import nimqt
import nimqt/qdialog
import nimqt/[qgridlayout,qboxlayout, qlabel, qlineedit, qpushbutton, qdialogbuttonbox]

nimqt.init
type
  Children = ref object
    txtlinedit_input: QString
    txtlinedit_outpu: QString

proc newDialog*(a: QString): Children =
  result = Children(txtlinedit_input: a)

proc dialogExt*(self: Children): auto = #: ptr QDialog =
  echo "printa figlia"
  #let app10 = newQApplication(commandLineParams())
  let label_100 = newQLabel(Q "Foo Text")
  let linedit_local = newQLineEdit()
  linedit_local.setText(self.txtlinedit_input)

  let finestra: ptr QDialog = newQDialog()
  finestra.makelayout:
    - newQWidget():
      - newQHBoxLayout():
        - useObject label_100
        - useObject linedit_local

    - newQDialogButtonBox(newQFlags(QDialogButtonBox_StandardButton.Ok)|newQFlags(QDialogButtonBox_StandardButton.Cancel), finestra):
        connect(SIGNAL "rejected()", finestra, SLOT "close()")
        connect(SIGNAL "accepted()", finestra, SLOT "accept()")

  finestra.setWindowTitle( Q "Children Class")
  finestra.resize(350, 250)
  result = finestra
  #finestra.show()
  #discard app10.exec()

#let v = piso(a= Q "axt")
#v.pippocl() 

gui2_6_childrenClass.nim (2 try)

import std/[strformat, os]
import nimqt
import nimqt/qdialog
import nimqt/[qgridlayout,qboxlayout, qlabel, qlineedit, qpushbutton, qdialogbuttonbox]

nimqt.init
type
  Children* = ref object
    txtlinedit_input*: QString
    txtlinedit_outpu*: QString

proc newDialogExt*(a: QString): Children =
  result = Children(txtlinedit_input: a)

proc dialogExt*(self: Children): auto =
  let label_100 = newQLabel(Q "Foo Text")
  let linedit_local = newQLineEdit()
  linedit_local.setText(self.txtlinedit_input)
  #let app10 = newQApplication(commandLineParams())

  inherit_QObject(BottoneCl, QPushButton): # --> error!!!!!!!
    slot_defer foo_accept():
      self.txtlinedit_outpu = linedit_local.text()
      echo("accept?")
      #finestra.accept()
    slot_defer foo_close():
      echo("close?")

  let bottoneOk = newBottoneCl()
  bottoneOk.setText(Q "Ok")

  let bottoneDiscard = newBottoneCl()
  bottoneOk.setText(Q "Discard") 

  let finestra: ptr QDialog = newQDialog()
  finestra.makelayout:
    - newQWidget():
      - newQHBoxLayout():
        - useObject label_100
        - useObject linedit_local
    - newQWidget():
      - newQHBoxLayout():
        - useObject bottoneOk:
            connect(SIGNAL "accepted()", bottoneOk, SLOT "foo_accept()")
        - useObject bottoneDiscard:
            connect(SIGNAL "rejected()", bottoneDiscard, SLOT "foo_close()") 

  nimqt.insertSlotImplementations("BottoneCL")
  finestra.setWindowTitle( Q "Children Class")
  finestra.resize(350, 250)
  result = finestra

  #finestra.show()
  #discard app10.exec()

The error I get in this case is: /home/andrea/Scrivania/qtDialogMode/gui2_6_figliaClass.nim(21, 18) template/generic instantiation of inheritQobject from here /home/andrea/.nimble/pkgs/nimqt-0.1/nimqt.nim(380, 24) Error: 'export' is only allowed at top level andrea@tec-martin:~/Scrivania/qtDialogMode>

And I don't really know what to do or can try, everything I feel there is an obstacle (Keep in mind that I am an electronic and not an IT, so my knowledge is very modest :) ).

Excuse the very long post, but I had to show you all the tests made, and maybe you can understand where I am wrong or if there is an error somewhere. The call of windows (Modal for now) and the transmission of the data modified to the mother, I think it is very important for window systems. Sorry again and thanks from Andrea

Martinix75 commented 1 year ago

Maybe found a half solution (or rather I dreamed of it !!), but I don't think it is the best, because I have to ignected to variable, using a template (a compromise between a "class" and a function in the mother's body). This is because you cannot use or at least I am not able to make it work "Inheritqobject (Namexx, Qwidgetxx)" inside a "porc" or a "template" (if you can do it I would be happy to know how :))) ). In any case, this is the solution (ugly I found today):

moterT.nim

import std/[strformat, os]
import nimqt
import nimqt/qdialog
import nimqt/[qgridlayout,qboxlayout, qlabel, qlineedit, qpushbutton, qdialogbuttonbox]
import childrenTemplate
nimqt.init
let app1 = newQApplication(commandLineParams())

let label_1 = newQLabel(Q "Text Origin")
let linedit_1 = newQLineEdit()
linedit_1.setReadOnly(true)

inheritQObject(Bottone, QPushButton):
  slot_defer classExt():
    echo("--> Win Template")
    let dialx = dialogExt(a=linedit_1.text())
    if dialx.exec() == 1:
      echo("rr")
      linedit_1.settext(linedit_local.text())

let bottone_1 = newBottone()
bottone_1.setText(Q "Config Template")

let finestra: ptr QDialog = newQDialog() 
finestra.makelayout:
  - newQWidget():
    - newQHBoxLayout():
      - useObject label_1
      - useObject linedit_1
  - useObject bottone_1:
    connect(SIGNAL "clicked()", bottone_1, SLOT "classExt()")

nimqt.insertSlotImplementations("Bottone")

finestra.resize(250, 250)
finestra.setWindowTitle(Q "Mother --> Class")
finestra.show()
discard app1.exec()

childrenTemplate.nim

#import std/[strformat, os]
#import nimqt
import nimqt/qdialog
#import nimqt/[qgridlayout,qboxlayout, qlabel, qlineedit, qpushbutton, qdialogbuttonbox]

template dialogExt*(a: QString) : ptr QDialog =

  echo "printa figlia"
  #let app10 = newQApplication(commandLineParams())
  let label_100 = newQLabel(Q "Foo Text")
  let linedit_local {.inject.} = newQLineEdit() #--> use inject not good for Nim!!!!
  linedit_local.setText(a)

  let finestra: ptr QDialog = newQDialog()
  finestra.makelayout:
    - newQWidget():
      - newQHBoxLayout():
        - useObject label_100
        - useObject linedit_local
    - newQDialogButtonBox(newQFlags(QDialogButtonBox_StandardButton.Ok)|newQFlags(QDialogButtonBox_StandardButton.Cancel), finestra):
        connect(SIGNAL "rejected()", finestra, SLOT "close()")
        connect(SIGNAL "accepted()", finestra, SLOT "accept()")

  finestra.setWindowTitle( Q "Children Template")
  finestra.resize(350, 250)
  finestra 

In conclusion I think it would be nice to find a way to use "inheritqobject" inside a porc, template etc. thanks and good day from Andrea

jerous86 commented 1 year ago

I've been playing a little with making it possible to use inheritQObject inside a proc, but it does not seem so easy (e.g. you cannot define a c++ struct inside a function, which would require positioning the emitted code somewhere else, and there will probably other things pop up). I think it would complicate nimqt.nim while the gains are not that much, I think, so for now I will not implement it.

Martinix75 commented 1 year ago

OK thank you! For now at least until an "easy" solution will be found I will use the methods found above. For the future maybe I await news. Thanks for the attention!! Good day from Andrea