adding state in GUIs (qtHaskell)

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

adding state in GUIs (qtHaskell)

Michael Mossey
I'm trying to learn qtHaskell. I realize few people on this list know anything
about qtHaskell, but I have a question that probably relates to all GUIs as
implemented in Haskell. I just need a hint that could help me figure out the
next step, which I might be able to infer from the qtHaskell API.

I don't think is any tutorial-type or step-by-step type documentation for
qtHaskell. I have sent some questions to the author of qtHaskell, David Harley,
but he hasn't responded yet, and anyway I don't want to trouble him every time I
have a question, so I'm trying to infer as much as I can.

The problem relates to state. In Qt, one adds state to a widget by subclassing
it and adding new member variables. For example, I want to create a widget that
responds to keypresses and remembers what keypresses have taken place.

I'm totally stuck on this part, because Haskell doesn't have state. There must
be some kind of Haskell call that adds state to a widget, but it is hard to
figure out from the qtHaskell examples David provides.

Thanks,
Mike
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: adding state in GUIs (qtHaskell)

Michael Mossey
Been poking around. Maybe IORef has something to do with this? I found a
qtHaskell example that seems to make use of IORef in order to accomplish
something similar to what I want.

Michael P Mossey wrote:

> I'm trying to learn qtHaskell. I realize few people on this list know
> anything about qtHaskell, but I have a question that probably relates to
> all GUIs as implemented in Haskell. I just need a hint that could help
> me figure out the next step, which I might be able to infer from the
> qtHaskell API.
>
> I don't think is any tutorial-type or step-by-step type documentation
> for qtHaskell. I have sent some questions to the author of qtHaskell,
> David Harley, but he hasn't responded yet, and anyway I don't want to
> trouble him every time I have a question, so I'm trying to infer as much
> as I can.
>
> The problem relates to state. In Qt, one adds state to a widget by
> subclassing it and adding new member variables. For example, I want to
> create a widget that responds to keypresses and remembers what
> keypresses have taken place.
>
> I'm totally stuck on this part, because Haskell doesn't have state.
> There must be some kind of Haskell call that adds state to a widget, but
> it is hard to figure out from the qtHaskell examples David provides.
>
> Thanks,
> Mike
> _______________________________________________
> Haskell-Cafe mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/haskell-cafe

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: adding state in GUIs (qtHaskell)

Bulat Ziganshin-2
In reply to this post by Michael Mossey
Hello Michael,

Thursday, September 10, 2009, 5:29:33 AM, you wrote:
> I'm totally stuck on this part, because Haskell doesn't have state. There must

Haskell support states (yes, IORef is equal to C++ reference type -
it's a constant pointer to some memory area that you may read/write),
but it doesn't support OOP subclassing. this problem solved in
different ways in each particular haskell GUI


--
Best regards,
 Bulat                            mailto:[hidden email]

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: adding state in GUIs (qtHaskell)

Dan Weston
In reply to this post by Michael Mossey
One simple solution is to leave the state in Qt.

As of Qt 4.2, in C++ you can use

   bool QObject::setProperty(const char * name, const QVariant & value)
   QVariant QObject::property(const char * name) const

to set and get properties on any QObject (hence any QWidget).

Since I believe these are (not yet) wrapped in QtHaskell, you can
instead just create a widget that contains the state and just don't add
it to a layout. Parent it to a widget and it will quietly disappear when
its parent dies. If you want it to persist until you say so, don't
parent it to anything (but then you might as well use Haskell for your
state!)

Dan

Michael P Mossey wrote:

> I'm trying to learn qtHaskell. I realize few people on this list know anything
> about qtHaskell, but I have a question that probably relates to all GUIs as
> implemented in Haskell. I just need a hint that could help me figure out the
> next step, which I might be able to infer from the qtHaskell API.
>
> I don't think is any tutorial-type or step-by-step type documentation for
> qtHaskell. I have sent some questions to the author of qtHaskell, David Harley,
> but he hasn't responded yet, and anyway I don't want to trouble him every time I
> have a question, so I'm trying to infer as much as I can.
>
> The problem relates to state. In Qt, one adds state to a widget by subclassing
> it and adding new member variables. For example, I want to create a widget that
> responds to keypresses and remembers what keypresses have taken place.
>
> I'm totally stuck on this part, because Haskell doesn't have state. There must
> be some kind of Haskell call that adds state to a widget, but it is hard to
> figure out from the qtHaskell examples David provides.
>
> Thanks,
> Mike
> _______________________________________________
> Haskell-Cafe mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>
>

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: adding state in GUIs (qtHaskell)

Duncan Coutts
In reply to this post by Michael Mossey
On Wed, 2009-09-09 at 18:29 -0700, Michael P Mossey wrote:
> I'm trying to learn qtHaskell. I realize few people on this list know anything
> about qtHaskell, but I have a question that probably relates to all GUIs as
> implemented in Haskell. I just need a hint that could help me figure out the
> next step, which I might be able to infer from the qtHaskell API.

Ultimately it's done by some kind of mutable state, either an IORef,
MVar or a thread.

On top of these you can layer nicer stuff like a state monad (with a
'runState' function that saves and restores from an IORef).

A personal favourite of mine is having the GUI event handler post data
over a channel to a thread. That thread reads from the channel and deals
with the events. The state of the GUI app is then held as local
parameters in that thread.

Doing this of course requires that the GUI lib you're using can cope
with normal Haskell (forkIO) threads. This is possible with gtk2hs, I
don't know about the others.

Duncan

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: adding state in GUIs (qtHaskell)

Michael Mossey
In reply to this post by Dan Weston


Dan Weston wrote:

> One simple solution is to leave the state in Qt.
>
> As of Qt 4.2, in C++ you can use
>
>   bool QObject::setProperty(const char * name, const QVariant & value)
>   QVariant QObject::property(const char * name) const
>
> to set and get properties on any QObject (hence any QWidget).
>
> Since I believe these are (not yet) wrapped in QtHaskell, you can
> instead just create a widget that contains the state and just don't add
> it to a layout. Parent it to a widget and it will quietly disappear when
> its parent dies. If you want it to persist until you say so, don't
> parent it to anything (but then you might as well use Haskell for your
> state!)
>
> Dan

Thanks for the reply, Dan. I don't quite follow---you mean create a widget
in C++? I can't find setProperty/property in qtHaskell. I would like to
keep everything in Haskell, though.

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: adding state in GUIs (qtHaskell)

Michael Mossey
In reply to this post by Duncan Coutts


Duncan Coutts wrote:

> On Wed, 2009-09-09 at 18:29 -0700, Michael P Mossey wrote:
>> I'm trying to learn qtHaskell. I realize few people on this list know anything
>> about qtHaskell, but I have a question that probably relates to all GUIs as
>> implemented in Haskell. I just need a hint that could help me figure out the
>> next step, which I might be able to infer from the qtHaskell API.
>
> Ultimately it's done by some kind of mutable state, either an IORef,
> MVar or a thread.
>
> On top of these you can layer nicer stuff like a state monad (with a
> 'runState' function that saves and restores from an IORef).
>
> A personal favourite of mine is having the GUI event handler post data
> over a channel to a thread. That thread reads from the channel and deals
> with the events. The state of the GUI app is then held as local
> parameters in that thread.
>
> Doing this of course requires that the GUI lib you're using can cope
> with normal Haskell (forkIO) threads. This is possible with gtk2hs, I
> don't know about the others.

Hi Duncan, thanks for the reply. Can you point me to some code examples
that do these things?

-Mike
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: adding state in GUIs (qtHaskell)

Roman Cheplyaka-2
In reply to this post by Duncan Coutts
* Duncan Coutts <[hidden email]> [2009-09-10 20:43:54+0000]
> A personal favourite of mine is having the GUI event handler post data
> over a channel to a thread. That thread reads from the channel and deals
> with the events. The state of the GUI app is then held as local
> parameters in that thread.
>
> Doing this of course requires that the GUI lib you're using can cope
> with normal Haskell (forkIO) threads. This is possible with gtk2hs, I
> don't know about the others.

I also would be happy to see some code. Recently I need to write a small
app in gtk2hs which had to deal with state. I used Reader monad with
IORef's in it, but got tired of mixing code in different monads. (It
would help, btw, if gtk2hs functions were not in IO, but in MonadIO).

So I'm curious how 'gtk2hs app done right' looks like.

--
Roman I. Cheplyaka :: http://ro-che.info/
"Don't let school get in the way of your education." - Mark Twain
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: adding state in GUIs (qtHaskell)

Jeremy O'Donoghue
In reply to this post by Michael Mossey
Michael Mossey wrote:
Duncan Coutts wrote:
On Wed, 2009-09-09 at 18:29 -0700, Michael P Mossey wrote:
I'm trying to learn qtHaskell. I realize few people on this list know anything about qtHaskell, but I have a question that probably relates to all GUIs as implemented in Haskell. I just need a hint that could help me figure out the next step, which I might be able to infer from the qtHaskell API.

Ultimately it's done by some kind of mutable state, either an IORef,
MVar or a thread.
In wxHaskell, the 'simplest' way to code this looks something like the following (literate Haskell)

Structure containing 'state' of all of the GUI objects

> data UIState = UIState { uiConnect    :: Button ()
>                        , uiPort       :: TextCtrl ()
>                        , uiUser       :: TextCtrl ()
>                        , uiPasswd     :: TextCtrl ()
>                        , uiSandbox    :: TextCtrl ()
>                        , uiClients    :: ComboBox ()
>                        , uiChanges    :: SingleListBox ()
>                        , uiChangeInfo :: TextCtrl ()
>                        , uiOrigin     :: TextCtrl ()
>                        , uiUpdate     :: TextCtrl ()
>                        , uiFrame      :: Frame ()
>                        }

> uiState = unsafePerformIO $ newMVar (Nothing :: Maybe UIState)

Ensure that we initialize exactly once...

> uiInitState bt pt us pw sb cl ci ch or up f =
>     takeMVar uiState >>= \st ->
>     case st of
>       Nothing -> let st' = UIState bt pt us pw sb cl ci ch or up f in
>                  putMVar uiState (Just st')
>       Just _  -> return ()

Get the mutable state.
Note that in the error case we deliberately do not put the MVar back, as a means
to block all threads waiting on the MVar (as this would indicate a general
programming/threading issue to be identified).

> getMVarState mv txt =
>     takeMVar mv >>= \may_st ->
>     case may_st of
>       Nothing -> error (txt ++ " is not available")
>       Just st -> putMVar mv may_st >>
>                  return st

Fetch the UI state - this will fail fatally if we fetch before state is initialized

> uiGetState = getMVarState uiState "UI state"


I don't have anything as neat to show you as Duncan's suggetion (I'd also be interested to see a cleaner way to do it - this sort of code always grates a little with me, although all of the major Haskell GUI bindings seem to need a similar programming style.

However, at the most basic 'trying it out' level, I suspect that something very like this will work just as well for qtHaskell as it does for wxHaskell.
On top of these you can layer nicer stuff like a state monad (with a
'runState' function that saves and restores from an IORef).

A personal favourite of mine is having the GUI event handler post data
over a channel to a thread. That thread reads from the channel and deals
with the events. The state of the GUI app is then held as local
parameters in that thread.

Doing this of course requires that the GUI lib you're using can cope
with normal Haskell (forkIO) threads. This is possible with gtk2hs, I
don't know about the others.
Regards
Jeremy

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: adding state in GUIs (qtHaskell)

Alp Mestan-2
On Fri, Sep 11, 2009 at 5:55 PM, Jeremy O'Donoghue <[hidden email]> wrote:
<snip>

I don't have anything as neat to show you as Duncan's suggetion (I'd also be interested to see a cleaner way to do it - this sort of code always grates a little with me, although all of the major Haskell GUI bindings seem to need a similar programming style.

However, at the most basic 'trying it out' level, I suspect that something very like this will work just as well for qtHaskell as it does for wxHaskell.

Regards
Jeremy

Very interesting code. However, I'd be very curious to see if qthaskell handles .ui files. And how it does. With C++, thanks to the 'uic' command line tool, we generate a class from the .ui file, and then just have to store an instance of it in our window/dialog/widget/whatever. This class has a setupUI member function, taking a QWidget*/QDialog*/QMainWindow*/whatever, which initializes all the ui components and put them on our widget just like we asked it to do in the designer.

Actually, I'm wondering how the trick could be done (and if it is already done ?) in Haskell without letting too much things generated and compiled at the C++ level with some FFI magic.


--
Alp Mestan
http://blog.mestan.fr/
http://alp.developpez.com/

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe