Merge branch 'linux_filedialog_improvements' of https://github.com/GoaLitiuM/FlaxEngine into GoaLitiuM-linux_filedialog_improvements

This commit is contained in:
Wojtek Figat
2023-02-15 14:21:44 +01:00
4 changed files with 62 additions and 12 deletions

View File

@@ -50,11 +50,16 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(FileSystemBase);
/// </summary>
/// <param name="parentWindow">The parent window or null.</param>
/// <param name="initialDirectory">The initial directory.</param>
/// <param name="filter">The custom filter.</param>
/// <param name="filter">The file filter string as null-terminated pairs of name and list of extensions. Multiple file extensions must be separated with semicolon.</param>
/// <param name="multiSelect">True if allow multiple files to be selected, otherwise use single-file mode.</param>
/// <param name="title">The dialog title.</param>
/// <param name="filenames">The output names of the files picked by the user.</param>
/// <returns>True if failed, otherwise false.</returns>
/// <remarks>
/// Example file filters:
/// "All Files\0*.*"
/// "All Files\0*.*\0Image Files\0*.png;*.jpg"
/// </remarks>
API_FUNCTION() static bool ShowOpenFileDialog(Window* parentWindow, const StringView& initialDirectory, const StringView& filter, bool multiSelect, const StringView& title, API_PARAM(Out) Array<String, HeapAllocation>& filenames);
/// <summary>
@@ -62,11 +67,16 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(FileSystemBase);
/// </summary>
/// <param name="parentWindow">The parent window.</param>
/// <param name="initialDirectory">The initial directory.</param>
/// <param name="filter">The filter.</param>
/// <param name="filter">The file filter string as null-terminated pairs of name and list of extensions. Multiple file extensions must be separated with semicolon.</param>
/// <param name="multiSelect">True if allow multiple files to be selected, otherwise use single-file mode.</param>
/// <param name="title">The title.</param>
/// <param name="filenames">The output names of the files picked by the user.</param>
/// <returns>True if failed, otherwise false.</returns>
/// <remarks>
/// Example file filters:
/// "All Files\0*.*"
/// "All Files\0*.*\0Image Files\0*.png;*.jpg"
/// </remarks>
API_FUNCTION() static bool ShowSaveFileDialog(Window* parentWindow, const StringView& initialDirectory, const StringView& filter, bool multiSelect, const StringView& title, API_PARAM(Out) Array<String, HeapAllocation>& filenames);
/// <summary>

View File

@@ -528,4 +528,17 @@ String StringUtils::ToString(double value)
return String::Format(TEXT("{}"), value);
}
String StringUtils::GetZZString(const Char* str)
{
const Char* end = str;
while (*end != '\0')
{
end++;
if (*end == '\0')
end++;
}
const int len = end - str;
return String(str, len);
}
#undef STRING_UTILS_ITOSTR_BUFFER_SIZE

View File

@@ -4,7 +4,9 @@
#include "LinuxFileSystem.h"
#include "Engine/Platform/File.h"
#include "Engine/Platform/StringUtils.h"
#include "Engine/Core/Types/String.h"
#include "Engine/Core/Types/StringBuilder.h"
#include "Engine/Core/Types/StringView.h"
#include "Engine/Core/Types/TimeSpan.h"
#include "Engine/Core/Math/Math.h"
@@ -27,20 +29,38 @@ bool LinuxFileSystem::ShowOpenFileDialog(Window* parentWindow, const StringView&
{
const StringAsANSI<> initialDirectoryAnsi(*initialDirectory, initialDirectory.Length());
const StringAsANSI<> titleAnsi(*title, title.Length());
const char* initDir = initialDirectory.HasChars() ? initialDirectoryAnsi.Get() : ".";
char cmd[2048];
if (FileSystem::FileExists(TEXT("/usr/bin/zenity")))
String xdgCurrentDesktop;
StringBuilder fileFilter;
Array<String> fileFilterEntries;
Platform::GetEnvironmentVariable(TEXT("XDG_CURRENT_DESKTOP"), xdgCurrentDesktop);
StringUtils::GetZZString(filter.Get()).Split('\0', fileFilterEntries);
const bool zenitySupported = FileSystem::FileExists(TEXT("/usr/bin/zenity"));
const bool kdialogSupported = FileSystem::FileExists(TEXT("/usr/bin/kdialog"));
if (zenitySupported && (xdgCurrentDesktop != TEXT("KDE") || !kdialogSupported)) // Prefer kdialog when running on KDE
{
// TODO: initialDirectory support
// TODO: multiSelect support
// TODO: filter support
sprintf(cmd, "/usr/bin/zenity --modal --file-selection --title=\"%s\" ", titleAnsi.Get());
for (int32 i = 1; i < fileFilterEntries.Count(); i += 2)
{
String extensions(fileFilterEntries[i]);
fileFilterEntries[i].Replace(TEXT(";"), TEXT(" "));
fileFilter.Append(String::Format(TEXT("{0}--file-filter=\"{1}|{2}\""), i > 1 ? TEXT(" ") : TEXT(""), fileFilterEntries[i-1].Get(), extensions.Get()));
}
sprintf(cmd, "/usr/bin/zenity --modal --file-selection %s--filename=\"%s\" --title=\"%s\" %s ", multiSelect ? "--multiple --separator=$'\n' " : " ", initDir, titleAnsi.Get(), fileFilter.ToStringView().ToStringAnsi().GetText());
}
else if (FileSystem::FileExists(TEXT("/usr/bin/kdialog")))
else if (kdialogSupported)
{
// TODO: multiSelect support
// TODO: filter support
const char* initDir = initialDirectory.HasChars() ? initialDirectoryAnsi.Get() : ".";
sprintf(cmd, "/usr/bin/kdialog --getopenfilename \"%s\" --title \"%s\" ", initDir, titleAnsi.Get());
for (int32 i = 1; i < fileFilterEntries.Count(); i += 2)
{
String extensions(fileFilterEntries[i]);
fileFilterEntries[i].Replace(TEXT(";"), TEXT(" "));
fileFilter.Append(String::Format(TEXT("{0}\"{1}({2})\""), i > 1 ? TEXT(" ") : TEXT(""), fileFilterEntries[i-1].Get(), extensions.Get()));
}
fileFilter.Append(String::Format(TEXT("{0}\"{1}({2})\""), TEXT(" "), TEXT("many things"), TEXT("*.png *.jpg")));
sprintf(cmd, "/usr/bin/kdialog --getopenfilename %s--title \"%s\" \"%s\" %s ", multiSelect ? "--multiple --separate-output " : " ", titleAnsi.Get(), initDir, fileFilter.ToStringView().ToStringAnsi().GetText());
}
else
{

View File

@@ -438,6 +438,13 @@ public:
static String ToString(uint64 value);
static String ToString(float value);
static String ToString(double value);
public:
// Returns the String to double null-terminated string
// @param str Double null-terminated string
// @return Double null-terminated String
static String GetZZString(const Char* str);
};
inline uint32 GetHash(const char* key)