Closed smolck closed 3 years ago
Hi,
Would you mind sharing the code you have so far? I'm trying to do the same but I'm stuck even before I get the FileChooserDialog to display properly.
I have an unfinished workaround consisting of a FileChooserWidget plus Buttons inside a Box inside a (regular) Dialog. That might perhaps work but it's quite ugly.
Thanks, Martin
@marhop Hi! So, I haven't used Haskell or worked on the project I was making with this library in a little while, but iirc what I ended up doing was write some imperative code to create the dialog which I then used in the declarative view
. So I have this function (with a little bit of context included; also, please excuse any messiness, my Haskell skills are not the best :sweat_smile:):
data Event
= Closed
| Save (Maybe FilePath)
showFileChooserDialog :: IO Event
showFileChooserDialog =
Gtk.new FileChooserDialog [#action Gtk.:= FileChooserActionSave] >>= run
where
run :: FileChooserDialog -> IO Event
run fc = do
configure fc
event <- eventFromResponse fc (#run fc)
#destroy fc
pure event
configure :: Gtk.FileChooserDialog -> IO ()
configure fc = do
#addButton fc "Cancel" 1
#addButton fc "Save" 2
#setDefaultResponse fc 2
eventFromResponse :: Gtk.FileChooserDialog -> IO Int32 -> IO Event
eventFromResponse fc resp = do
resp' <- resp
#getUri fc
>>= pure
. fmap (Text.unpack . Text.replace "file://" "")
>>= if resp' == 2 then pure . Save else const $ pure (Save Nothing)
Then, I use it in the view like so:
container
MenuBar
[]
[ subMenu
"File"
[ menuItem MenuItem [onM #activate (const showFileChooserDialog)]
$ widget Label [#label := "Save"]
]
]
If you need more information like with imports or language extensions or similar let me know and I'll see if I can give you those as well.
Note that I haven't tested this (started the compilation but it's still not finished :smile:) but hopefully it gives you enough to get an idea of what you can do.
Also, there may very well be a better way of doing this that is more declarative, I just didn't know it at the time (and still don't).
Wow, thank you very much for your quick and detailed answer! That's really helpful. I'll take a closer look at the weekend.
OK, I now played with your code and it works like a charm. Thanks, that helped a lot! I spent some rather confused evenings with this problem and don't know if I would have come up with the idea to solve it imperatively on my own.
If I may offer some hints in return:
#getUri
with #getFilename
you can get rid of the Text.replace
part because #getFilename
seems to drop the file://
prefix anyway.#run
because you already get a proper Maybe value from #getUri
(or #getFilename
).~ EDIT: I was wrong here. If you don't check the response ID the Save
event will contain a Just
value if a file was selected, even if the dialog was cancelled afterwards. This is a great way to introduce some interesting bugs. ;-) A corrected version is in my comment below.So I went with something like this:
showFileChooserDialog :: IO Event
showFileChooserDialog = do
fc <- new FileChooserDialog [#action Gtk.:= FileChooserActionSave]
_ <- #addButton fc "Cancel" 1
_ <- #addButton fc "Save" 2
#setDefaultResponse fc 2
_ <- #run fc
name <- #getFilename fc
#destroy fc
return $ Save name
Thanks again, Martin
Seems you're all set, but just for reference there is also FileChooserNative
, which I'm using in Komposition here:
Cheers!
Good point, that's even better! Not only does the FileChooserNative
dialog look nicer, it also adds the appropriate buttons automatically. So the above code can be further reduced to this (edited to check the response type):
showFileChooserDialog :: IO Event
showFileChooserDialog = do
fc <- new FileChooserNative [#action Gtk.:= FileChooserActionSave]
response <- toEnum . fromIntegral <$> #run fc
name <- #getFilename fc
#destroy fc
return . Save $ guard (response == ResponseTypeAccept) >> name
(FYI, ResponseType
is defined in GI.Gtk.Enums
.)
Cheers, Martin
Closing this as it seems there's an accepted solution to the problem? Otherwise let me know and I'll reopen.
Hello! So, I've been trying to use
FileChooserDialog
a bit, but I'm having some trouble with it. By default, it seems as though aFileChooserDialog
doesn't have any buttons at the bottom of the dialog, and I'm not sure how to add, say, aCancel
and aSave
button. I was wondering if I'd have to create a new custom widget to do that, or is there an easier way?My end goal is to have a
MenuBar
with a File > Save As button, but I'm not sure how to go about implementing the "Save As" part usingFileChooserDialog
; I'm not sure how to add theCancel
andSave
buttons at the bottom or how to know when the user is done choosing the filename/location for the file to be saved to.