billeksah-forms-1.0.0: src/Base/Preferences.hs
{-# Language ExistentialQuantification, TypeFamilies, DeriveDataTypeable #-}
-----------------------------------------------------------------------------
--
-- Module : Base.Preferences
-- Copyright : (c) Juergen Nicklisch-Franken
-- License : GNU-GPL
--
-- Maintainer : <maintainer at leksah.org>
--
-- | Module for handling preferences
--
-----------------------------------------------------------------------------------
module Base.Preferences (
loadPrefs
, savePrefs
, validatePrefs
, getPrefs
, setPrefs
) where
import Base
import Graphics.Pane
import Graphics.Forms.Parameters
import Graphics.Forms.Basics
import Data.List (sortBy, (\\), nub)
import Data.Typeable (Typeable(..), Typeable)
import Control.Monad.IO.Class (MonadIO(..))
import Control.Monad (when)
import Graphics.UI.Gtk.General.Enums (ShadowType(..))
import qualified Text.PrettyPrint as PP (text)
import Graphics.Forms.Composite (pairEditor)
import Graphics.UI.Gtk (cellText)
import System.Glib.Attributes (AttrOp(..))
import Graphics.Forms.Simple (genericEditor, stringEditor)
import Debug.Trace (trace)
-------------------------------------
-- * The functions to handle preferences
--
--
-- | Checks uniqness of categories
--
validatePrefs :: [(String,GenFieldDescription)] -> Maybe String
validatePrefs prefsDescr =
let categories = map (\(cat,_) -> cat) prefsDescr
nCats = nub categories
in if nCats /= categories
then Just $ "duplicate categories:" ++ show (categories \\ nCats)
else Nothing
--
-- | Load preferences from filepath.
-- Pref descriptions needs to be registered before
loadPrefs :: FilePath -> StateM ()
loadPrefs fp = trace "loadPrefs" $ do
allPrefs <- getState PrefsDescrState
let allPrefsS = map (\(s,GenF descr val) -> (s, GenFS (toFieldDescriptionS descr) val)) allPrefs
Left loadedPrefs <- liftIO $ readFields fp (Left allPrefsS)
let newPrefs = map (exchangeValues loadedPrefs) allPrefs
trace ("loadedPrefs " ++ show (length loadedPrefs)) $ setState PrefsDescrState newPrefs
triggerFormsEvent PrefsChanged >> return ()
where
exchangeValues :: [(String, GenFieldDescriptionS)] -> (String, GenFieldDescription)
-> (String, GenFieldDescription)
exchangeValues loadedPrefs (s1, GenF fda a) =
case [gen | (s2, gen) <- loadedPrefs, s1 == s2] of
[GenFS _ newValue] -> let nv = myCast "Preferences>>loadPrefs:" newValue
in (s1, GenF fda nv)
_ -> (s1, GenF fda a)
--
-- | Save preferences to filepath.
-- Pref descriptions needs to be registered before.
savePrefs :: FilePath -> StateM ()
savePrefs fp = do
allPrefs <- getState PrefsDescrState
let allPrefsS = map (\(s,GenF fda a) -> (s, GenFS (toFieldDescriptionS fda) a)) allPrefs
let string = showFields (Left allPrefsS)
liftIO $ writeFile fp string
triggerFormsEvent PrefsChanged >> return ()
--
-- | Gets a preference value from a category
--
getPrefs :: Typeable alpha => String -> StateM alpha
getPrefs category = do
allPrefs <- getState PrefsDescrState
case [ genF | (s,genF) <- allPrefs, s == category] of
[GenF _gd a] ->
let a' = myCast ("Preferences>>getPrefs:" ++
"cast error for category: " ++ category) a
in return a'
_ -> error ("Preferences>>getPrefs: category not found: " ++ category)
--
-- | Sets a preference value for a category
--
setPrefs :: (Eq alpha , Typeable alpha) => String -> alpha -> StateM ()
setPrefs category value = do
allPrefs <- getState PrefsDescrState
setState PrefsDescrState
(map (\ old@(s,GenF des a) ->
if s == category
then if typeOf a == typeOf value
then (s,GenF des (myCast "setPrefs" value))
else error ("Preferences>>setPrefs: type error for category: "
++ category)
else old)
allPrefs)
-- -----------------------------------------------
-- * Convert to a form, which is usable for reading and writing to files
--
toFieldDescriptionS :: FieldDescription alpha -> [FieldDescriptionS alpha]
toFieldDescriptionS = map ppToS . flattenFieldDescription
ppToS :: FieldDescription alpha -> FieldDescriptionS alpha
ppToS (Field para print pars _ _) =
FieldS (let ParaString str = getPara "Name" para in str) print pars
(Just (let ParaString str = getPara "Synopsis" para in str))
ppToS _ = error "DescriptionPP.ppToS Can't transform"
flattenFieldDescription :: FieldDescription alpha -> [FieldDescription alpha]
flattenFieldDescription (VertBox _paras descrs) = concatMap flattenFieldDescription descrs
flattenFieldDescription (HoriBox _paras descrs) = concatMap flattenFieldDescription descrs
flattenFieldDescription (TabbedBox descrsp) = concatMap (flattenFieldDescription . snd) descrsp
flattenFieldDescription fdpp = [fdpp]