Qt: Always return paths with native directory separators

Add a function to WiresharkFileDialog to return the path with native
path separators ('\' on Windows) and alter the static functions to do
the same. Use WiresharkFileDialog everywhere instead of QFileDialog.

Qt and GLib can always handle paths with native path separators.
Our native dialog with the Win32 API used to give native path
separators, but the Qt dialog (whether Qt's native dialog or the
non native Qt widgets) has always returned a result with '/' as a
universal path separator, resulting in storing mixed path separators
in UAT preferences and other preference files.

Fix #19852
This commit is contained in:
John Thacker 2024-05-24 20:01:53 -04:00
parent a3c63ce61f
commit a3d57e8897
6 changed files with 33 additions and 16 deletions

View File

@ -593,7 +593,7 @@ int CaptureFileDialog::open(QString &file_name, unsigned int &type, QString &dis
}
if (WiresharkFileDialog::exec() && selectedFiles().length() > 0) {
file_name = selectedFiles()[0];
file_name = selectedNativePath();
type = open_info_name_to_type(qPrintable(format_type_.currentText()));
display_filter.append(display_filter_edit_->text());
@ -626,7 +626,7 @@ check_savability_t CaptureFileDialog::saveAs(QString &file_name, bool must_suppo
if (WiresharkFileDialog::exec() && selectedFiles().length() > 0) {
int file_type;
file_name = selectedFiles()[0];
file_name = selectedNativePath();
file_type = selectedFileType();
/* Is the file type bogus? */
if (file_type == WTAP_FILE_TYPE_SUBTYPE_UNKNOWN) {
@ -676,7 +676,7 @@ check_savability_t CaptureFileDialog::exportSelectedPackets(QString &file_name,
if (WiresharkFileDialog::exec() && selectedFiles().length() > 0) {
int file_type;
file_name = selectedFiles()[0];
file_name = selectedNativePath();
file_type = selectedFileType();
/* Is the file type bogus? */
if (file_type == WTAP_FILE_TYPE_SUBTYPE_UNKNOWN) {
@ -711,7 +711,7 @@ int CaptureFileDialog::merge(QString &file_name, QString &display_filter) {
resize(width() * WIDTH_SCALE_FACTOR, height() * HEIGHT_SCALE_FACTOR + right_v_box_.minimumSize().height() + display_filter_edit_->minimumSize().height());
if (WiresharkFileDialog::exec() && selectedFiles().length() > 0) {
file_name.append(selectedFiles()[0]);
file_name.append(selectedNativePath());
display_filter.append(display_filter_edit_->text());
return QDialog::Accepted;

View File

@ -132,7 +132,7 @@ void ExportDissectionDialog::dialogAccepted(const QStringList &selected)
*/
hide();
cf_print_status_t status;
QString file_name = selected[0];
QString file_name = QDir::toNativeSeparators(selected[0]);
/* Fill in our print (and export) args */

View File

@ -24,6 +24,7 @@
#include "main_application.h"
#include <ui/qt/utils/color_utils.h>
#include <ui/qt/simple_dialog.h>
#include <ui/qt/widgets/wireshark_file_dialog.h>
#include <QBrush>
#include <QDir>
@ -34,7 +35,6 @@
#include <QUrl>
#include <QComboBox>
#include <QLineEdit>
#include <QFileDialog>
#include <QStandardPaths>
#include <QKeyEvent>
#include <QMenu>
@ -615,7 +615,7 @@ void ProfileDialog::exportProfiles(bool exportAllPersonalProfiles)
return;
}
QString zipFile = QFileDialog::getSaveFileName(this, tr("Select zip file for export"), openDialogInitialDir(), tr("Zip File (*.zip)"));
QString zipFile = WiresharkFileDialog::getSaveFileName(this, tr("Select zip file for export"), openDialogInitialDir(), tr("Zip File (*.zip)"));
if (zipFile.length() > 0)
{
@ -646,7 +646,7 @@ void ProfileDialog::exportProfiles(bool exportAllPersonalProfiles)
void ProfileDialog::importFromZip()
{
QString zipFile = QFileDialog::getOpenFileName(this, tr("Select zip file for import"), openDialogInitialDir(), tr("Zip File (*.zip)"));
QString zipFile = WiresharkFileDialog::getOpenFileName(this, tr("Select zip file for import"), openDialogInitialDir(), tr("Zip File (*.zip)"));
QFileInfo fi(zipFile);
if (! fi.exists())
@ -662,7 +662,7 @@ void ProfileDialog::importFromZip()
void ProfileDialog::importFromDirectory()
{
QString importDir = QFileDialog::getExistingDirectory(this, tr("Select directory for import"), openDialogInitialDir());
QString importDir = WiresharkFileDialog::getExistingDirectory(this, tr("Select directory for import"), openDialogInitialDir());
QFileInfo fi(importDir);
if (! fi.isDir())

View File

@ -43,10 +43,11 @@
#include <ui/qt/utils/qt_ui_utils.h>
#include "main_application.h"
#include <ui/qt/widgets/wireshark_file_dialog.h>
#include <QClipboard>
#include <QContextMenuEvent>
#include <QMessageBox>
#include <QFileDialog>
// The GTK+ counterpart uses tap_param_dlg, which we don't use. If we
// need tap parameters we should probably create a TapParameterDialog
@ -548,7 +549,7 @@ void TapParameterDialog::on_actionSaveAs_triggered()
#ifdef Q_OS_WIN
HANDLE da_ctx = set_thread_per_monitor_v2_awareness();
#endif
QFileDialog SaveAsDialog(this, mainApp->windowTitleString(tr("Save Statistics As…")),
WiresharkFileDialog SaveAsDialog(this, mainApp->windowTitleString(tr("Save Statistics As…")),
get_open_dialog_initial_dir());
SaveAsDialog.setNameFilter(tr("Plain text file (*.txt);;"
"Comma separated values (*.csv);;"
@ -582,7 +583,7 @@ void TapParameterDialog::on_actionSaveAs_triggered()
}
// Get selected filename and add extension of necessary
QString file_name = SaveAsDialog.selectedFiles()[0];
QString file_name = SaveAsDialog.selectedNativePath();
if (!file_name.endsWith(file_ext, Qt::CaseInsensitive)) {
file_name.append(file_ext);
}

View File

@ -43,6 +43,15 @@ WiresharkFileDialog::WiresharkFileDialog(QWidget *parent, const QString &caption
#endif
}
QString WiresharkFileDialog::selectedNativePath() const
{
if (selectedFiles().isEmpty()) {
// The API implies this can't happen
return QString();
}
return QDir::toNativeSeparators(selectedFiles().at(0));
}
QString WiresharkFileDialog::getExistingDirectory(QWidget *parent, const QString &caption, const QString &dir, Options options)
{
#ifdef Q_OS_WIN
@ -52,7 +61,7 @@ QString WiresharkFileDialog::getExistingDirectory(QWidget *parent, const QString
#ifdef Q_OS_WIN
revert_thread_per_monitor_v2_awareness(da_ctx);
#endif
return ed;
return QDir::toNativeSeparators(ed);
}
QString WiresharkFileDialog::getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, Options options)
@ -64,7 +73,7 @@ QString WiresharkFileDialog::getOpenFileName(QWidget *parent, const QString &cap
#ifdef Q_OS_WIN
revert_thread_per_monitor_v2_awareness(da_ctx);
#endif
return ofn;
return QDir::toNativeSeparators(ofn);
}
QString WiresharkFileDialog::getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, Options options)
@ -76,5 +85,5 @@ QString WiresharkFileDialog::getSaveFileName(QWidget *parent, const QString &cap
#ifdef Q_OS_WIN
revert_thread_per_monitor_v2_awareness(da_ctx);
#endif
return sfn;
return QDir::toNativeSeparators(sfn);
}

View File

@ -15,6 +15,11 @@
/**
* @brief The WiresharkFileDialog class
*
* Qt uses '/' as a universal path separator and converts to native path
* separators, i.e., '\' on Windows, only immediately before displaying a
* path to a user. This class can return the path with native path
* separators.
*
* Qt <= 5.9 supports setting old (Windows 8.1) per-monitor DPI awareness
* via Qt:AA_EnableHighDpiScaling. We do this in main.cpp. In order for
* native dialogs to be rendered correctly we need to set per-monitor
@ -23,13 +28,15 @@
* we need to revert our thread context when we're done.
* The class functions below are simple wrappers around their QFileDialog
* equivalents that set PMv2 awareness before showing native dialogs on
* Windows and resets it afterward.
* Windows and resets it afterward. They also return the result with native
* directory separators on Windows.
*/
class WiresharkFileDialog : public QFileDialog
{
public:
WiresharkFileDialog(QWidget *parent = nullptr, const QString &caption = QString(), const QString &directory = QString(), const QString &filter = QString());
QString selectedNativePath() const;
static QString getExistingDirectory(QWidget *parent = Q_NULLPTR, const QString &caption = QString(), const QString &dir = QString(), Options options = ShowDirsOnly);
static QString getOpenFileName(QWidget *parent = Q_NULLPTR, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = Q_NULLPTR, Options options = Options());
static QString getSaveFileName(QWidget *parent = Q_NULLPTR, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = Q_NULLPTR, Options options = Options());