mirror of
https://github.com/johndoe6345789/SDL3CPlusPlus.git
synced 2026-04-27 15:14:58 +00:00
stuff
This commit is contained in:
237
MaterialX/source/MaterialXGraphEditor/FileDialog.cpp
Normal file
237
MaterialX/source/MaterialXGraphEditor/FileDialog.cpp
Normal file
@@ -0,0 +1,237 @@
|
||||
//
|
||||
// Copyright Contributors to the MaterialX Project
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <MaterialXGraphEditor/FileDialog.h>
|
||||
|
||||
#include <MaterialXCore/Exception.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
FileDialog::FileDialog(int flags) :
|
||||
_flags(flags)
|
||||
{
|
||||
}
|
||||
|
||||
void FileDialog::setTitle(const std::string& title)
|
||||
{
|
||||
_title = title;
|
||||
}
|
||||
|
||||
void FileDialog::setTypeFilters(const mx::StringVec& typeFilters)
|
||||
{
|
||||
_filetypes.clear();
|
||||
|
||||
for (auto typefilter : typeFilters)
|
||||
{
|
||||
std::string minusExt = typefilter.substr(1, typefilter.size() - 1);
|
||||
std::pair<std::string, std::string> filterPair = { minusExt, minusExt };
|
||||
_filetypes.push_back(filterPair);
|
||||
}
|
||||
}
|
||||
|
||||
void FileDialog::open()
|
||||
{
|
||||
clearSelected();
|
||||
_openFlag = true;
|
||||
}
|
||||
|
||||
bool FileDialog::isOpened()
|
||||
{
|
||||
return _isOpened;
|
||||
}
|
||||
|
||||
bool FileDialog::hasSelected()
|
||||
{
|
||||
return !_selectedFilenames.empty();
|
||||
}
|
||||
|
||||
mx::FilePath FileDialog::getSelected()
|
||||
{
|
||||
return _selectedFilenames.empty() ? mx::FilePath() : _selectedFilenames[0];
|
||||
}
|
||||
|
||||
void FileDialog::clearSelected()
|
||||
{
|
||||
_selectedFilenames.clear();
|
||||
}
|
||||
|
||||
void FileDialog::display()
|
||||
{
|
||||
// Only call the dialog if it's not already displayed
|
||||
if (!_openFlag || _isOpened)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_openFlag = false;
|
||||
|
||||
// Check if we want to save or open
|
||||
bool save = !(_flags & SelectDirectory) && (_flags & EnterNewFilename);
|
||||
|
||||
mx::StringVec result = launchFileDialog(_filetypes, save, false);
|
||||
std::string path = result.empty() ? "" : result.front();
|
||||
if (!path.empty())
|
||||
{
|
||||
_selectedFilenames.push_back(path);
|
||||
}
|
||||
|
||||
_isOpened = false;
|
||||
}
|
||||
|
||||
#if !defined(__APPLE__)
|
||||
mx::StringVec launchFileDialog(const std::vector<std::pair<std::string, std::string>>& filetypes, bool save, bool multiple)
|
||||
{
|
||||
static const int FILE_DIALOG_MAX_BUFFER = 16384;
|
||||
if (save && multiple)
|
||||
{
|
||||
throw mx::Exception("save and multiple must not both be true.");
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
OPENFILENAME ofn;
|
||||
ZeroMemory(&ofn, sizeof(OPENFILENAME));
|
||||
ofn.lStructSize = sizeof(OPENFILENAME);
|
||||
char tmp[FILE_DIALOG_MAX_BUFFER];
|
||||
ofn.lpstrFile = tmp;
|
||||
ZeroMemory(tmp, FILE_DIALOG_MAX_BUFFER);
|
||||
ofn.nMaxFile = FILE_DIALOG_MAX_BUFFER;
|
||||
ofn.nFilterIndex = 1;
|
||||
|
||||
std::string filter;
|
||||
|
||||
if (!save && filetypes.size() > 1)
|
||||
{
|
||||
filter.append("Supported file types (");
|
||||
for (size_t i = 0; i < filetypes.size(); ++i)
|
||||
{
|
||||
filter.append("*.");
|
||||
filter.append(filetypes[i].first);
|
||||
if (i + 1 < filetypes.size())
|
||||
filter.append(";");
|
||||
}
|
||||
filter.append(")");
|
||||
filter.push_back('\0');
|
||||
for (size_t i = 0; i < filetypes.size(); ++i)
|
||||
{
|
||||
filter.append("*.");
|
||||
filter.append(filetypes[i].first);
|
||||
if (i + 1 < filetypes.size())
|
||||
filter.append(";");
|
||||
}
|
||||
filter.push_back('\0');
|
||||
}
|
||||
for (auto pair : filetypes)
|
||||
{
|
||||
filter.append(pair.second);
|
||||
filter.append(" (*.");
|
||||
filter.append(pair.first);
|
||||
filter.append(")");
|
||||
filter.push_back('\0');
|
||||
filter.append("*.");
|
||||
filter.append(pair.first);
|
||||
filter.push_back('\0');
|
||||
}
|
||||
filter.push_back('\0');
|
||||
ofn.lpstrFilter = filter.data();
|
||||
|
||||
if (save)
|
||||
{
|
||||
ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT;
|
||||
if (GetSaveFileNameA(&ofn) == FALSE)
|
||||
return {};
|
||||
}
|
||||
else
|
||||
{
|
||||
ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
|
||||
if (multiple)
|
||||
ofn.Flags |= OFN_ALLOWMULTISELECT;
|
||||
if (GetOpenFileNameA(&ofn) == FALSE)
|
||||
return {};
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
mx::StringVec result;
|
||||
while (tmp[i] != '\0')
|
||||
{
|
||||
result.emplace_back(&tmp[i]);
|
||||
i += result.back().size() + 1;
|
||||
}
|
||||
|
||||
if (result.size() > 1)
|
||||
{
|
||||
for (i = 1; i < result.size(); ++i)
|
||||
{
|
||||
result[i] = result[0] + "\\" + result[i];
|
||||
}
|
||||
result.erase(begin(result));
|
||||
}
|
||||
|
||||
if (save && ofn.nFilterIndex > 0)
|
||||
{
|
||||
auto ext = filetypes[ofn.nFilterIndex - 1].first;
|
||||
if (ext != "*")
|
||||
{
|
||||
ext.insert(0, ".");
|
||||
|
||||
auto& name = result.front();
|
||||
if (name.size() <= ext.size() ||
|
||||
name.compare(name.size() - ext.size(), ext.size(), ext) != 0)
|
||||
{
|
||||
name.append(ext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
#else
|
||||
char buffer[FILE_DIALOG_MAX_BUFFER];
|
||||
buffer[0] = '\0';
|
||||
|
||||
std::string cmd = "zenity --file-selection ";
|
||||
// The safest separator for multiple selected paths is /, since / can never occur
|
||||
// in file names. Only where two paths are concatenated will there be two / following
|
||||
// each other.
|
||||
if (multiple)
|
||||
cmd += "--multiple --separator=\"/\" ";
|
||||
if (save)
|
||||
cmd += "--save ";
|
||||
cmd += "--file-filter=\"";
|
||||
for (size_t i = 0, n = filetypes.size(); i < n; ++i)
|
||||
{
|
||||
cmd += "\"*." + filetypes[i].first + "\"";
|
||||
if (i+1 < n)
|
||||
cmd += " ";
|
||||
}
|
||||
cmd += "\"";
|
||||
FILE* output = popen(cmd.c_str(), "r");
|
||||
if (output == nullptr)
|
||||
throw mx::Exception("popen() failed -- could not launch zenity!");
|
||||
while (fgets(buffer, FILE_DIALOG_MAX_BUFFER, output) != NULL)
|
||||
;
|
||||
pclose(output);
|
||||
std::string paths(buffer);
|
||||
paths.erase(std::remove(paths.begin(), paths.end(), '\n'), paths.end());
|
||||
|
||||
mx::StringVec result;
|
||||
while (!paths.empty())
|
||||
{
|
||||
size_t end = paths.find("//");
|
||||
if (end == std::string::npos)
|
||||
{
|
||||
result.emplace_back(paths);
|
||||
paths = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
result.emplace_back(paths.substr(0, end));
|
||||
paths = paths.substr(end + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user