QT File Dialog (open folder) and KDE-NEON Extension

Hi there,

I’m really struggling to get an “Open Directory” dialog working in a snap. The dialog really fits in niceley in the GTK Theme, but instead of selecting a directory, only file-selection is possible (Clicking of open opens the folder in the dialog instead of selecting the folder and returning the path to the app).

Using DontUseNativeDialog option, folder selection is possible, but i try to avoid this, because

  • I prefer not to change the existing code of an application
  • it looks pretty ugly.

I am using the QT QFileDialog class with QFileDialog::ShowDirsOnly.
My snap is based on core18 and i use the KDE extension to keep the snap small.

The behaviour of the snap is consistent in all Versions: Ubuntu 18.04, 20.04 and 20.10 (where the new xdg-desktop-portal package is installed on the host) and regardless of the environment variable QT_QPA_PLATFORMTHEME (gtk3 or xdgdesktopportal).

Here is a little example project i wrote to test the code: https://gitlab.com/tschlaeppi/test-openfolder-qt
…and of course the snap in the store: https://snapcraft.io/test-openfolder-qt

Here the versions i use:
snapcraft, version 4.4.4
snap 2.48.1
snapd 2.48.1
series 16
ubuntu 20.04
kernel 5.4.0-58-generic

Can i force the app to not use portals?
Is there another way?
Does this work for anyone?

Thanks

Thomas

I did some further analysis, compared the application in a flatpak vs. the snap sandbox.

When i start xdg-destop-portal (G_MESSAGES_DEBUG=all /usr/libexec/xdg-desktop-portal --verbose --replace) on the host service with logging enabled, it’s clear that the snapped application calls the portal (‘Handling Openfile’) - the flatpak version does not - which is fine, because of the limitations of my host system (Ubuntu 20.04 with installed xdg_desktop-portal 1.6.0, open folder is not possible, source: https://snapcraft.io/docs/xdg-desktop-portals)

Opened a bug report: https://bugs.launchpad.net/snappy/+bug/1909033

Looking at DBus traffic, the Qt backend is calling the portal directly, in which case I would suggest asking the Qt guys how to trigger the right behavior when a different version of a portal is running.

The actual request looks like this:

‣ Type=method_call  Endian=l  Flags=0  Version=1 Cookie=10                                                                                                                                     
  Sender=:1.605  Destination=org.freedesktop.portal.Desktop  Path=/org/freedesktop/portal/desktop  Interface=org.freedesktop.portal.FileChooser  Member=OpenFile                               
  UniqueName=:1.605                                                                            
  MESSAGE "ssa{sv}" {                                                                          
          STRING "x11:0";                                                                      
          STRING "";                                                                                                                                                                           
          ARRAY "{sv}" {                                                                                                                                                                       
                  DICT_ENTRY "sv" {                                                            
                          STRING "filters";                                                    
                          VARIANT "a(sa(us))" {                                                                                                                                                
                                  ARRAY "(sa(us))" {                                                                                                                                           
                                          STRUCT "sa(us)" {                                                                                                                                    
                                                  STRING "All Files ";                         
                                                  ARRAY "(us)" {                                                                                                                               
                                                          STRUCT "us" {                                                                                                                        
                                                                  UINT32 0;                    
                                                                  STRING "*";                  
                                                          };                                                                                                                                   
                                                  };                                                                                                                                           
                                          };                                                   
                                  };                                                           
                          };                                                                                                                                                                   
                  };                                                                                                                                                                           
                  DICT_ENTRY "sv" {                                                            
                          STRING "handle_token";                                               
                          VARIANT "s" {                                                                                                                                                        
                                  STRING "qt2804674725";                                       
                          };                                                                   
                  };                                                                                                                                                                           
                  DICT_ENTRY "sv" {                                                                                                                                                            
                          STRING "modal";                                                      
                          VARIANT "b" {                                                                                                                                                        
                                  BOOLEAN true;                                                                                                                                                
                          };                                                                   
                  };                                                                                                                                                                           
                  DICT_ENTRY "sv" {                                                            
                          STRING "multiple";                                                   
                          VARIANT "b" {                                                                                                                                                        
                                  BOOLEAN false;                                                                                                                                               
                          };                                                                   
                  };                                                                                                                                                                           
          };                                                                                                                                                                                   
  };  

According to the docs https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#idm9, the caller can pass directory: true in request options to indicate that they want to select directories only. Even though I have a recent enough version of the xdg-desktop-portal the option isn’t set. The options is supported only for interface version 3 (and up?).

However, I have not seen any requests to get properties from your app so, I assume that the Qt version you use does not check that. Digging a bit more more, the directories are only correctly handled via portals since 5.15.1: https://github.com/qt/qtbase/commit/844967d297327dc72a1aa67644c1b2fa3fe6839c The same commit suggests that the old code would always use a native file dialog? Anyways, this is a question for someone more familiar with Qt.

Could this be backported to focal’s Qt to help people who build snaps with Qt from core20?

Thank you. the snapcraft version (core18/kde-neon) uses qt 5.12.3, flatpak with the runtime org.kde.Platform/5.15 uses 5.15.2.

So the resolution will probably be to use a recent version of qt… which is not that simple.