mirror of
				https://github.com/AlexandreRouma/SDRPlusPlus.git
				synced 2025-11-04 10:49:11 +01:00 
			
		
		
		
	Added cross platform support for file and folder select widgets
This commit is contained in:
		
							
								
								
									
										2
									
								
								.github/workflows/build_all.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/build_all.yml
									
									
									
									
										vendored
									
									
								
							@@ -66,7 +66,7 @@ jobs:
 | 
			
		||||
 | 
			
		||||
        - name: Prepare CMake
 | 
			
		||||
          working-directory: ${{runner.workspace}}/build
 | 
			
		||||
          run: cmake $GITHUB_WORKSPACE -DOPT_BUILD_AIRSPYHF_SOURCE=OFF -DOPT_BUILD_PLUTOSDR_SOURCE=OFF -DOPT_BUILD_SOAPY_SOURCE=OFF
 | 
			
		||||
          run: cmake $GITHUB_WORKSPACE -DOPT_BUILD_AIRSPYHF_SOURCE=OFF -DOPT_BUILD_PLUTOSDR_SOURCE=OFF -DOPT_BUILD_SOAPY_SOURCE=OFF -DOPT_BUILD_AIRSPY_SOURCE=OFF
 | 
			
		||||
 | 
			
		||||
        - name: Build
 | 
			
		||||
          working-directory: ${{runner.workspace}}/build
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,7 @@ namespace sdrpp_credits {
 | 
			
		||||
        "RtAudio",
 | 
			
		||||
        "SoapySDR (PothosWare)",
 | 
			
		||||
        "spdlog (gabime)",
 | 
			
		||||
        "Portable File Dialogs"
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const char* patrons[] = {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1709
									
								
								core/src/gui/file_dialogs.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1709
									
								
								core/src/gui/file_dialogs.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -2,17 +2,17 @@
 | 
			
		||||
#include <regex>
 | 
			
		||||
#include <options.h>
 | 
			
		||||
#include <filesystem>
 | 
			
		||||
#include <gui/file_dialogs.h>
 | 
			
		||||
 | 
			
		||||
FileSelect::FileSelect(std::string defaultPath) {
 | 
			
		||||
    path = defaultPath;
 | 
			
		||||
    pathValid = std::filesystem::is_regular_file(path);
 | 
			
		||||
    strcpy(strPath, path.c_str());
 | 
			
		||||
FileSelect::FileSelect(std::string defaultPath, std::vector<std::string> filter) {
 | 
			
		||||
    _filter = filter;
 | 
			
		||||
    setPath(defaultPath);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool FileSelect::render(std::string id) {
 | 
			
		||||
    bool _pathChanged = false;
 | 
			
		||||
    float menuColumnWidth = ImGui::GetContentRegionAvailWidth();
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
 | 
			
		||||
    float buttonWidth = ImGui::CalcTextSize("...").x + 20.0f;
 | 
			
		||||
    bool lastPathValid = pathValid;
 | 
			
		||||
    if (!lastPathValid) {
 | 
			
		||||
@@ -37,29 +37,9 @@ bool FileSelect::render(std::string id) {
 | 
			
		||||
    if (ImGui::Button(("..." + id + "_winselect").c_str(), ImVec2(buttonWidth - 8.0f, 0)) && !dialogOpen) {
 | 
			
		||||
        dialogOpen = true;
 | 
			
		||||
        if (workerThread.joinable()) { workerThread.join(); }
 | 
			
		||||
        workerThread = std::thread(&FileSelect::windowsWorker, this);
 | 
			
		||||
        workerThread = std::thread(&FileSelect::worker, this);
 | 
			
		||||
    }
 | 
			
		||||
#else
 | 
			
		||||
    bool lastPathValid = pathValid;
 | 
			
		||||
    if (!lastPathValid) {
 | 
			
		||||
        ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.0f, 0.0f, 1.0f));
 | 
			
		||||
    }
 | 
			
		||||
    ImGui::SetNextItemWidth(menuColumnWidth);
 | 
			
		||||
    if (ImGui::InputText(id.c_str(), strPath, 2047)) {
 | 
			
		||||
        path = std::string(strPath);
 | 
			
		||||
        std::string expandedPath = expandString(strPath);
 | 
			
		||||
        if (!std::filesystem::is_regular_file(expandedPath)) {
 | 
			
		||||
            pathValid = false;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            pathValid = true;
 | 
			
		||||
            _pathChanged = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (!lastPathValid) {
 | 
			
		||||
        ImGui::PopStyleColor();
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
    
 | 
			
		||||
    _pathChanged |= pathChanged;
 | 
			
		||||
    pathChanged = false;
 | 
			
		||||
    return _pathChanged;
 | 
			
		||||
@@ -67,7 +47,8 @@ bool FileSelect::render(std::string id) {
 | 
			
		||||
 | 
			
		||||
void FileSelect::setPath(std::string path) {
 | 
			
		||||
    this->path = path;
 | 
			
		||||
    pathValid = std::filesystem::is_regular_file(path);
 | 
			
		||||
    std::string expandedPath = expandString(path);
 | 
			
		||||
    pathValid = std::filesystem::is_regular_file(expandedPath);
 | 
			
		||||
    strcpy(strPath, path.c_str());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -80,35 +61,16 @@ bool FileSelect::pathIsValid() {
 | 
			
		||||
    return pathValid;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
void FileSelect::worker() {
 | 
			
		||||
        auto file = pfd::open_file("Open File", "", _filter);
 | 
			
		||||
        std::vector<std::string> res = file.result();
 | 
			
		||||
 | 
			
		||||
void FileSelect::setWindowsFilter(COMDLG_FILTERSPEC* filt, int n) {
 | 
			
		||||
    filter = filt;
 | 
			
		||||
    filterCount = n;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FileSelect::windowsWorker() {
 | 
			
		||||
        IFileOpenDialog *pFileOpen;
 | 
			
		||||
        HRESULT hr;
 | 
			
		||||
 | 
			
		||||
        // Create the FileOpenDialog object.
 | 
			
		||||
        hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL, IID_IFileOpenDialog, reinterpret_cast<void**>(&pFileOpen));
 | 
			
		||||
        
 | 
			
		||||
        if (filter != NULL) { pFileOpen->SetFileTypes(filterCount, filter); }
 | 
			
		||||
 | 
			
		||||
        hr = pFileOpen->Show(NULL);
 | 
			
		||||
        if (SUCCEEDED(hr)) {
 | 
			
		||||
            PWSTR pszFilePath;
 | 
			
		||||
            IShellItem *pItem;
 | 
			
		||||
            hr = pFileOpen->GetResult(&pItem);
 | 
			
		||||
            hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath);
 | 
			
		||||
            wcstombs(strPath, pszFilePath, 2048);
 | 
			
		||||
            CoTaskMemFree(pszFilePath);
 | 
			
		||||
            path = std::string(strPath);
 | 
			
		||||
        if (res.size() > 0) {
 | 
			
		||||
            path = res[0];
 | 
			
		||||
            strcpy(strPath, path.c_str());
 | 
			
		||||
            pathChanged = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        pathValid = std::filesystem::is_regular_file(path);
 | 
			
		||||
        pathValid = std::filesystem::is_regular_file(expandString(path));
 | 
			
		||||
        dialogOpen = false;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
@@ -3,16 +3,11 @@
 | 
			
		||||
#include <imgui_internal.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
#include <Windows.h>
 | 
			
		||||
#include <thread>
 | 
			
		||||
#include <ShlObj.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
class FileSelect {
 | 
			
		||||
public:
 | 
			
		||||
    FileSelect(std::string defaultPath);
 | 
			
		||||
    FileSelect(std::string defaultPath, std::vector<std::string> filter = {"All Files", "*"});
 | 
			
		||||
    bool render(std::string id);
 | 
			
		||||
    void setPath(std::string path);
 | 
			
		||||
    bool pathIsValid();
 | 
			
		||||
@@ -20,20 +15,13 @@ public:
 | 
			
		||||
    std::string expandString(std::string input);
 | 
			
		||||
 | 
			
		||||
    std::string path = "";
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
    void setWindowsFilter(COMDLG_FILTERSPEC* filt, int n);
 | 
			
		||||
#endif
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
    void windowsWorker();
 | 
			
		||||
    void worker();
 | 
			
		||||
    std::thread workerThread;
 | 
			
		||||
    COMDLG_FILTERSPEC* filter = NULL;
 | 
			
		||||
    int filterCount = 0;
 | 
			
		||||
#endif
 | 
			
		||||
    std::vector<std::string> _filter;
 | 
			
		||||
 | 
			
		||||
    char _filter[2048];
 | 
			
		||||
    bool pathValid = false;
 | 
			
		||||
    bool dialogOpen = false;
 | 
			
		||||
    char strPath[2048];
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@
 | 
			
		||||
#include <regex>
 | 
			
		||||
#include <options.h>
 | 
			
		||||
#include <filesystem>
 | 
			
		||||
#include <gui/file_dialogs.h>
 | 
			
		||||
 | 
			
		||||
FolderSelect::FolderSelect(std::string defaultPath) {
 | 
			
		||||
    setPath(defaultPath);
 | 
			
		||||
@@ -10,7 +11,7 @@ FolderSelect::FolderSelect(std::string defaultPath) {
 | 
			
		||||
bool FolderSelect::render(std::string id) {
 | 
			
		||||
    bool _pathChanged = false;
 | 
			
		||||
    float menuColumnWidth = ImGui::GetContentRegionAvailWidth();
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
 | 
			
		||||
    float buttonWidth = ImGui::CalcTextSize("...").x + 20.0f;
 | 
			
		||||
    bool lastPathValid = pathValid;
 | 
			
		||||
    if (!lastPathValid) {
 | 
			
		||||
@@ -35,29 +36,9 @@ bool FolderSelect::render(std::string id) {
 | 
			
		||||
    if (ImGui::Button(("..." + id + "_winselect").c_str(), ImVec2(buttonWidth - 8.0f, 0)) && !dialogOpen) {
 | 
			
		||||
        dialogOpen = true;
 | 
			
		||||
        if (workerThread.joinable()) { workerThread.join(); }
 | 
			
		||||
        workerThread = std::thread(&FolderSelect::windowsWorker, this);
 | 
			
		||||
        workerThread = std::thread(&FolderSelect::worker, this);
 | 
			
		||||
    }
 | 
			
		||||
#else
 | 
			
		||||
    bool lastPathValid = pathValid;
 | 
			
		||||
    if (!lastPathValid) {
 | 
			
		||||
        ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.0f, 0.0f, 1.0f));
 | 
			
		||||
    }
 | 
			
		||||
    ImGui::SetNextItemWidth(menuColumnWidth);
 | 
			
		||||
    if (ImGui::InputText(id.c_str(), strPath, 2047)) {
 | 
			
		||||
        path = std::string(strPath);
 | 
			
		||||
        std::string expandedPath = expandString(strPath);
 | 
			
		||||
        if (!std::filesystem::is_directory(expandedPath)) {
 | 
			
		||||
            pathValid = false;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            pathValid = true;
 | 
			
		||||
            _pathChanged = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (!lastPathValid) {
 | 
			
		||||
        ImGui::PopStyleColor();
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
    
 | 
			
		||||
    _pathChanged |= pathChanged;
 | 
			
		||||
    pathChanged = false;
 | 
			
		||||
    return _pathChanged;
 | 
			
		||||
@@ -79,31 +60,16 @@ bool FolderSelect::pathIsValid() {
 | 
			
		||||
    return pathValid;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
void FolderSelect::windowsWorker() {
 | 
			
		||||
        IFileOpenDialog *pFileOpen;
 | 
			
		||||
        HRESULT hr;
 | 
			
		||||
void FolderSelect::worker() {
 | 
			
		||||
        auto fold = pfd::select_folder("Select Folder");
 | 
			
		||||
        std::string res = fold.result();
 | 
			
		||||
 | 
			
		||||
        // Create the FileOpenDialog object.
 | 
			
		||||
        hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL, IID_IFileOpenDialog, reinterpret_cast<void**>(&pFileOpen));
 | 
			
		||||
        
 | 
			
		||||
        DWORD options;
 | 
			
		||||
        pFileOpen->GetOptions(&options);
 | 
			
		||||
        pFileOpen->SetOptions(options | FOS_PICKFOLDERS);
 | 
			
		||||
 | 
			
		||||
        hr = pFileOpen->Show(NULL);
 | 
			
		||||
        if (SUCCEEDED(hr)) {
 | 
			
		||||
            PWSTR pszFilePath;
 | 
			
		||||
            IShellItem *pItem;
 | 
			
		||||
            hr = pFileOpen->GetResult(&pItem);
 | 
			
		||||
            hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath);
 | 
			
		||||
            wcstombs(strPath, pszFilePath, 2048);
 | 
			
		||||
            CoTaskMemFree(pszFilePath);
 | 
			
		||||
            path = std::string(strPath);
 | 
			
		||||
        if (res != "") {
 | 
			
		||||
            path = res;
 | 
			
		||||
            strcpy(strPath, path.c_str());
 | 
			
		||||
            pathChanged = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        pathValid = std::filesystem::is_directory(path);
 | 
			
		||||
        pathValid = std::filesystem::is_directory(expandString(path));
 | 
			
		||||
        dialogOpen = false;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
@@ -3,12 +3,7 @@
 | 
			
		||||
#include <imgui_internal.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
#include <Windows.h>
 | 
			
		||||
#include <ShlObj.h>
 | 
			
		||||
#include <thread>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
class FolderSelect {
 | 
			
		||||
public:
 | 
			
		||||
@@ -23,10 +18,8 @@ public:
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
    void windowsWorker();
 | 
			
		||||
    void worker();
 | 
			
		||||
    std::thread workerThread;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    bool pathValid = false;
 | 
			
		||||
    bool dialogOpen = false;
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ SDRPP_MOD_INFO {
 | 
			
		||||
 | 
			
		||||
class FileSourceModule : public ModuleManager::Instance  {
 | 
			
		||||
public:
 | 
			
		||||
    FileSourceModule(std::string name) : fileSelect("") {
 | 
			
		||||
    FileSourceModule(std::string name) : fileSelect("", {"Wav IQ Files (*.wav)", "*.wav", "All Files", "*"}) {
 | 
			
		||||
        this->name = name;
 | 
			
		||||
 | 
			
		||||
        handler.ctx = this;
 | 
			
		||||
 
 | 
			
		||||
@@ -263,3 +263,4 @@ I will soon publish a contributing.md listing the code style to use.
 | 
			
		||||
* [spdlog (gabime)](https://github.com/gabime/spdlog)
 | 
			
		||||
* [json (nlohmann)](https://github.com/nlohmann/json)
 | 
			
		||||
* [rtaudio](http://www.portaudio.com/)
 | 
			
		||||
* [Portable File Dialogs](https://github.com/samhocevar/portable-file-dialogs)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user