Mar 08

I have my search functions working again. The problem was that when Gtk was updated, and I updated my code to this I also changed how FilePath’s were passed around to the various methods. I did this to only pass around what was necessary, rather than the full paths, and I never reflected this within my search code! Pretty stupid really, but an easy mistake to make. A mistake that also had a domino effect on the methods that search uses!! So when search was fixed, I had to go through the other methods and update those too!

I edited my openFile method so that, it tries to open the supplied file using “xdg-open”. If that is successful, it returns ExitSuccess, and the function exits. However, if it returns any other type of exit, i.e. ExitFailure Int, it searches a file containg extensions & commands. It searches for the extension of the supplied file. If it’s found it asks the user for a command to run the file with, i.e. .hs files are opened in gedit. If the command that the user enters is successful, it then writes the extension command combo to the file for future use.

I finally figured out how to do a right-click menu, which is pretty good, the code is 90% identical to the file menu code. Originally, following the example I found, the action had to be added to the overall window, but I found that that didn’t work. It has to be added to the ScrolledWindow that the user will be making selections from. This has a couple of benefits: Different menu’s for different parts of the screen.

I still have to try to:

  • Implement Drag and Drop.
  • Expand tree to selected
  • Now that I have the right-click menu, try renaming within the scrolled window.

M

Tagged with:
Feb 17

I worked xdg-open into the code now, so all files open on double-click/selecting open from the buttons.

I removed the in-file searching from my search method, as it is takes to long to complete when searching from a high directory. I tested a search for *png* from “/” aswell, and that has thrown up quite a few errors I didn’t catch before.

One of particular interest is in my filterLinks method, which removes symbolic links & unaccessible entries from a list of FilePath’s. The function getSymbolicLinkStatus was throwing errors for accessing a file in the “/proc/” folder, and adding error catching to this is trouble some, as there is no “visible” constructor for FileStatus. This means that returning a “custom” FileStatus isn’t possible, so i decided to use fileExist as a work around for this. and if an error is thrown here it returns False, and myfunction can carry on from there.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
filterLinks :: [FilePath] -> IO [FilePath]
filterLinks [] = return []
filterLinks (x:xs) = do
        exists <- fileExist x `E.catch` (\e -> return ( False ) )
        case exists of
                True -> do --Get filestatus associated with x.
                        status <- getSymbolicLinkStatus x
                        --Determine wherther or not it is a link.
                        let link = isSymbolicLink status
                        nonLink <- case link of
                                        --If so, remove x and filter remaining.
                                        True -> filterLinks xs
                                        --Otherwise keep, and filter remaining.
                                        False -> do
                                                        list <- filterLinks xs
                                                        return ( x : list )
                        accessible <- filterM (\paths -> fileAccess paths True False False ) nonLink
                        return ( accessible )
                False -> do
                                list <- filterLinks xs
                                return ( list )

The search function is also droping a “/” from the end of the first folder name of each result in it’s result set, which is annoying. I’m really going to have to find a way to speed this search up, even though full system searches probably won’t be a commonly used function!

It’s basically superficial things I have left to do now, I have all the core functionality working.

M

Tagged with:
Feb 16

After spending all day, trying to figure out a decent way of opening programs, and storing the commands/icon details related to the different file types, I come across this while looking at the man page for open:

xdg-open FILENAME

Basically, I can execute this from my program using the rawSystem command, ( link in previous post ), i.e.

rawSystem "xdg-open" [fileName]

and that will open the system’s default application associated with that file. Convenient! I spent a couple of days looking at ways of using the system itself to open files, and several hours tab completing letters that might have anything to do with files on the command line, and looking at any command that came up that might be related to files and I didn’t come across that!

How I was planning on storing/accessing file information, was to just use the file extension, to search a list of predefined programs for one associated with that extension. If it found an associated program, it would execute that program’s command, passing the selected file’s path to it as a parameter, and that would open the program. This list of program information would be read at execution and written to file at closing, due to new programs being added to the list. Basically the program information would be stored in a Program type containing a String representing a program command, a list of Strings representing the extensions, and a String representing the icon name, with methods for finding the icon and command names, like so (very simple prototype methods):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
newtype Program = Program (String,[String],String) deriving ( Show )
 
getProgramInfos :: IO [Program]
getProgramInfos = do
        conts <- readFile "program_info.txt"
        return ( assignInfo ( lines conts ) )
 
assignInfo :: [String] -> [Program]
assignInfo [] = []
assignInfo (x:xs) = thisProg : assignInfo xs
        where progwords = words x
              thisProg = Program ( head progwords, tail ( init progwords ), last progwords )
 
findIcon :: FilePath -> [Program] -> String
findIcon file [] = "File"
findIcon file ((Program (_, etns, icon)):xs)
 | ( tail ( takeExtension file ) `elem` etns ) = icon
 | otherwise = findIcon file xs

Now, I can just predefine my set of icons for certain file types i.e. pdf, txt, and have a generic one for unknown file types!

M

Tagged with:
preload preload preload