{-# OPTIONS_GHC -fno-warn-unused-imports #-}

module Graphics.QML.DataModel.Tutorial 
  ( -- * Haskell side
    -- $hsk

    -- * QML side
    -- $qml
  ) where

import Graphics.QML.DataModel
import Graphics.QML.DataModel.TH
import Graphics.QML
import GHC.Generics

{- $hsk
Any data type with a single constructor and marshallable fields can be used in a QML data model. For example:

@
  data Row = Row {foo :: Int, bar :: String, baz :: Double}
    deriving Generic
@

To use the data type in a model, first you need to declare the necessary instances.
All the necessary classes have default implementations using 'Generic'.
To further automate the process, there's a Template Haskell macro that declares them all:

@ 
 dataModelInstances Row
@ 

If you don't want to use TH, you can declare them manually:

@
 instance QtTable      Row
 instance Mock         Row
 instance CountFields  Row
 instance SetupColumns Row
@

Finally, in your 'main' function, register the data model as a QML type, set up the delegate and its callbacks, and provide a way for QML to access it.

@
setTVarCallbacks 
  :: QtTable a 
  => DataModel a 
  -> TVar [a]
  -> IO ()
setTVarCallbacks model tv = do
  setRowCountCallback model $      length <$> readTVarIO mtv
  setDataCallback     model $ \i -> (!!i) <$> readTVarIO mtv

main = do
    registerHaskellModel   

    storage <- newTVarIO [Row 1 "a" 3.0, Row 2 "b" 4.2]
    model <- setupDataModel
    setTVarCallbacks model storage

    toplevel'class <- newClass [ defPropertyConst' "haskellModelDelegate" . return $ delegate model ]
    toplevel'obj <- newObject toplevel'class ()

    runEngineLoop defaultEngineConfig 
      { initialDocument = "path//to//your//main.qml"
      , contextObject = Just $ anyObjRef toplevel'obj
      }
@

-}


{- $qml
Using the model in QML is simple as that:

@
  HaskellModel {
    id: haskellModel;
    delegate: haskellModelDelegate;
  }

  TableView {
    id: hsView;
    model: haskellModel;

    TableViewColumn {
      title: \"A\";
      role: "baz";
    }

    TableViewColumn {
      title: \"B\";
      role: "foo";
    }
  }
@

Record fields become roles, and you can use them in any order any with any names you like.
Views other than TableView can be used too, of course.

-}