{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TypeApplications #-}
module Data.GI.Gtk.ModelView.Types (
TypedTreeModel(..),
IsTypedTreeModel,
toTypedTreeModel,
unsafeTreeModelToGeneric,
TypedTreeModelSort(..),
unsafeTreeModelSortToGeneric,
TypedTreeModelFilter(..),
unsafeTreeModelFilterToGeneric,
treePathNewFromIndices',
treePathGetIndices',
withTreePath,
stringToTreePath,
treeSelectionGetSelectedRows',
ColumnAccess(..),
ColumnId(..),
comboQuark,
equalManagedPtr
) where
import Prelude ()
import Prelude.Compat
import GHC.Exts (unsafeCoerce#)
import Data.Char ( isDigit )
import Data.Word (Word32)
import Data.Int (Int32)
import Data.Text (Text)
import qualified Data.Text as T (unpack)
import Data.Coerce (coerce)
import Control.Monad ( liftM )
import Control.Monad.IO.Class (MonadIO(..))
import Control.Exception (catch)
import Foreign.Storable (Storable(..))
import Foreign.Ptr (Ptr, castPtr, plusPtr, minusPtr, nullPtr)
import Foreign.C.Types (CInt(..))
import Foreign.Marshal.Alloc (alloca)
import Foreign.Marshal.Utils (toBool)
import System.IO.Unsafe (unsafePerformIO)
import Foreign.Marshal.Utils (with)
import Data.GI.Base.BasicTypes
(ManagedPtr(..), ManagedPtrNewtype, UnexpectedNullPointerReturn,
GObject(..))
import Data.GI.Base.ManagedPtr (withManagedPtr)
import Data.GI.Base.Overloading (HasParentTypes, ParentTypes)
import Data.GI.Base.GValue (GValue)
import GI.GObject.Objects.Object (Object(..))
import GI.Gtk.Interfaces.TreeModel (TreeModel, IsTreeModel(..))
import GI.Gtk.Objects.TreeModelSort (TreeModelSort, IsTreeModelSort(..))
import GI.Gtk.Objects.TreeSelection (IsTreeSelection, treeSelectionCountSelectedRows, treeSelectionGetSelectedRows)
import GI.Gtk.Objects.TreeModelFilter (TreeModelFilter)
import GI.Gtk.Interfaces.TreeSortable (TreeSortable, IsTreeSortable(..))
import GI.GLib.Functions (quarkFromString)
import GI.GdkPixbuf.Objects.Pixbuf (Pixbuf(..))
import GI.Gtk.Structs.TreeIter
(TreeIter(..), treeIterCopy)
import GI.Gtk.Structs.TreePath (TreePath(..), treePathGetIndices, treePathAppendIndex, treePathNew, treePathGetDepth)
import Data.GI.Base.Constructible (Constructible(..))
import Data.GI.Base.Attributes (AttrOp(..))
import Unsafe.Coerce (unsafeCoerce)
import Data.GI.Base (set, get)
import Data.IORef (newIORef)
equalManagedPtr :: ManagedPtrNewtype a => a -> a -> Bool
equalManagedPtr a b =
managedForeignPtr (coerce a :: ManagedPtr ()) == managedForeignPtr (coerce b :: ManagedPtr ())
newtype TypedTreeModel row = TypedTreeModel (ManagedPtr (TypedTreeModel row))
class IsTypedTreeModel model where
dummy :: model a -> a
dummy _ = error "not used"
toTypedTreeModel :: IsTypedTreeModel model => model row -> TypedTreeModel row
toTypedTreeModel = unsafeCoerce#
unsafeTreeModelToGeneric :: TreeModel -> model row
unsafeTreeModelToGeneric = unsafeCoerce#
instance IsTypedTreeModel TypedTreeModel
newtype TypedTreeModelSort row = TypedTreeModelSort (ManagedPtr (TypedTreeModelSort row))
instance HasParentTypes (TypedTreeModelSort row)
type instance ParentTypes (TypedTreeModelSort row) = '[TreeSortable, TreeModel, TreeModelSort]
instance GObject (TypedTreeModelSort row) where
#if !MIN_VERSION_haskell_gi_base(0,20,1)
gobjectIsInitiallyUnowned _ = False
#endif
gobjectType = gobjectType @TreeModelSort
unsafeTreeModelSortToGeneric :: TreeModelSort -> TypedTreeModelSort row
unsafeTreeModelSortToGeneric = unsafeCoerce#
instance IsTypedTreeModel TypedTreeModelSort
newtype TypedTreeModelFilter row = TypedTreeModelFilter (ManagedPtr (TypedTreeModelFilter row))
unsafeTreeModelFilterToGeneric :: TreeModelFilter -> TypedTreeModelFilter row
unsafeTreeModelFilterToGeneric = unsafeCoerce#
instance IsTypedTreeModel TypedTreeModelFilter
treePathNewFromIndices' :: MonadIO m => [Int32] -> m TreePath
treePathNewFromIndices' [] = treePathNew
treePathNewFromIndices' x = do
path <- treePathNew
mapM_ (treePathAppendIndex path) x
return path
treePathGetIndices' :: MonadIO m => TreePath -> m [Int32]
treePathGetIndices' path = treePathGetDepth path >>= \case
0 -> return []
_ -> do
indices <- treePathGetIndices path
case indices of
Just ixs -> return ixs
Nothing -> return []
withTreePath :: MonadIO m => [Int32] -> (TreePath -> m a) -> m a
withTreePath tp act = treePathNewFromIndices' tp >>= act
treeSelectionGetSelectedRows' :: (MonadIO m, IsTreeSelection sel) => sel -> m [TreePath]
treeSelectionGetSelectedRows' sel = treeSelectionCountSelectedRows sel >>= \case
0 -> return []
_ -> liftIO $ (fst <$> treeSelectionGetSelectedRows sel) `catch` (\(_::UnexpectedNullPointerReturn) -> return [])
stringToTreePath :: Text -> [Int32]
stringToTreePath = stringToTreePath' . T.unpack
where
stringToTreePath' "" = []
stringToTreePath' path = getNum 0 (dropWhile (not . isDigit) path)
getNum acc ('0':xs) = getNum (10*acc) xs
getNum acc ('1':xs) = getNum (10*acc+1) xs
getNum acc ('2':xs) = getNum (10*acc+2) xs
getNum acc ('3':xs) = getNum (10*acc+3) xs
getNum acc ('4':xs) = getNum (10*acc+4) xs
getNum acc ('5':xs) = getNum (10*acc+5) xs
getNum acc ('6':xs) = getNum (10*acc+6) xs
getNum acc ('7':xs) = getNum (10*acc+7) xs
getNum acc ('8':xs) = getNum (10*acc+8) xs
getNum acc ('9':xs) = getNum (10*acc+9) xs
getNum acc xs = acc:stringToTreePath' (dropWhile (not . isDigit) xs)
data ColumnAccess row where
CAInvalid :: ColumnAccess row
CAInt :: (row -> Int32) -> ColumnAccess row
CABool :: (row -> Bool) -> ColumnAccess row
CAString :: (row -> Text) -> ColumnAccess row
CAPixbuf :: (row -> Pixbuf) -> ColumnAccess row
data ColumnId row ty
= ColumnId (GValue -> IO ty) ((row -> ty) -> ColumnAccess row) Int32
{-# NOINLINE comboQuark #-}
comboQuark :: Word32
comboQuark =
unsafePerformIO $ quarkFromString (Just "comboBoxHaskellStringModelQuark")