Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Native file dialog on Linux Ubuntu "swallows" file extensions
Forum Updated to NodeBB v4.3 + New Features

Native file dialog on Linux Ubuntu "swallows" file extensions

Scheduled Pinned Locked Moved Solved General and Desktop
11 Posts 3 Posters 1.8k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Offline
    R Offline
    Robert Hairgrove
    wrote on 19 Sept 2019, 13:04 last edited by
    #1

    In the past, when I call the static QFileDialog::getOpenFileName() and QFileDialog::getSaveFileName() functions, the window manager in Ubuntu appears to hide the file extension from the user, although it filters the files correctly. I.e. if I pass a filter like CSV files (*.csv), on Ubuntu Nautilus the drop-down list at the bottom will only show "CSV files". So to get the "(*.csv)" part to show, I have been setting the filters like this: "CSV files [*.csv] (*.csv)" and the user will see "CSV files [*.csv]" which is OK.

    Now I discovered that I am getting a lot of Gtk warnings about GtkDialog mapped without a transient parent and have read somewhere that if you pass the option QFileDialog::DontUseNativeDialog, you can make the warnings go away. However, when I do that, the filter shows both the [*.csv] AND the (*.csv) part, which is obviously very strange for the user to see.

    Also, I would rather use the native dialog if possible because the user then has access to the bookmarks, etc. which are not shown in the non-native dialog.

    It is very strange because all other applications seem to get the file extension to show up in the selection list with no problem ... only in Qt. Is this a known bug?

    1 Reply Last reply
    0
    • R Offline
      R Offline
      Robert Hairgrove
      wrote on 19 Sept 2019, 14:35 last edited by
      #2

      I think this is a bug. Have a look at this function in the file qgtk3dialoghelpers.cpp (beginning at line 473 using Qt 5.11.1 sources):

      void QGtk3FileDialogHelper::setNameFilters(const QStringList &filters)
      {
          GtkDialog *gtkDialog = d->gtkDialog();
          foreach (GtkFileFilter *filter, _filters)
              gtk_file_chooser_remove_filter(GTK_FILE_CHOOSER(gtkDialog), filter);
      
          _filters.clear();
          _filterNames.clear();
      
          foreach (const QString &filter, filters) {
              GtkFileFilter *gtkFilter = gtk_file_filter_new();
              const QString name = filter.left(filter.indexOf(QLatin1Char('(')));
              const QStringList extensions = cleanFilterList(filter);
      
              gtk_file_filter_set_name(gtkFilter, qUtf8Printable(name.isEmpty() ? extensions.join(QLatin1String(", ")) : name));
              foreach (const QString &ext, extensions)
                  gtk_file_filter_add_pattern(gtkFilter, qUtf8Printable(ext));
      
              gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(gtkDialog), gtkFilter);
      
              _filters.insert(filter, gtkFilter);
              _filterNames.insert(gtkFilter, filter);
          }
      }
      

      According to the Gtk docs, the function gtk_file_filter_set_name() is supposed to set the "human-readable" part of the file filter. But the code immediately above it has stripped the variable name of the extension, so it seems obvious that it won't be shown.

      I seem to remember that on Windows, one could add the extension twice in round parentheses; however, it will get cut off at the first round left parenthesis here in this function.

      Should I file a bug report? Or has this been fixed in later versions of Qt?

      J 1 Reply Last reply 19 Sept 2019, 14:43
      0
      • R Robert Hairgrove
        19 Sept 2019, 14:35

        I think this is a bug. Have a look at this function in the file qgtk3dialoghelpers.cpp (beginning at line 473 using Qt 5.11.1 sources):

        void QGtk3FileDialogHelper::setNameFilters(const QStringList &filters)
        {
            GtkDialog *gtkDialog = d->gtkDialog();
            foreach (GtkFileFilter *filter, _filters)
                gtk_file_chooser_remove_filter(GTK_FILE_CHOOSER(gtkDialog), filter);
        
            _filters.clear();
            _filterNames.clear();
        
            foreach (const QString &filter, filters) {
                GtkFileFilter *gtkFilter = gtk_file_filter_new();
                const QString name = filter.left(filter.indexOf(QLatin1Char('(')));
                const QStringList extensions = cleanFilterList(filter);
        
                gtk_file_filter_set_name(gtkFilter, qUtf8Printable(name.isEmpty() ? extensions.join(QLatin1String(", ")) : name));
                foreach (const QString &ext, extensions)
                    gtk_file_filter_add_pattern(gtkFilter, qUtf8Printable(ext));
        
                gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(gtkDialog), gtkFilter);
        
                _filters.insert(filter, gtkFilter);
                _filterNames.insert(gtkFilter, filter);
            }
        }
        

        According to the Gtk docs, the function gtk_file_filter_set_name() is supposed to set the "human-readable" part of the file filter. But the code immediately above it has stripped the variable name of the extension, so it seems obvious that it won't be shown.

        I seem to remember that on Windows, one could add the extension twice in round parentheses; however, it will get cut off at the first round left parenthesis here in this function.

        Should I file a bug report? Or has this been fixed in later versions of Qt?

        J Offline
        J Offline
        jsulm
        Lifetime Qt Champion
        wrote on 19 Sept 2019, 14:43 last edited by
        #3

        @robert-hairgrove said in Native file dialog on Linux Ubuntu "swallows" file extensions:

        Or has this been fixed in later versions of Qt?

        I don't know, but you can test with the recent Qt version.

        https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        0
        • R Offline
          R Offline
          Robert Hairgrove
          wrote on 19 Sept 2019, 15:09 last edited by Robert Hairgrove
          #4

          Test case using the filter string from the Qt docs. Please note that the behavior probably is only shown on Linux with Gtk window manager.

          #include <QMainWindow>
          #include <QApplication>
          #include <QPushButton>
          #include <QtCore>
          #include <QFileDialog>
          #include <QMessageBox>
          
          int main(int argc, char *argv[])
          {
            QApplication a(argc, argv);
            QMainWindow w;
            QPushButton b;
            b.setText("Bye!");
            w.setCentralWidget(&b);
            w.connect(&b, &QPushButton::clicked, &w, &QMainWindow::close);
          
            QString fn = QFileDialog::getOpenFileName(
                  &w,
                  "Testing the native dialog",
                  QString(),
                  "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)");
            if (!fn.isEmpty()) {
              QString msg = "You chose the file:\n";
              QMessageBox::information(&w,"File Selected",msg.append(fn));
            }
            fn = QFileDialog::getOpenFileName(
                   &w,
                   "Testing the Qt (non-native) dialog",
                  QString(),
                  "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)",
                  nullptr, QFileDialog::DontUseNativeDialog);
            if (!fn.isEmpty()) {
              QString msg = "You chose the file:\n";
              QMessageBox::information(&w,"File Selected",msg.append(fn));
            }
          
            w.show();
            return a.exec();
          }
          
          1 Reply Last reply
          0
          • R Offline
            R Offline
            Robert Hairgrove
            wrote on 19 Sept 2019, 15:36 last edited by
            #5

            I just filed a bug report here.

            1 Reply Last reply
            2
            • R Offline
              R Offline
              Robert Hairgrove
              wrote on 21 Sept 2019, 07:54 last edited by
              #6

              I'm trying to create a workaround until this is fixed. Is there any way to determine which platform theme is used at compile time, or lacking that at runtime? I can use #ifdef __linux__ etc., but there are certainly other window managers which might be used and not just Gtk. And I couldn't find any Gtk-specific macros to use.

              And since the platform dialog helpers (QPA) are plugins, maybe a runtime decision as to how to format the filter string would be most appropriate. How can I do this?

              R 1 Reply Last reply 14 Nov 2020, 11:05
              0
              • SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on 21 Sept 2019, 19:17 last edited by
                #7

                Hi,

                You can use QSysInfo for runtime checks.

                You have the Q_OS_XXX macros for build time separation.

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                R 1 Reply Last reply 23 Sept 2019, 05:57
                1
                • SGaistS SGaist
                  21 Sept 2019, 19:17

                  Hi,

                  You can use QSysInfo for runtime checks.

                  You have the Q_OS_XXX macros for build time separation.

                  R Offline
                  R Offline
                  Robert Hairgrove
                  wrote on 23 Sept 2019, 05:57 last edited by
                  #8

                  @SGaist Thanks ... these are great suggestions, but I couldn't find any way of querying QSysInfo for the window manager currently being used. I would need something Gnome or Gtk-specific, I suppose.

                  1 Reply Last reply
                  0
                  • SGaistS Offline
                    SGaistS Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on 23 Sept 2019, 19:57 last edited by
                    #9

                    This thread might give you some clues:

                    Interested in AI ? www.idiap.ch
                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                    R 1 Reply Last reply 23 Sept 2019, 20:19
                    3
                    • SGaistS SGaist
                      23 Sept 2019, 19:57

                      This thread might give you some clues:

                      R Offline
                      R Offline
                      Robert Hairgrove
                      wrote on 23 Sept 2019, 20:19 last edited by
                      #10

                      @SGaist Fantastic ... this will certainly help ... thank you!

                      1 Reply Last reply
                      0
                      • R Robert Hairgrove
                        21 Sept 2019, 07:54

                        I'm trying to create a workaround until this is fixed. Is there any way to determine which platform theme is used at compile time, or lacking that at runtime? I can use #ifdef __linux__ etc., but there are certainly other window managers which might be used and not just Gtk. And I couldn't find any Gtk-specific macros to use.

                        And since the platform dialog helpers (QPA) are plugins, maybe a runtime decision as to how to format the filter string would be most appropriate. How can I do this?

                        R Offline
                        R Offline
                        Robert Hairgrove
                        wrote on 14 Nov 2020, 11:05 last edited by
                        #11

                        @Robert-Hairgrove In the meantime, I have resorted to iterating over the environment variables which are available in the main() function if you declare it like this:

                        int main(int argc, char*argv[], char*envp[]) { /*...*/ }
                        

                        If any of the strings contain "GNOME" or "GTK_", I can set a global flag which allows me to mogrify the filter string so that it isn't swallowed. So if my filter string looks like this:

                        "Text files (*.txt)"
                        

                        then I insert two Unicode look-alike characters (u8'FF08' and u8'FF09', full-width parentheses) and duplicate the extension, i.e.:

                        "Text files(*.txt) (*.txt)"
                        

                        The user will see: "Text files(*.txt)" which is good enough for my purposes.

                        1 Reply Last reply
                        0

                        • Login

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved