2015-12-24 17:25:05 +00:00
|
|
|
{--
|
|
|
|
HSFM, a filemanager written in Haskell.
|
2016-03-30 22:28:23 +00:00
|
|
|
Copyright (C) 2016 Julian Ospald
|
2015-12-24 17:25:05 +00:00
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public License
|
|
|
|
version 2 as published by the Free Software Foundation.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
--}
|
|
|
|
|
2016-04-10 23:59:18 +00:00
|
|
|
{-# LANGUAGE OverloadedStrings #-}
|
2015-12-17 03:42:22 +00:00
|
|
|
{-# OPTIONS_HADDOCK ignore-exports #-}
|
|
|
|
|
2016-03-30 18:16:34 +00:00
|
|
|
module HSFM.GUI.Gtk.Callbacks where
|
2015-12-19 15:13:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
import Control.Concurrent.STM
|
|
|
|
(
|
2015-12-30 16:53:16 +00:00
|
|
|
readTVarIO
|
2015-12-19 15:13:48 +00:00
|
|
|
)
|
2015-12-27 17:17:33 +00:00
|
|
|
import Control.Exception
|
|
|
|
(
|
2016-05-09 09:34:02 +00:00
|
|
|
throwIO
|
2015-12-27 17:17:33 +00:00
|
|
|
)
|
2015-12-22 13:15:48 +00:00
|
|
|
import Control.Monad
|
|
|
|
(
|
2016-04-24 16:38:25 +00:00
|
|
|
forM_
|
2016-06-01 20:02:18 +00:00
|
|
|
, forM
|
|
|
|
, join
|
2016-04-24 16:38:25 +00:00
|
|
|
, void
|
|
|
|
, when
|
2015-12-22 13:15:48 +00:00
|
|
|
)
|
2015-12-19 15:13:48 +00:00
|
|
|
import Control.Monad.IO.Class
|
|
|
|
(
|
|
|
|
liftIO
|
|
|
|
)
|
2016-05-08 22:45:47 +00:00
|
|
|
import Data.ByteString
|
|
|
|
(
|
|
|
|
ByteString
|
|
|
|
)
|
2016-05-29 11:26:21 +00:00
|
|
|
import Data.ByteString.UTF8
|
|
|
|
(
|
|
|
|
fromString
|
|
|
|
, toString
|
|
|
|
)
|
2015-12-26 02:04:28 +00:00
|
|
|
import Data.Foldable
|
|
|
|
(
|
|
|
|
for_
|
|
|
|
)
|
2015-12-19 15:13:48 +00:00
|
|
|
import Graphics.UI.Gtk
|
2016-03-30 00:50:32 +00:00
|
|
|
import qualified HPath as P
|
2016-03-31 13:49:35 +00:00
|
|
|
import HPath
|
|
|
|
(
|
|
|
|
Abs
|
|
|
|
, Path
|
|
|
|
)
|
2016-05-09 14:37:02 +00:00
|
|
|
import HPath.IO
|
|
|
|
import HPath.IO.Errors
|
|
|
|
import HPath.IO.Utils
|
2016-03-30 18:16:34 +00:00
|
|
|
import HSFM.FileSystem.FileType
|
2016-05-08 18:14:30 +00:00
|
|
|
import HSFM.FileSystem.UtilTypes
|
|
|
|
import HSFM.GUI.Gtk.Callbacks.Utils
|
2016-03-30 18:16:34 +00:00
|
|
|
import HSFM.GUI.Gtk.Data
|
|
|
|
import HSFM.GUI.Gtk.Dialogs
|
|
|
|
import HSFM.GUI.Gtk.MyView
|
|
|
|
import HSFM.GUI.Gtk.Utils
|
|
|
|
import HSFM.Utils.IO
|
2016-04-15 12:23:41 +00:00
|
|
|
import Prelude hiding(readFile)
|
2015-12-19 15:13:48 +00:00
|
|
|
import System.Glib.UTFString
|
|
|
|
(
|
|
|
|
glibToString
|
|
|
|
)
|
2016-04-16 23:01:04 +00:00
|
|
|
import System.Posix.Env.ByteString
|
|
|
|
(
|
|
|
|
getEnv
|
|
|
|
)
|
2016-04-24 18:00:34 +00:00
|
|
|
import qualified System.Posix.Process.ByteString as SPP
|
|
|
|
import System.Posix.Types
|
|
|
|
(
|
|
|
|
ProcessID
|
|
|
|
)
|
|
|
|
|
2015-12-19 15:13:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-----------------
|
|
|
|
--[ Callbacks ]--
|
|
|
|
-----------------
|
|
|
|
|
|
|
|
|
2016-04-19 23:25:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
---- MAIN CALLBACK ENTRYPOINT ----
|
|
|
|
|
|
|
|
|
2016-04-24 16:38:25 +00:00
|
|
|
-- |Set callbacks for the whole gui, on hotkeys, events and stuff.
|
|
|
|
setGUICallbacks :: MyGUI -> IO ()
|
|
|
|
setGUICallbacks mygui = do
|
|
|
|
|
|
|
|
_ <- clearStatusBar mygui `on` buttonActivated $ do
|
|
|
|
popStatusbar mygui
|
|
|
|
writeTVarIO (operationBuffer mygui) None
|
|
|
|
|
|
|
|
-- menubar-file
|
|
|
|
_ <- (menubarFileQuit . menubar) mygui `on` menuItemActivated $
|
|
|
|
mainQuit
|
|
|
|
|
|
|
|
-- menubar-help
|
|
|
|
_ <- (menubarHelpAbout . menubar) mygui `on` menuItemActivated $
|
|
|
|
liftIO showAboutDialog
|
|
|
|
return ()
|
|
|
|
|
|
|
|
-- key events
|
|
|
|
_ <- rootWin mygui `on` keyPressEvent $ tryEvent $ do
|
|
|
|
[Control] <- eventModifier
|
|
|
|
"q" <- fmap glibToString eventKeyName
|
|
|
|
liftIO mainQuit
|
|
|
|
|
|
|
|
return ()
|
|
|
|
|
|
|
|
|
|
|
|
-- |Set callbacks specific to a given view, on hotkeys, events and stuff.
|
|
|
|
setViewCallbacks :: MyGUI -> MyView -> IO ()
|
|
|
|
setViewCallbacks mygui myview = do
|
2015-12-30 16:53:16 +00:00
|
|
|
view' <- readTVarIO $ view myview
|
|
|
|
case view' of
|
2016-04-09 14:26:12 +00:00
|
|
|
fmv@(FMTreeView treeView) -> do
|
2015-12-30 17:01:36 +00:00
|
|
|
_ <- treeView `on` rowActivated
|
|
|
|
$ (\_ _ -> withItems mygui myview open)
|
2016-04-17 22:51:45 +00:00
|
|
|
|
|
|
|
-- drag events
|
|
|
|
_ <- treeView `on` dragBegin $
|
|
|
|
\_ -> withItems mygui myview moveInit
|
|
|
|
_ <- treeView `on` dragDrop $
|
|
|
|
\dc p ts -> do
|
|
|
|
p' <- treeViewConvertWidgetToTreeCoords treeView p
|
|
|
|
mpath <- treeViewGetPathAtPos treeView p'
|
|
|
|
case mpath of
|
|
|
|
Nothing -> do
|
|
|
|
dragFinish dc False False ts
|
|
|
|
return False
|
|
|
|
Just _ -> do
|
2016-04-19 19:05:29 +00:00
|
|
|
atom <- atomNew ("HSFM" :: String)
|
2016-04-17 22:51:45 +00:00
|
|
|
dragGetData treeView dc atom ts
|
|
|
|
return True
|
|
|
|
_ <- treeView `on` dragDataReceived $
|
|
|
|
\dc p _ ts ->
|
|
|
|
liftIO $ do
|
|
|
|
signalStopEmission treeView "drag_data_received"
|
|
|
|
p' <- treeViewConvertWidgetToTreeCoords treeView p
|
|
|
|
mpath <- treeViewGetPathAtPos treeView p'
|
|
|
|
case mpath of
|
|
|
|
Nothing -> dragFinish dc False False ts
|
|
|
|
Just (tp, _, _) -> do
|
|
|
|
mitem <- rawPathToItem myview tp
|
|
|
|
forM_ mitem $ \item ->
|
|
|
|
operationFinal mygui myview (Just item)
|
|
|
|
dragFinish dc True False ts
|
|
|
|
|
2016-04-09 14:26:12 +00:00
|
|
|
commonGuiEvents fmv
|
2015-12-30 17:01:36 +00:00
|
|
|
return ()
|
2016-04-09 14:26:12 +00:00
|
|
|
fmv@(FMIconView iconView) -> do
|
2015-12-30 17:01:36 +00:00
|
|
|
_ <- iconView `on` itemActivated
|
|
|
|
$ (\_ -> withItems mygui myview open)
|
2016-04-09 14:26:12 +00:00
|
|
|
commonGuiEvents fmv
|
2015-12-30 17:01:36 +00:00
|
|
|
return ()
|
2015-12-30 16:53:16 +00:00
|
|
|
where
|
2016-04-09 14:26:12 +00:00
|
|
|
commonGuiEvents fmv = do
|
|
|
|
let view = fmViewToContainer fmv
|
|
|
|
|
2015-12-30 16:53:16 +00:00
|
|
|
-- GUI events
|
2016-04-24 16:38:25 +00:00
|
|
|
_ <- urlBar myview `on` entryActivated $ urlGoTo mygui myview
|
|
|
|
_ <- upViewB myview `on` buttonActivated $
|
2016-04-16 23:01:04 +00:00
|
|
|
upDir mygui myview
|
2016-04-24 16:38:25 +00:00
|
|
|
_ <- homeViewB myview `on` buttonActivated $
|
2016-04-16 23:01:04 +00:00
|
|
|
goHome mygui myview
|
2016-04-24 16:38:25 +00:00
|
|
|
_ <- refreshViewB myview `on` buttonActivated $ do
|
2015-12-30 16:53:16 +00:00
|
|
|
cdir <- liftIO $ getCurrentDir myview
|
|
|
|
refreshView' mygui myview cdir
|
|
|
|
|
|
|
|
-- key events
|
2016-04-24 16:38:25 +00:00
|
|
|
_ <- viewBox myview `on` keyPressEvent $ tryEvent $ do
|
2015-12-30 16:53:16 +00:00
|
|
|
[Control] <- eventModifier
|
|
|
|
"h" <- fmap glibToString eventKeyName
|
|
|
|
cdir <- liftIO $ getCurrentDir myview
|
|
|
|
liftIO $ modifyTVarIO (settings mygui)
|
|
|
|
(\x -> x { showHidden = not . showHidden $ x})
|
|
|
|
>> refreshView' mygui myview cdir
|
2016-04-24 16:38:25 +00:00
|
|
|
_ <- viewBox myview `on` keyPressEvent $ tryEvent $ do
|
2015-12-30 16:53:16 +00:00
|
|
|
[Alt] <- eventModifier
|
|
|
|
"Up" <- fmap glibToString eventKeyName
|
|
|
|
liftIO $ upDir mygui myview
|
2016-04-24 16:38:25 +00:00
|
|
|
_ <- viewBox myview `on` keyPressEvent $ tryEvent $ do
|
2016-04-19 22:38:22 +00:00
|
|
|
[Alt] <- eventModifier
|
|
|
|
"Left" <- fmap glibToString eventKeyName
|
|
|
|
liftIO $ goHistoryPrev mygui myview
|
2016-04-24 16:38:25 +00:00
|
|
|
_ <- viewBox myview `on` keyPressEvent $ tryEvent $ do
|
2016-04-19 22:38:22 +00:00
|
|
|
[Alt] <- eventModifier
|
|
|
|
"Right" <- fmap glibToString eventKeyName
|
|
|
|
liftIO $ goHistoryNext mygui myview
|
2015-12-30 17:01:36 +00:00
|
|
|
_ <- view `on` keyPressEvent $ tryEvent $ do
|
2015-12-30 16:53:16 +00:00
|
|
|
"Delete" <- fmap glibToString eventKeyName
|
|
|
|
liftIO $ withItems mygui myview del
|
2015-12-30 17:01:36 +00:00
|
|
|
_ <- view `on` keyPressEvent $ tryEvent $ do
|
2015-12-30 16:53:16 +00:00
|
|
|
[] <- eventModifier
|
|
|
|
"Return" <- fmap glibToString eventKeyName
|
|
|
|
liftIO $ withItems mygui myview open
|
2015-12-30 17:01:36 +00:00
|
|
|
_ <- view `on` keyPressEvent $ tryEvent $ do
|
2015-12-30 16:53:16 +00:00
|
|
|
[Control] <- eventModifier
|
|
|
|
"c" <- fmap glibToString eventKeyName
|
|
|
|
liftIO $ withItems mygui myview copyInit
|
2015-12-30 17:01:36 +00:00
|
|
|
_ <- view `on` keyPressEvent $ tryEvent $ do
|
2015-12-30 16:53:16 +00:00
|
|
|
[Control] <- eventModifier
|
|
|
|
"x" <- fmap glibToString eventKeyName
|
|
|
|
liftIO $ withItems mygui myview moveInit
|
2016-04-24 16:38:25 +00:00
|
|
|
_ <- viewBox myview `on` keyPressEvent $ tryEvent $ do
|
2015-12-30 16:53:16 +00:00
|
|
|
[Control] <- eventModifier
|
|
|
|
"v" <- fmap glibToString eventKeyName
|
2016-04-17 22:51:45 +00:00
|
|
|
liftIO $ operationFinal mygui myview Nothing
|
2016-04-24 16:38:25 +00:00
|
|
|
_ <- viewBox myview `on` keyPressEvent $ tryEvent $ do
|
|
|
|
[Control] <- eventModifier
|
|
|
|
"t" <- fmap glibToString eventKeyName
|
|
|
|
liftIO $ void $ do
|
|
|
|
cwd <- getCurrentDir myview
|
2016-06-01 20:02:18 +00:00
|
|
|
newTabHere mygui cwd
|
2016-04-24 16:38:25 +00:00
|
|
|
_ <- viewBox myview `on` keyPressEvent $ tryEvent $ do
|
|
|
|
[Control] <- eventModifier
|
|
|
|
"w" <- fmap glibToString eventKeyName
|
|
|
|
liftIO $ void $ closeTab mygui myview
|
2016-04-24 18:00:34 +00:00
|
|
|
_ <- viewBox myview `on` keyPressEvent $ tryEvent $ do
|
|
|
|
"F4" <- fmap glibToString eventKeyName
|
|
|
|
liftIO $ void $ openTerminalHere myview
|
2015-12-30 16:53:16 +00:00
|
|
|
|
2016-06-01 20:02:18 +00:00
|
|
|
-- mouse button click
|
2015-12-30 17:01:36 +00:00
|
|
|
_ <- view `on` buttonPressEvent $ do
|
2015-12-30 16:53:16 +00:00
|
|
|
eb <- eventButton
|
|
|
|
t <- eventTime
|
|
|
|
case eb of
|
2016-04-09 14:26:12 +00:00
|
|
|
RightButton -> do
|
2016-04-24 16:38:25 +00:00
|
|
|
_ <- liftIO $ menuPopup (rcMenu . rcmenu $ myview)
|
2016-04-09 14:26:12 +00:00
|
|
|
$ Just (RightButton, t)
|
|
|
|
-- this is just to not screw with current selection
|
|
|
|
-- on right-click
|
|
|
|
-- TODO: this misbehaves under IconView
|
|
|
|
(x, y) <- eventCoordinates
|
|
|
|
mpath <- liftIO $ getPathAtPos fmv (x, y)
|
|
|
|
case mpath of
|
|
|
|
-- item under the cursor, only pass on the signal
|
|
|
|
-- if the item under the cursor is not within the current
|
|
|
|
-- selection
|
|
|
|
(Just tp) -> do
|
|
|
|
selectedTps <- liftIO $ getSelectedTreePaths mygui myview
|
|
|
|
return $ elem tp selectedTps
|
|
|
|
-- no item under the cursor, pass on the signal
|
|
|
|
Nothing -> return False
|
2016-06-01 20:02:18 +00:00
|
|
|
MiddleButton -> do
|
|
|
|
(x, y) <- eventCoordinates
|
|
|
|
mitem <- liftIO $ (getPathAtPos fmv (x, y))
|
|
|
|
>>= \mpos -> fmap join
|
|
|
|
$ forM mpos (rawPathToItem myview)
|
|
|
|
|
|
|
|
case mitem of
|
|
|
|
-- item under the cursor, only pass on the signal
|
|
|
|
-- if the item under the cursor is not within the current
|
|
|
|
-- selection
|
|
|
|
(Just item) -> do
|
|
|
|
liftIO $ newTabHere mygui item
|
|
|
|
return True
|
|
|
|
-- no item under the cursor, pass on the signal
|
|
|
|
Nothing -> return False
|
|
|
|
|
2016-04-19 22:38:22 +00:00
|
|
|
OtherButton 8 -> do
|
|
|
|
liftIO $ goHistoryPrev mygui myview
|
|
|
|
return False
|
|
|
|
OtherButton 9 -> do
|
|
|
|
liftIO $ goHistoryNext mygui myview
|
|
|
|
return False
|
2016-04-09 14:26:12 +00:00
|
|
|
-- not right-click, so pass on the signal
|
|
|
|
_ -> return False
|
2016-04-24 16:38:25 +00:00
|
|
|
|
|
|
|
-- right click menu
|
|
|
|
_ <- (rcFileOpen . rcmenu) myview `on` menuItemActivated $
|
2015-12-30 16:53:16 +00:00
|
|
|
liftIO $ withItems mygui myview open
|
2016-04-24 16:38:25 +00:00
|
|
|
_ <- (rcFileExecute . rcmenu) myview `on` menuItemActivated $
|
2015-12-30 16:53:16 +00:00
|
|
|
liftIO $ withItems mygui myview execute
|
2016-04-24 16:38:25 +00:00
|
|
|
_ <- (rcFileNewRegFile . rcmenu) myview `on` menuItemActivated $
|
2015-12-30 16:53:16 +00:00
|
|
|
liftIO $ newFile mygui myview
|
2016-04-24 16:38:25 +00:00
|
|
|
_ <- (rcFileNewDir . rcmenu) myview `on` menuItemActivated $
|
2016-04-17 01:12:34 +00:00
|
|
|
liftIO $ newDir mygui myview
|
2016-04-24 16:38:25 +00:00
|
|
|
_ <- (rcFileCopy . rcmenu) myview `on` menuItemActivated $
|
2015-12-30 16:53:16 +00:00
|
|
|
liftIO $ withItems mygui myview copyInit
|
2016-04-24 16:38:25 +00:00
|
|
|
_ <- (rcFileRename . rcmenu) myview `on` menuItemActivated $
|
2015-12-30 16:53:16 +00:00
|
|
|
liftIO $ withItems mygui myview renameF
|
2016-04-24 16:38:25 +00:00
|
|
|
_ <- (rcFilePaste . rcmenu) myview `on` menuItemActivated $
|
2016-04-17 22:51:45 +00:00
|
|
|
liftIO $ operationFinal mygui myview Nothing
|
2016-04-24 16:38:25 +00:00
|
|
|
_ <- (rcFileDelete . rcmenu) myview `on` menuItemActivated $
|
2015-12-30 16:53:16 +00:00
|
|
|
liftIO $ withItems mygui myview del
|
2016-04-24 16:38:25 +00:00
|
|
|
_ <- (rcFileProperty . rcmenu) myview `on` menuItemActivated $
|
2016-04-19 19:05:29 +00:00
|
|
|
liftIO $ withItems mygui myview showFilePropertyDialog
|
2016-04-24 16:38:25 +00:00
|
|
|
_ <- (rcFileCut . rcmenu) myview `on` menuItemActivated $
|
2015-12-30 16:53:16 +00:00
|
|
|
liftIO $ withItems mygui myview moveInit
|
2016-04-24 16:38:25 +00:00
|
|
|
_ <- (rcFileIconView . rcmenu) myview `on` menuItemActivated $
|
|
|
|
liftIO $ switchView mygui myview createIconView
|
|
|
|
_ <- (rcFileTreeView . rcmenu) myview `on` menuItemActivated $
|
|
|
|
liftIO $ switchView mygui myview createTreeView
|
2015-12-30 16:53:16 +00:00
|
|
|
return ()
|
2016-04-24 16:38:25 +00:00
|
|
|
|
2016-04-09 14:26:12 +00:00
|
|
|
getPathAtPos fmv (x, y) =
|
|
|
|
case fmv of
|
|
|
|
FMTreeView treeView -> do
|
|
|
|
mp <- treeViewGetPathAtPos treeView (round x, round y)
|
|
|
|
return $ fmap (\(p, _, _) -> p) mp
|
|
|
|
FMIconView iconView ->
|
|
|
|
fmap (\tp -> if null tp then Nothing else Just tp)
|
|
|
|
$ iconViewGetPathAtPos iconView (round x) (round y)
|
|
|
|
|
2015-12-19 15:13:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2016-04-24 18:00:34 +00:00
|
|
|
---- OTHER ----
|
|
|
|
|
|
|
|
|
|
|
|
openTerminalHere :: MyView -> IO ProcessID
|
|
|
|
openTerminalHere myview = do
|
|
|
|
cwd <- (P.fromAbs . path) <$> getCurrentDir myview
|
|
|
|
-- TODO: make terminal configurable
|
|
|
|
SPP.forkProcess $ SPP.executeFile "sakura" True ["-d", cwd] Nothing
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
---- TAB OPERATIONS ----
|
2016-04-24 16:38:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
-- |Closes the current tab, but only if there is more than one tab.
|
|
|
|
closeTab :: MyGUI -> MyView -> IO ()
|
|
|
|
closeTab mygui myview = do
|
|
|
|
n <- notebookGetNPages (notebook mygui)
|
|
|
|
when (n > 1) $ void $ destroyView mygui myview
|
|
|
|
|
|
|
|
|
2016-06-01 20:02:18 +00:00
|
|
|
newTabHere :: MyGUI -> Item -> IO ()
|
|
|
|
newTabHere mygui item =
|
|
|
|
void $ newTab mygui createTreeView (path item)
|
|
|
|
|
|
|
|
|
2015-12-19 15:13:48 +00:00
|
|
|
|
2016-04-19 23:25:40 +00:00
|
|
|
---- FILE OPERATION CALLBACKS (COPY, MOVE, ...) ----
|
2015-12-24 13:41:06 +00:00
|
|
|
|
|
|
|
|
2015-12-27 17:17:33 +00:00
|
|
|
-- |Supposed to be used with 'withRows'. Deletes a file or directory.
|
2015-12-30 16:53:16 +00:00
|
|
|
del :: [Item] -> MyGUI -> MyView -> IO ()
|
2016-03-31 14:19:31 +00:00
|
|
|
del [item] _ _ = withErrorDialog $ do
|
2016-04-16 19:50:15 +00:00
|
|
|
let cmsg = "Really delete \"" ++ getFPasStr item ++ "\"?"
|
2015-12-22 16:56:37 +00:00
|
|
|
withConfirmationDialog cmsg
|
2016-05-02 17:14:41 +00:00
|
|
|
$ easyDelete . path $ item
|
2015-12-27 17:17:33 +00:00
|
|
|
-- this throws on the first error that occurs
|
2016-03-31 14:19:31 +00:00
|
|
|
del items@(_:_) _ _ = withErrorDialog $ do
|
2015-12-30 16:53:16 +00:00
|
|
|
let cmsg = "Really delete " ++ show (length items) ++ " files?"
|
2015-12-27 17:17:33 +00:00
|
|
|
withConfirmationDialog cmsg
|
2016-05-02 17:14:41 +00:00
|
|
|
$ forM_ items $ \item -> easyDelete . path $ item
|
2015-12-27 17:17:33 +00:00
|
|
|
del _ _ _ = withErrorDialog
|
2016-05-09 09:34:02 +00:00
|
|
|
. throwIO $ InvalidOperation
|
|
|
|
"Operation not supported on multiple files"
|
2015-12-19 15:13:48 +00:00
|
|
|
|
|
|
|
|
2015-12-23 15:09:37 +00:00
|
|
|
-- |Initializes a file move operation.
|
2015-12-30 16:53:16 +00:00
|
|
|
moveInit :: [Item] -> MyGUI -> MyView -> IO ()
|
2016-04-24 16:38:25 +00:00
|
|
|
moveInit items@(_:_) mygui _ = do
|
2016-05-02 17:14:41 +00:00
|
|
|
writeTVarIO (operationBuffer mygui) (FMove . PartialMove . map path $ items)
|
2016-04-09 13:15:05 +00:00
|
|
|
let sbmsg = case items of
|
2016-04-16 19:50:15 +00:00
|
|
|
(item:[]) -> "Move buffer: " ++ getFPasStr item
|
2016-04-09 13:15:05 +00:00
|
|
|
_ -> "Move buffer: " ++ (show . length $ items)
|
|
|
|
++ " items"
|
2015-12-28 02:20:29 +00:00
|
|
|
popStatusbar mygui
|
2015-12-28 01:02:06 +00:00
|
|
|
void $ pushStatusBar mygui sbmsg
|
2015-12-27 17:17:33 +00:00
|
|
|
moveInit _ _ _ = withErrorDialog
|
2016-05-09 09:34:02 +00:00
|
|
|
. throwIO $ InvalidOperation
|
|
|
|
"No file selected!"
|
2015-12-23 15:09:37 +00:00
|
|
|
|
2015-12-27 17:17:33 +00:00
|
|
|
-- |Supposed to be used with 'withRows'. Initializes a file copy operation.
|
2015-12-30 16:53:16 +00:00
|
|
|
copyInit :: [Item] -> MyGUI -> MyView -> IO ()
|
2016-04-24 16:38:25 +00:00
|
|
|
copyInit items@(_:_) mygui _ = do
|
2016-05-02 17:14:41 +00:00
|
|
|
writeTVarIO (operationBuffer mygui) (FCopy . PartialCopy . map path $ items)
|
2016-04-09 13:15:05 +00:00
|
|
|
let sbmsg = case items of
|
2016-04-16 19:50:15 +00:00
|
|
|
(item:[]) -> "Copy buffer: " ++ getFPasStr item
|
2016-04-09 13:15:05 +00:00
|
|
|
_ -> "Copy buffer: " ++ (show . length $ items)
|
|
|
|
++ " items"
|
2015-12-28 02:20:29 +00:00
|
|
|
popStatusbar mygui
|
2015-12-28 01:02:06 +00:00
|
|
|
void $ pushStatusBar mygui sbmsg
|
2015-12-27 17:17:33 +00:00
|
|
|
copyInit _ _ _ = withErrorDialog
|
2016-05-09 09:34:02 +00:00
|
|
|
. throwIO $ InvalidOperation
|
|
|
|
"No file selected!"
|
2015-12-19 15:13:48 +00:00
|
|
|
|
|
|
|
|
2015-12-23 15:09:37 +00:00
|
|
|
-- |Finalizes a file operation, such as copy or move.
|
2016-04-17 22:51:45 +00:00
|
|
|
operationFinal :: MyGUI -> MyView -> Maybe Item -> IO ()
|
2016-04-17 23:02:18 +00:00
|
|
|
operationFinal mygui myview mitem = withErrorDialog $ do
|
2016-04-24 16:38:25 +00:00
|
|
|
op <- readTVarIO (operationBuffer mygui)
|
2016-04-17 22:51:45 +00:00
|
|
|
cdir <- case mitem of
|
|
|
|
Nothing -> path <$> getCurrentDir myview
|
|
|
|
Just x -> return $ path x
|
2015-12-19 15:13:48 +00:00
|
|
|
case op of
|
2016-05-02 17:14:41 +00:00
|
|
|
FMove (PartialMove s) -> do
|
2016-04-09 13:15:05 +00:00
|
|
|
let cmsg = "Really move " ++ imsg s
|
2016-05-29 11:26:21 +00:00
|
|
|
++ " to \"" ++ toString (P.fromAbs cdir)
|
2016-04-04 22:56:36 +00:00
|
|
|
++ "\"?"
|
2016-05-08 18:14:30 +00:00
|
|
|
withConfirmationDialog cmsg $ doFileOperation (FMove $ Move s cdir)
|
|
|
|
popStatusbar mygui
|
|
|
|
writeTVarIO (operationBuffer mygui) None
|
2016-05-02 17:14:41 +00:00
|
|
|
FCopy (PartialCopy s) -> do
|
2016-04-09 13:15:05 +00:00
|
|
|
let cmsg = "Really copy " ++ imsg s
|
2016-05-29 11:26:21 +00:00
|
|
|
++ " to \"" ++ toString (P.fromAbs cdir)
|
2016-04-04 22:56:36 +00:00
|
|
|
++ "\"?"
|
2016-05-08 18:14:30 +00:00
|
|
|
withConfirmationDialog cmsg $ doFileOperation (FCopy $ Copy s cdir)
|
2015-12-19 15:13:48 +00:00
|
|
|
_ -> return ()
|
2016-04-09 13:15:05 +00:00
|
|
|
where
|
|
|
|
imsg s = case s of
|
2016-05-29 11:26:21 +00:00
|
|
|
(item:[]) -> "\"" ++ toString (P.fromAbs item) ++ "\""
|
2016-04-09 13:15:05 +00:00
|
|
|
items -> (show . length $ items) ++ " items"
|
2015-12-19 15:13:48 +00:00
|
|
|
|
|
|
|
|
2016-04-17 01:12:34 +00:00
|
|
|
-- |Create a new file.
|
2015-12-25 21:51:45 +00:00
|
|
|
newFile :: MyGUI -> MyView -> IO ()
|
2016-03-31 14:19:31 +00:00
|
|
|
newFile _ myview = withErrorDialog $ do
|
2016-05-08 22:45:47 +00:00
|
|
|
mfn <- textInputDialog "Enter file name" ("" :: String)
|
2016-05-29 11:26:21 +00:00
|
|
|
let pmfn = P.parseFn =<< fromString <$> mfn
|
2016-03-30 00:50:32 +00:00
|
|
|
for_ pmfn $ \fn -> do
|
2015-12-26 02:04:28 +00:00
|
|
|
cdir <- getCurrentDir myview
|
2016-05-02 17:14:41 +00:00
|
|
|
createRegularFile (path cdir P.</> fn)
|
2015-12-26 02:04:28 +00:00
|
|
|
|
|
|
|
|
2016-04-17 01:12:34 +00:00
|
|
|
-- |Create a new directory.
|
|
|
|
newDir :: MyGUI -> MyView -> IO ()
|
|
|
|
newDir _ myview = withErrorDialog $ do
|
2016-05-08 22:45:47 +00:00
|
|
|
mfn <- textInputDialog "Enter directory name" ("" :: String)
|
2016-05-29 11:26:21 +00:00
|
|
|
let pmfn = P.parseFn =<< fromString <$> mfn
|
2016-04-17 01:12:34 +00:00
|
|
|
for_ pmfn $ \fn -> do
|
|
|
|
cdir <- getCurrentDir myview
|
2016-05-02 17:14:41 +00:00
|
|
|
createDir (path cdir P.</> fn)
|
2016-04-17 01:12:34 +00:00
|
|
|
|
|
|
|
|
2015-12-30 16:53:16 +00:00
|
|
|
renameF :: [Item] -> MyGUI -> MyView -> IO ()
|
2016-03-31 14:19:31 +00:00
|
|
|
renameF [item] _ _ = withErrorDialog $ do
|
2016-05-08 22:45:47 +00:00
|
|
|
iname <- P.fromRel <$> (P.basename $ path item)
|
|
|
|
mfn <- textInputDialog "Enter new file name" (iname :: ByteString)
|
2016-05-29 11:26:21 +00:00
|
|
|
let pmfn = P.parseFn =<< fromString <$> mfn
|
2016-03-30 00:50:32 +00:00
|
|
|
for_ pmfn $ \fn -> do
|
2016-04-16 19:50:15 +00:00
|
|
|
let cmsg = "Really rename \"" ++ getFPasStr item
|
2016-04-04 22:56:36 +00:00
|
|
|
++ "\"" ++ " to \""
|
2016-05-29 11:26:21 +00:00
|
|
|
++ toString (P.fromAbs $ (P.dirname . path $ item)
|
2016-04-15 12:23:41 +00:00
|
|
|
P.</> fn) ++ "\"?"
|
2016-03-30 18:16:34 +00:00
|
|
|
withConfirmationDialog cmsg $
|
2016-05-09 14:37:02 +00:00
|
|
|
HPath.IO.renameFile (path item)
|
|
|
|
((P.dirname $ path item) P.</> fn)
|
2015-12-27 17:17:33 +00:00
|
|
|
renameF _ _ _ = withErrorDialog
|
2016-05-09 09:34:02 +00:00
|
|
|
. throwIO $ InvalidOperation
|
|
|
|
"Operation not supported on multiple files"
|
2016-04-19 22:38:22 +00:00
|
|
|
|
|
|
|
|
2016-04-19 23:25:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
---- DIRECTORY TRAVERSAL AND FILE OPENING CALLBACKS ----
|
|
|
|
|
|
|
|
|
|
|
|
-- |Go to the url given at the 'urlBar' and visualize it in the given
|
|
|
|
-- treeView.
|
|
|
|
--
|
|
|
|
-- If the url is invalid, does nothing.
|
|
|
|
urlGoTo :: MyGUI -> MyView -> IO ()
|
|
|
|
urlGoTo mygui myview = withErrorDialog $ do
|
2016-04-24 16:38:25 +00:00
|
|
|
fp <- entryGetText (urlBar myview)
|
2016-04-19 23:25:40 +00:00
|
|
|
forM_ (P.parseAbs fp :: Maybe (Path Abs)) $ \fp' ->
|
|
|
|
whenM (canOpenDirectory fp')
|
2016-06-01 20:00:37 +00:00
|
|
|
(goDir True mygui myview =<< (readFile getFileInfo $ fp'))
|
2016-04-19 23:25:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
goHome :: MyGUI -> MyView -> IO ()
|
|
|
|
goHome mygui myview = withErrorDialog $ do
|
|
|
|
mhomedir <- getEnv "HOME"
|
|
|
|
forM_ (P.parseAbs =<< mhomedir :: Maybe (Path Abs)) $ \fp' ->
|
|
|
|
whenM (canOpenDirectory fp')
|
2016-06-01 20:00:37 +00:00
|
|
|
(goDir True mygui myview =<< (readFile getFileInfo $ fp'))
|
2016-04-19 23:25:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
-- |Execute a given file.
|
|
|
|
execute :: [Item] -> MyGUI -> MyView -> IO ()
|
|
|
|
execute [item] _ _ = withErrorDialog $
|
2016-05-02 17:14:41 +00:00
|
|
|
void $ executeFile (path item) []
|
2016-04-19 23:25:40 +00:00
|
|
|
execute _ _ _ = withErrorDialog
|
2016-05-09 09:34:02 +00:00
|
|
|
. throwIO $ InvalidOperation
|
|
|
|
"Operation not supported on multiple files"
|
2016-04-19 23:25:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
-- |Supposed to be used with 'withRows'. Opens a file or directory.
|
|
|
|
open :: [Item] -> MyGUI -> MyView -> IO ()
|
|
|
|
open [item] mygui myview = withErrorDialog $
|
|
|
|
case item of
|
|
|
|
DirOrSym r -> do
|
|
|
|
nv <- readFile getFileInfo $ path r
|
2016-06-01 20:00:37 +00:00
|
|
|
goDir True mygui myview nv
|
2016-04-19 23:25:40 +00:00
|
|
|
r ->
|
2016-05-02 17:14:41 +00:00
|
|
|
void $ openFile . path $ r
|
2016-04-19 23:25:40 +00:00
|
|
|
-- this throws on the first error that occurs
|
|
|
|
open (FileLikeList fs) _ _ = withErrorDialog $
|
2016-05-02 17:14:41 +00:00
|
|
|
forM_ fs $ \f -> void $ openFile . path $ f
|
2016-04-19 23:25:40 +00:00
|
|
|
open _ _ _ = withErrorDialog
|
2016-05-09 09:34:02 +00:00
|
|
|
. throwIO $ InvalidOperation
|
|
|
|
"Operation not supported on multiple files"
|
2016-04-19 23:25:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
-- |Go up one directory and visualize it in the treeView.
|
|
|
|
upDir :: MyGUI -> MyView -> IO ()
|
|
|
|
upDir mygui myview = withErrorDialog $ do
|
|
|
|
cdir <- getCurrentDir myview
|
|
|
|
nv <- goUp cdir
|
2016-06-01 20:00:37 +00:00
|
|
|
goDir True mygui myview nv
|
2016-04-19 23:25:40 +00:00
|
|
|
|
|
|
|
|
2016-04-19 22:38:22 +00:00
|
|
|
-- |Go "back" in the history.
|
|
|
|
goHistoryPrev :: MyGUI -> MyView -> IO ()
|
|
|
|
goHistoryPrev mygui myview = do
|
|
|
|
hs <- readTVarIO (history myview)
|
|
|
|
case hs of
|
|
|
|
([], _) -> return ()
|
|
|
|
(x:xs, _) -> do
|
|
|
|
cdir <- getCurrentDir myview
|
|
|
|
nv <- readFile getFileInfo $ x
|
|
|
|
modifyTVarIO (history myview)
|
|
|
|
(\(_, n) -> (xs, path cdir `addHistory` n))
|
2016-06-01 20:00:37 +00:00
|
|
|
goDir False mygui myview nv
|
2016-04-19 22:38:22 +00:00
|
|
|
|
|
|
|
|
|
|
|
-- |Go "forth" in the history.
|
|
|
|
goHistoryNext :: MyGUI -> MyView -> IO ()
|
|
|
|
goHistoryNext mygui myview = do
|
|
|
|
hs <- readTVarIO (history myview)
|
|
|
|
case hs of
|
|
|
|
(_, []) -> return ()
|
|
|
|
(_, x:xs) -> do
|
|
|
|
cdir <- getCurrentDir myview
|
|
|
|
nv <- readFile getFileInfo $ x
|
|
|
|
modifyTVarIO (history myview)
|
|
|
|
(\(p, _) -> (path cdir `addHistory` p, xs))
|
2016-06-01 20:00:37 +00:00
|
|
|
goDir False mygui myview nv
|
2016-04-19 22:38:22 +00:00
|
|
|
|