mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-11 18:34:58 +01:00
Reimplementation of Dialogs
Cleanup code to integrate multithreading process for dialogs into the DialogToolkit (avoid poluting UserInterfaceManager and improves reliability)
This commit is contained in:
@@ -6,16 +6,17 @@
|
|||||||
// because of 'zenity' access rights nightmare :(
|
// because of 'zenity' access rights nightmare :(
|
||||||
// Thus this re-implementation of native GTK+ dialogs for linux
|
// Thus this re-implementation of native GTK+ dialogs for linux
|
||||||
|
|
||||||
|
#include "defines.h"
|
||||||
|
#include "Settings.h"
|
||||||
|
#include "SystemToolkit.h"
|
||||||
|
#include "DialogToolkit.h"
|
||||||
|
|
||||||
#if defined(LINUX)
|
#if defined(LINUX)
|
||||||
#define USE_TINYFILEDIALOG 0
|
#define USE_TINYFILEDIALOG 0
|
||||||
#else
|
#else
|
||||||
#define USE_TINYFILEDIALOG 1
|
#define USE_TINYFILEDIALOG 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "defines.h"
|
|
||||||
#include "SystemToolkit.h"
|
|
||||||
#include "DialogToolkit.h"
|
|
||||||
|
|
||||||
#if USE_TINYFILEDIALOG
|
#if USE_TINYFILEDIALOG
|
||||||
#include "tinyfiledialogs.h"
|
#include "tinyfiledialogs.h"
|
||||||
#else
|
#else
|
||||||
@@ -61,7 +62,140 @@ bool gtk_init()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::string DialogToolkit::saveSessionFileDialog(const std::string &path)
|
|
||||||
|
// globals
|
||||||
|
const std::chrono::milliseconds timeout = std::chrono::milliseconds(4);
|
||||||
|
bool DialogToolkit::FileDialog::pending = false;
|
||||||
|
|
||||||
|
//
|
||||||
|
// FileDialog common functions
|
||||||
|
//
|
||||||
|
DialogToolkit::FileDialog::FileDialog(const std::string &name) : id_(name)
|
||||||
|
{
|
||||||
|
if ( Settings::application.dialogRecentFolder.count(id_) == 0 )
|
||||||
|
Settings::application.dialogRecentFolder[id_] = SystemToolkit::home_path();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DialogToolkit::FileDialog::closed()
|
||||||
|
{
|
||||||
|
if ( !promises_.empty() ) {
|
||||||
|
// check that file dialog thread finished
|
||||||
|
if (promises_.back().wait_for(timeout) == std::future_status::ready ) {
|
||||||
|
// get the filename from this file dialog
|
||||||
|
std::string string = promises_.back().get();
|
||||||
|
if (!string.empty()) {
|
||||||
|
// selected a filename
|
||||||
|
path_ = string;
|
||||||
|
// save path location
|
||||||
|
Settings::application.dialogRecentFolder[id_] = SystemToolkit::path_filename(string);
|
||||||
|
}
|
||||||
|
// done with this file dialog
|
||||||
|
promises_.pop_back();
|
||||||
|
pending = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// type specific implementations
|
||||||
|
//
|
||||||
|
std::string openImageFileDialog(const std::string &label, const std::string &path);
|
||||||
|
void DialogToolkit::OpenImageDialog::open()
|
||||||
|
{
|
||||||
|
if ( !pending && promises_.empty() ) {
|
||||||
|
promises_.emplace_back( std::async(std::launch::async, openImageFileDialog, id_,
|
||||||
|
Settings::application.dialogRecentFolder[id_]) );
|
||||||
|
pending = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string openSessionFileDialog(const std::string &label, const std::string &path);
|
||||||
|
void DialogToolkit::OpenSessionDialog::open()
|
||||||
|
{
|
||||||
|
if ( !pending && promises_.empty() ) {
|
||||||
|
promises_.emplace_back( std::async(std::launch::async, openSessionFileDialog, id_,
|
||||||
|
Settings::application.dialogRecentFolder[id_]) );
|
||||||
|
pending = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string openMediaFileDialog(const std::string &label, const std::string &path);
|
||||||
|
void DialogToolkit::OpenMediaDialog::open()
|
||||||
|
{
|
||||||
|
if ( !pending && promises_.empty() ) {
|
||||||
|
promises_.emplace_back( std::async(std::launch::async, openMediaFileDialog, id_,
|
||||||
|
Settings::application.dialogRecentFolder[id_]) );
|
||||||
|
pending = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string saveSessionFileDialog(const std::string &label, const std::string &path);
|
||||||
|
void DialogToolkit::SaveSessionDialog::open()
|
||||||
|
{
|
||||||
|
if ( !pending && promises_.empty() ) {
|
||||||
|
promises_.emplace_back( std::async(std::launch::async, saveSessionFileDialog, id_,
|
||||||
|
Settings::application.dialogRecentFolder[id_]) );
|
||||||
|
pending = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string openFolderDialog(const std::string &label, const std::string &path);
|
||||||
|
void DialogToolkit::OpenFolderDialog::open()
|
||||||
|
{
|
||||||
|
if ( !pending && promises_.empty() ) {
|
||||||
|
promises_.emplace_back( std::async(std::launch::async, openFolderDialog, id_,
|
||||||
|
Settings::application.dialogRecentFolder[id_]) );
|
||||||
|
pending = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::list<std::string> selectImagesFileDialog(const std::string &label,const std::string &path);
|
||||||
|
void DialogToolkit::MultipleImagesDialog::open()
|
||||||
|
{
|
||||||
|
if ( !pending && promisedlist_.empty() ) {
|
||||||
|
promisedlist_.emplace_back( std::async(std::launch::async, selectImagesFileDialog, id_,
|
||||||
|
Settings::application.dialogRecentFolder[id_]) );
|
||||||
|
pending = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DialogToolkit::MultipleImagesDialog::closed()
|
||||||
|
{
|
||||||
|
if ( !promisedlist_.empty() ) {
|
||||||
|
// check that file dialog thread finished
|
||||||
|
if (promisedlist_.back().wait_for(timeout) == std::future_status::ready ) {
|
||||||
|
// get the filename from this file dialog
|
||||||
|
std::list<std::string> list = promisedlist_.back().get();
|
||||||
|
if (!list.empty()) {
|
||||||
|
// selected a filenames
|
||||||
|
pathlist_ = list;
|
||||||
|
path_ = list.front();
|
||||||
|
// save path location
|
||||||
|
Settings::application.dialogRecentFolder[id_] = SystemToolkit::path_filename(path_);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pathlist_.clear();
|
||||||
|
path_.clear();
|
||||||
|
}
|
||||||
|
// done with this file dialog
|
||||||
|
promisedlist_.pop_back();
|
||||||
|
pending = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// CALLBACKS
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
std::string saveSessionFileDialog(const std::string &label, const std::string &path)
|
||||||
{
|
{
|
||||||
std::string filename = "";
|
std::string filename = "";
|
||||||
char const * save_pattern[1] = { "*.mix" };
|
char const * save_pattern[1] = { "*.mix" };
|
||||||
@@ -69,17 +203,17 @@ std::string DialogToolkit::saveSessionFileDialog(const std::string &path)
|
|||||||
#if USE_TINYFILEDIALOG
|
#if USE_TINYFILEDIALOG
|
||||||
char const * save_file_name;
|
char const * save_file_name;
|
||||||
|
|
||||||
save_file_name = tinyfd_saveFileDialog( "Save a session file", path.c_str(), 1, save_pattern, "vimix session");
|
save_file_name = tinyfd_saveFileDialog( label.c_str(), path.c_str(), 1, save_pattern, "vimix session");
|
||||||
|
|
||||||
if (save_file_name)
|
if (save_file_name)
|
||||||
filename = std::string(save_file_name);
|
filename = std::string(save_file_name);
|
||||||
#else
|
#else
|
||||||
if (!gtk_init()) {
|
if (!gtk_init()) {
|
||||||
ErrorDialog("Could not initialize GTK+ for dialog");
|
DialogToolkit::ErrorDialog("Could not initialize GTK+ for dialog");
|
||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkWidget *dialog = gtk_file_chooser_dialog_new( "Save Session File", NULL,
|
GtkWidget *dialog = gtk_file_chooser_dialog_new( label.c_str(), NULL,
|
||||||
GTK_FILE_CHOOSER_ACTION_SAVE,
|
GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||||
"_Cancel", GTK_RESPONSE_CANCEL,
|
"_Cancel", GTK_RESPONSE_CANCEL,
|
||||||
"_Save", GTK_RESPONSE_ACCEPT, NULL );
|
"_Save", GTK_RESPONSE_ACCEPT, NULL );
|
||||||
@@ -122,7 +256,7 @@ std::string DialogToolkit::saveSessionFileDialog(const std::string &path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string DialogToolkit::openSessionFileDialog(const std::string &path)
|
std::string openSessionFileDialog(const std::string &label, const std::string &path)
|
||||||
{
|
{
|
||||||
std::string filename = "";
|
std::string filename = "";
|
||||||
std::string startpath = SystemToolkit::file_exists(path) ? path : SystemToolkit::home_path();
|
std::string startpath = SystemToolkit::file_exists(path) ? path : SystemToolkit::home_path();
|
||||||
@@ -130,17 +264,17 @@ std::string DialogToolkit::openSessionFileDialog(const std::string &path)
|
|||||||
|
|
||||||
#if USE_TINYFILEDIALOG
|
#if USE_TINYFILEDIALOG
|
||||||
char const * open_file_name;
|
char const * open_file_name;
|
||||||
open_file_name = tinyfd_openFileDialog( "Import a file", startpath.c_str(), 1, open_pattern, "vimix session", 0);
|
open_file_name = tinyfd_openFileDialog( label.c_str(), startpath.c_str(), 1, open_pattern, "vimix session", 0);
|
||||||
|
|
||||||
if (open_file_name)
|
if (open_file_name)
|
||||||
filename = std::string(open_file_name);
|
filename = std::string(open_file_name);
|
||||||
#else
|
#else
|
||||||
if (!gtk_init()) {
|
if (!gtk_init()) {
|
||||||
ErrorDialog("Could not initialize GTK+ for dialog");
|
DialogToolkit::ErrorDialog("Could not initialize GTK+ for dialog");
|
||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkWidget *dialog = gtk_file_chooser_dialog_new( "Open Session File", NULL,
|
GtkWidget *dialog = gtk_file_chooser_dialog_new( label.c_str(), NULL,
|
||||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||||
"_Cancel", GTK_RESPONSE_CANCEL,
|
"_Cancel", GTK_RESPONSE_CANCEL,
|
||||||
"_Open", GTK_RESPONSE_ACCEPT, NULL );
|
"_Open", GTK_RESPONSE_ACCEPT, NULL );
|
||||||
@@ -178,7 +312,7 @@ std::string DialogToolkit::openSessionFileDialog(const std::string &path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string DialogToolkit::openMediaFileDialog(const std::string &path)
|
std::string openMediaFileDialog(const std::string &label, const std::string &path)
|
||||||
{
|
{
|
||||||
std::string filename = "";
|
std::string filename = "";
|
||||||
std::string startpath = SystemToolkit::file_exists(path) ? path : SystemToolkit::home_path();
|
std::string startpath = SystemToolkit::file_exists(path) ? path : SystemToolkit::home_path();
|
||||||
@@ -190,18 +324,18 @@ std::string DialogToolkit::openMediaFileDialog(const std::string &path)
|
|||||||
"*.gif", "*.tif", "*.svg" };
|
"*.gif", "*.tif", "*.svg" };
|
||||||
#if USE_TINYFILEDIALOG
|
#if USE_TINYFILEDIALOG
|
||||||
char const * open_file_name;
|
char const * open_file_name;
|
||||||
open_file_name = tinyfd_openFileDialog( "Open Media File", startpath.c_str(), 18, open_pattern, "All supported formats", 0);
|
open_file_name = tinyfd_openFileDialog( label.c_str(), startpath.c_str(), 18, open_pattern, "All supported formats", 0);
|
||||||
|
|
||||||
if (open_file_name)
|
if (open_file_name)
|
||||||
filename = std::string(open_file_name);
|
filename = std::string(open_file_name);
|
||||||
#else
|
#else
|
||||||
|
|
||||||
if (!gtk_init()) {
|
if (!gtk_init()) {
|
||||||
ErrorDialog("Could not initialize GTK+ for dialog");
|
DialogToolkit::ErrorDialog("Could not initialize GTK+ for dialog");
|
||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkWidget *dialog = gtk_file_chooser_dialog_new( "Open Media File", NULL,
|
GtkWidget *dialog = gtk_file_chooser_dialog_new( label.c_str(), NULL,
|
||||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||||
"_Cancel", GTK_RESPONSE_CANCEL,
|
"_Cancel", GTK_RESPONSE_CANCEL,
|
||||||
"_Open", GTK_RESPONSE_ACCEPT, NULL );
|
"_Open", GTK_RESPONSE_ACCEPT, NULL );
|
||||||
@@ -238,24 +372,81 @@ std::string DialogToolkit::openMediaFileDialog(const std::string &path)
|
|||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string DialogToolkit::openFolderDialog(const std::string &path)
|
|
||||||
|
std::string openImageFileDialog(const std::string &label, const std::string &path)
|
||||||
|
{
|
||||||
|
std::string filename = "";
|
||||||
|
std::string startpath = SystemToolkit::file_exists(path) ? path : SystemToolkit::home_path();
|
||||||
|
char const * open_pattern[2] = { "*.jpg", "*.png"};
|
||||||
|
#if USE_TINYFILEDIALOG
|
||||||
|
char const * open_file_name;
|
||||||
|
open_file_name = tinyfd_openFileDialog( label.c_str(), startpath.c_str(), 2, open_pattern, "Image JPG or PNG", 0);
|
||||||
|
|
||||||
|
if (open_file_name)
|
||||||
|
filename = std::string(open_file_name);
|
||||||
|
#else
|
||||||
|
|
||||||
|
if (!gtk_init()) {
|
||||||
|
DialogToolkit::ErrorDialog("Could not initialize GTK+ for dialog");
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget *dialog = gtk_file_chooser_dialog_new( label.c_str(), NULL,
|
||||||
|
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||||
|
"_Cancel", GTK_RESPONSE_CANCEL,
|
||||||
|
"_Open", GTK_RESPONSE_ACCEPT, NULL );
|
||||||
|
|
||||||
|
// set file filters
|
||||||
|
add_filter_file_dialog(dialog, 2, open_pattern, "Image JPG or PNG");
|
||||||
|
add_filter_any_file_dialog(dialog);
|
||||||
|
|
||||||
|
// Set the default path
|
||||||
|
gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER(dialog), startpath.c_str() );
|
||||||
|
|
||||||
|
// ensure front and centered
|
||||||
|
gtk_window_set_keep_above( GTK_WINDOW(dialog), TRUE );
|
||||||
|
if (window_x > 0 && window_y > 0)
|
||||||
|
gtk_window_move( GTK_WINDOW(dialog), window_x, window_y);
|
||||||
|
|
||||||
|
// display and get filename
|
||||||
|
if ( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT ) {
|
||||||
|
|
||||||
|
char *open_file_name = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(dialog) );
|
||||||
|
if (open_file_name)
|
||||||
|
filename = std::string(open_file_name);
|
||||||
|
g_free( open_file_name );
|
||||||
|
}
|
||||||
|
|
||||||
|
// remember position
|
||||||
|
gtk_window_get_position( GTK_WINDOW(dialog), &window_x, &window_y);
|
||||||
|
|
||||||
|
// done
|
||||||
|
gtk_widget_destroy(dialog);
|
||||||
|
wait_for_event();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string openFolderDialog(const std::string &label, const std::string &path)
|
||||||
{
|
{
|
||||||
std::string foldername = "";
|
std::string foldername = "";
|
||||||
std::string startpath = SystemToolkit::file_exists(path) ? path : SystemToolkit::home_path();
|
std::string startpath = SystemToolkit::file_exists(path) ? path : SystemToolkit::home_path();
|
||||||
|
|
||||||
#if USE_TINYFILEDIALOG
|
#if USE_TINYFILEDIALOG
|
||||||
char const * open_folder_name;
|
char const * open_folder_name;
|
||||||
open_folder_name = tinyfd_selectFolderDialog("Select folder", startpath.c_str());
|
open_folder_name = tinyfd_selectFolderDialog(label.c_str(), startpath.c_str());
|
||||||
|
|
||||||
if (open_folder_name)
|
if (open_folder_name)
|
||||||
foldername = std::string(open_folder_name);
|
foldername = std::string(open_folder_name);
|
||||||
#else
|
#else
|
||||||
if (!gtk_init()) {
|
if (!gtk_init()) {
|
||||||
ErrorDialog("Could not initialize GTK+ for dialog");
|
DialogToolkit::ErrorDialog("Could not initialize GTK+ for dialog");
|
||||||
return foldername;
|
return foldername;
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkWidget *dialog = gtk_file_chooser_dialog_new( "Select folder", NULL,
|
GtkWidget *dialog = gtk_file_chooser_dialog_new( label.c_str(), NULL,
|
||||||
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
|
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
|
||||||
"_Cancel", GTK_RESPONSE_CANCEL,
|
"_Cancel", GTK_RESPONSE_CANCEL,
|
||||||
"_Select", GTK_RESPONSE_ACCEPT, NULL );
|
"_Select", GTK_RESPONSE_ACCEPT, NULL );
|
||||||
@@ -290,7 +481,7 @@ std::string DialogToolkit::openFolderDialog(const std::string &path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::list<std::string> DialogToolkit::selectImagesFileDialog(const std::string &path)
|
std::list<std::string> selectImagesFileDialog(const std::string &label,const std::string &path)
|
||||||
{
|
{
|
||||||
std::list<std::string> files;
|
std::list<std::string> files;
|
||||||
|
|
||||||
@@ -299,7 +490,7 @@ std::list<std::string> DialogToolkit::selectImagesFileDialog(const std::string &
|
|||||||
|
|
||||||
#if USE_TINYFILEDIALOG
|
#if USE_TINYFILEDIALOG
|
||||||
char const * open_file_names;
|
char const * open_file_names;
|
||||||
open_file_names = tinyfd_openFileDialog( "Select images", startpath.c_str(), 6, open_pattern, "Images", 1);
|
open_file_names = tinyfd_openFileDialog(label.c_str(), startpath.c_str(), 6, open_pattern, "Images", 1);
|
||||||
|
|
||||||
if (open_file_names) {
|
if (open_file_names) {
|
||||||
|
|
||||||
@@ -325,11 +516,11 @@ std::list<std::string> DialogToolkit::selectImagesFileDialog(const std::string &
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
if (!gtk_init()) {
|
if (!gtk_init()) {
|
||||||
ErrorDialog("Could not initialize GTK+ for dialog");
|
DialogToolkit::ErrorDialog("Could not initialize GTK+ for dialog");
|
||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkWidget *dialog = gtk_file_chooser_dialog_new( "Select images", NULL,
|
GtkWidget *dialog = gtk_file_chooser_dialog_new( label.c_str(), NULL,
|
||||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||||
"_Cancel", GTK_RESPONSE_CANCEL,
|
"_Cancel", GTK_RESPONSE_CANCEL,
|
||||||
"_Open", GTK_RESPONSE_ACCEPT, NULL );
|
"_Open", GTK_RESPONSE_ACCEPT, NULL );
|
||||||
|
|||||||
@@ -3,23 +3,80 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <vector>
|
||||||
|
#include <thread>
|
||||||
|
#include <future>
|
||||||
|
|
||||||
|
|
||||||
namespace DialogToolkit
|
namespace DialogToolkit
|
||||||
{
|
{
|
||||||
|
|
||||||
std::string saveSessionFileDialog(const std::string &path);
|
|
||||||
|
|
||||||
std::string openSessionFileDialog(const std::string &path);
|
|
||||||
|
|
||||||
std::string openMediaFileDialog(const std::string &path);
|
|
||||||
|
|
||||||
std::string openFolderDialog(const std::string &path);
|
|
||||||
|
|
||||||
std::list<std::string> selectImagesFileDialog(const std::string &path);
|
|
||||||
|
|
||||||
void ErrorDialog(const char* message);
|
void ErrorDialog(const char* message);
|
||||||
|
|
||||||
|
class FileDialog
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
std::string id_;
|
||||||
|
std::string directory_;
|
||||||
|
std::string path_;
|
||||||
|
std::vector< std::future<std::string> >promises_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FileDialog(const std::string &name);
|
||||||
|
|
||||||
|
virtual void open() = 0;
|
||||||
|
virtual bool closed();
|
||||||
|
inline std::string path() const { return path_; }
|
||||||
|
|
||||||
|
static bool pending;
|
||||||
|
};
|
||||||
|
|
||||||
|
class OpenImageDialog : public FileDialog
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OpenImageDialog(const std::string &name) : FileDialog(name) {}
|
||||||
|
void open();
|
||||||
|
};
|
||||||
|
|
||||||
|
class OpenSessionDialog : public FileDialog
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OpenSessionDialog(const std::string &name) : FileDialog(name) {}
|
||||||
|
void open();
|
||||||
|
};
|
||||||
|
|
||||||
|
class OpenMediaDialog : public FileDialog
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OpenMediaDialog(const std::string &name) : FileDialog(name) {}
|
||||||
|
void open();
|
||||||
|
};
|
||||||
|
|
||||||
|
class SaveSessionDialog : public FileDialog
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SaveSessionDialog(const std::string &name) : FileDialog(name) {}
|
||||||
|
void open();
|
||||||
|
};
|
||||||
|
|
||||||
|
class OpenFolderDialog : public FileDialog
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OpenFolderDialog(const std::string &name) : FileDialog(name) {}
|
||||||
|
void open();
|
||||||
|
};
|
||||||
|
|
||||||
|
class MultipleImagesDialog : public FileDialog
|
||||||
|
{
|
||||||
|
std::list<std::string> pathlist_;
|
||||||
|
std::vector< std::future< std::list<std::string> > > promisedlist_;
|
||||||
|
public:
|
||||||
|
MultipleImagesDialog(const std::string &name) : FileDialog(name) {}
|
||||||
|
void open();
|
||||||
|
bool closed() override;
|
||||||
|
inline std::list<std::string> images() const { return pathlist_; }
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -238,7 +238,6 @@ Source * Mixer::createSourceFile(const std::string &path)
|
|||||||
|
|
||||||
// remember in recent media
|
// remember in recent media
|
||||||
Settings::application.recentImport.push(path);
|
Settings::application.recentImport.push(path);
|
||||||
Settings::application.recentImport.path = SystemToolkit::path_filename(path);
|
|
||||||
|
|
||||||
// propose a new name based on uri
|
// propose a new name based on uri
|
||||||
s->setName(SystemToolkit::base_filename(path));
|
s->setName(SystemToolkit::base_filename(path));
|
||||||
@@ -269,9 +268,6 @@ Source * Mixer::createSourceMultifile(const std::list<std::string> &list_files,
|
|||||||
mfs->setSequence(sequence, fps);
|
mfs->setSequence(sequence, fps);
|
||||||
s = mfs;
|
s = mfs;
|
||||||
|
|
||||||
// remember in recent media
|
|
||||||
Settings::application.recentImport.path = SystemToolkit::path_filename(list_files.front());
|
|
||||||
|
|
||||||
// propose a new name
|
// propose a new name
|
||||||
s->setName( SystemToolkit::base_filename( BaseToolkit::common_prefix(list_files) ) );
|
s->setName( SystemToolkit::base_filename( BaseToolkit::common_prefix(list_files) ) );
|
||||||
}
|
}
|
||||||
|
|||||||
43
Settings.cpp
43
Settings.cpp
@@ -173,13 +173,14 @@ void Settings::Save()
|
|||||||
{
|
{
|
||||||
XMLElement *recent = xmlDoc.NewElement( "Recent" );
|
XMLElement *recent = xmlDoc.NewElement( "Recent" );
|
||||||
|
|
||||||
|
// recent session filenames
|
||||||
XMLElement *recentsession = xmlDoc.NewElement( "Session" );
|
XMLElement *recentsession = xmlDoc.NewElement( "Session" );
|
||||||
recentsession->SetAttribute("path", application.recentSessions.path.c_str());
|
recentsession->SetAttribute("path", application.recentSessions.path.c_str());
|
||||||
recentsession->SetAttribute("autoload", application.recentSessions.load_at_start);
|
recentsession->SetAttribute("autoload", application.recentSessions.load_at_start);
|
||||||
recentsession->SetAttribute("autosave", application.recentSessions.save_on_exit);
|
recentsession->SetAttribute("autosave", application.recentSessions.save_on_exit);
|
||||||
recentsession->SetAttribute("valid", application.recentSessions.front_is_valid);
|
recentsession->SetAttribute("valid", application.recentSessions.front_is_valid);
|
||||||
for(auto it = application.recentSessions.filenames.begin();
|
for(auto it = application.recentSessions.filenames.cbegin();
|
||||||
it != application.recentSessions.filenames.end(); ++it) {
|
it != application.recentSessions.filenames.cend(); ++it) {
|
||||||
XMLElement *fileNode = xmlDoc.NewElement("path");
|
XMLElement *fileNode = xmlDoc.NewElement("path");
|
||||||
XMLText *text = xmlDoc.NewText( (*it).c_str() );
|
XMLText *text = xmlDoc.NewText( (*it).c_str() );
|
||||||
fileNode->InsertEndChild( text );
|
fileNode->InsertEndChild( text );
|
||||||
@@ -187,9 +188,10 @@ void Settings::Save()
|
|||||||
};
|
};
|
||||||
recent->InsertEndChild(recentsession);
|
recent->InsertEndChild(recentsession);
|
||||||
|
|
||||||
|
// recent session folders
|
||||||
XMLElement *recentfolder = xmlDoc.NewElement( "Folder" );
|
XMLElement *recentfolder = xmlDoc.NewElement( "Folder" );
|
||||||
for(auto it = application.recentFolders.filenames.begin();
|
for(auto it = application.recentFolders.filenames.cbegin();
|
||||||
it != application.recentFolders.filenames.end(); ++it) {
|
it != application.recentFolders.filenames.cend(); ++it) {
|
||||||
XMLElement *fileNode = xmlDoc.NewElement("path");
|
XMLElement *fileNode = xmlDoc.NewElement("path");
|
||||||
XMLText *text = xmlDoc.NewText( (*it).c_str() );
|
XMLText *text = xmlDoc.NewText( (*it).c_str() );
|
||||||
fileNode->InsertEndChild( text );
|
fileNode->InsertEndChild( text );
|
||||||
@@ -197,10 +199,11 @@ void Settings::Save()
|
|||||||
};
|
};
|
||||||
recent->InsertEndChild(recentfolder);
|
recent->InsertEndChild(recentfolder);
|
||||||
|
|
||||||
|
// recent media uri
|
||||||
XMLElement *recentmedia = xmlDoc.NewElement( "Import" );
|
XMLElement *recentmedia = xmlDoc.NewElement( "Import" );
|
||||||
recentmedia->SetAttribute("path", application.recentImport.path.c_str());
|
recentmedia->SetAttribute("path", application.recentImport.path.c_str());
|
||||||
for(auto it = application.recentImport.filenames.begin();
|
for(auto it = application.recentImport.filenames.cbegin();
|
||||||
it != application.recentImport.filenames.end(); ++it) {
|
it != application.recentImport.filenames.cend(); ++it) {
|
||||||
XMLElement *fileNode = xmlDoc.NewElement("path");
|
XMLElement *fileNode = xmlDoc.NewElement("path");
|
||||||
XMLText *text = xmlDoc.NewText( (*it).c_str() );
|
XMLText *text = xmlDoc.NewText( (*it).c_str() );
|
||||||
fileNode->InsertEndChild( text );
|
fileNode->InsertEndChild( text );
|
||||||
@@ -208,10 +211,21 @@ void Settings::Save()
|
|||||||
}
|
}
|
||||||
recent->InsertEndChild(recentmedia);
|
recent->InsertEndChild(recentmedia);
|
||||||
|
|
||||||
|
// recent dialog path
|
||||||
|
XMLElement *recentdialogpath = xmlDoc.NewElement( "Dialog" );
|
||||||
|
for(auto it = application.dialogRecentFolder.cbegin();
|
||||||
|
it != application.dialogRecentFolder.cend(); ++it) {
|
||||||
|
XMLElement *pathNode = xmlDoc.NewElement("path");
|
||||||
|
pathNode->SetAttribute("label", (*it).first.c_str() );
|
||||||
|
XMLText *text = xmlDoc.NewText( (*it).second.c_str() );
|
||||||
|
pathNode->InsertEndChild( text );
|
||||||
|
recentdialogpath->InsertFirstChild(pathNode);
|
||||||
|
}
|
||||||
|
recent->InsertEndChild(recentdialogpath);
|
||||||
|
|
||||||
pRoot->InsertEndChild(recent);
|
pRoot->InsertEndChild(recent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// First save : create filename
|
// First save : create filename
|
||||||
if (settingsFilename.empty())
|
if (settingsFilename.empty())
|
||||||
settingsFilename = SystemToolkit::full_filename(SystemToolkit::settings_path(), APP_SETTINGS);
|
settingsFilename = SystemToolkit::full_filename(SystemToolkit::settings_path(), APP_SETTINGS);
|
||||||
@@ -459,6 +473,21 @@ void Settings::Load()
|
|||||||
application.recentImport.push( std::string (p) );
|
application.recentImport.push( std::string (p) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// recent dialog path
|
||||||
|
XMLElement * pDialog = pElement->FirstChildElement("Dialog");
|
||||||
|
if (pDialog)
|
||||||
|
{
|
||||||
|
application.dialogRecentFolder.clear();
|
||||||
|
XMLElement* path = pDialog->FirstChildElement("path");
|
||||||
|
for( ; path ; path = path->NextSiblingElement())
|
||||||
|
{
|
||||||
|
const char *l = path->Attribute("label");
|
||||||
|
const char *p = path->GetText();
|
||||||
|
if (l && p)
|
||||||
|
application.dialogRecentFolder[ std::string(l)] = std::string (p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,6 @@ struct ViewConfig
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define RECORD_MAX_TIMEOUT 301000
|
|
||||||
|
|
||||||
struct RecordConfig
|
struct RecordConfig
|
||||||
{
|
{
|
||||||
@@ -211,6 +210,7 @@ struct Application
|
|||||||
History recentSessions;
|
History recentSessions;
|
||||||
History recentFolders;
|
History recentFolders;
|
||||||
History recentImport;
|
History recentImport;
|
||||||
|
std::map< std::string, std::string > dialogRecentFolder;
|
||||||
|
|
||||||
Application() : fresh_start(false), instance_id(0), name(APP_NAME), executable(APP_NAME) {
|
Application() : fresh_start(false), instance_id(0), name(APP_NAME), executable(APP_NAME) {
|
||||||
scale = 1.f;
|
scale = 1.f;
|
||||||
|
|||||||
@@ -81,17 +81,8 @@ void ShowSandbox(bool* p_open);
|
|||||||
void SetMouseCursor(ImVec2 mousepos, View::Cursor c = View::Cursor());
|
void SetMouseCursor(ImVec2 mousepos, View::Cursor c = View::Cursor());
|
||||||
void SetNextWindowVisible(ImVec2 pos, ImVec2 size, float margin = 180.f);
|
void SetNextWindowVisible(ImVec2 pos, ImVec2 size, float margin = 180.f);
|
||||||
|
|
||||||
// static objects for multithreaded file dialog
|
// globals
|
||||||
const std::chrono::milliseconds timeout = std::chrono::milliseconds(4);
|
const std::chrono::milliseconds timeout = std::chrono::milliseconds(4);
|
||||||
static std::atomic<bool> fileDialogPending_ = false;
|
|
||||||
|
|
||||||
std::vector< std::future<std::string> > saveSessionFileDialogs;
|
|
||||||
std::vector< std::future<std::string> > openSessionFileDialogs;
|
|
||||||
std::vector< std::future<std::string> > importSessionFileDialogs;
|
|
||||||
std::vector< std::future<std::string> > fileImportFileDialogs;
|
|
||||||
std::vector< std::future<std::string> > recentFolderFileDialogs;
|
|
||||||
std::vector< std::future<std::string> > recordFolderFileDialogs;
|
|
||||||
|
|
||||||
std::vector< std::future<FrameGrabber *> > _video_recorders;
|
std::vector< std::future<FrameGrabber *> > _video_recorders;
|
||||||
FrameGrabber *delayTrigger(FrameGrabber *g, std::chrono::milliseconds delay) {
|
FrameGrabber *delayTrigger(FrameGrabber *g, std::chrono::milliseconds delay) {
|
||||||
std::this_thread::sleep_for (delay);
|
std::this_thread::sleep_for (delay);
|
||||||
@@ -119,6 +110,10 @@ UserInterface::UserInterface()
|
|||||||
#if defined(LINUX)
|
#if defined(LINUX)
|
||||||
webcam_emulator_ = nullptr;
|
webcam_emulator_ = nullptr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
sessionopendialog = nullptr;
|
||||||
|
sessionimportdialog = nullptr;
|
||||||
|
sessionsavedialog = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UserInterface::Init()
|
bool UserInterface::Init()
|
||||||
@@ -181,6 +176,11 @@ bool UserInterface::Init()
|
|||||||
std::sprintf(inifilepath, "%s", inifile.c_str() );
|
std::sprintf(inifilepath, "%s", inifile.c_str() );
|
||||||
io.IniFilename = inifilepath;
|
io.IniFilename = inifilepath;
|
||||||
|
|
||||||
|
// init dialogs
|
||||||
|
sessionopendialog = new DialogToolkit::OpenSessionDialog("Open Session");
|
||||||
|
sessionsavedialog = new DialogToolkit::SaveSessionDialog("Save Session");
|
||||||
|
sessionimportdialog = new DialogToolkit::OpenSessionDialog("Import Session") ;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -664,21 +664,18 @@ void UserInterface::handleMouse()
|
|||||||
|
|
||||||
void UserInterface::selectSaveFilename()
|
void UserInterface::selectSaveFilename()
|
||||||
{
|
{
|
||||||
// launch file dialog to select a session filename to save
|
if (sessionsavedialog)
|
||||||
if ( saveSessionFileDialogs.empty()) {
|
sessionsavedialog->open();
|
||||||
saveSessionFileDialogs.emplace_back( std::async(std::launch::async, DialogToolkit::saveSessionFileDialog, Settings::application.recentSessions.path) );
|
|
||||||
fileDialogPending_ = true;
|
|
||||||
}
|
|
||||||
navigator.hidePannel();
|
navigator.hidePannel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserInterface::selectOpenFilename()
|
void UserInterface::selectOpenFilename()
|
||||||
{
|
{
|
||||||
// launch file dialog to select a session filename to open
|
// launch file dialog to select a session filename to open
|
||||||
if ( openSessionFileDialogs.empty()) {
|
if (sessionopendialog)
|
||||||
openSessionFileDialogs.emplace_back( std::async(std::launch::async, DialogToolkit::openSessionFileDialog, Settings::application.recentSessions.path) );
|
sessionopendialog->open();
|
||||||
fileDialogPending_ = true;
|
|
||||||
}
|
|
||||||
navigator.hidePannel();
|
navigator.hidePannel();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -694,54 +691,18 @@ void UserInterface::NewFrame()
|
|||||||
handleMouse();
|
handleMouse();
|
||||||
handleScreenshot();
|
handleScreenshot();
|
||||||
|
|
||||||
// handle FileDialog
|
// handle FileDialogs
|
||||||
|
if (sessionopendialog && sessionopendialog->closed() && !sessionopendialog->path().empty())
|
||||||
|
Mixer::manager().open(sessionopendialog->path());
|
||||||
|
|
||||||
// if a file dialog future was registered
|
if (sessionimportdialog && sessionimportdialog->closed() && !sessionimportdialog->path().empty())
|
||||||
if ( !openSessionFileDialogs.empty() ) {
|
Mixer::manager().import(sessionimportdialog->path());
|
||||||
// check that file dialog thread finished
|
|
||||||
if (openSessionFileDialogs.back().wait_for(timeout) == std::future_status::ready ) {
|
if (sessionsavedialog && sessionsavedialog->closed() && !sessionsavedialog->path().empty())
|
||||||
// get the filename from this file dialog
|
Mixer::manager().saveas(sessionsavedialog->path());
|
||||||
std::string open_filename = openSessionFileDialogs.back().get();
|
|
||||||
if (!open_filename.empty()) {
|
|
||||||
Mixer::manager().open(open_filename);
|
|
||||||
Settings::application.recentSessions.path = SystemToolkit::path_filename(open_filename);
|
|
||||||
}
|
|
||||||
// done with this file dialog
|
|
||||||
openSessionFileDialogs.pop_back();
|
|
||||||
fileDialogPending_ = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( !importSessionFileDialogs.empty() ) {
|
|
||||||
// check that file dialog thread finished
|
|
||||||
if (importSessionFileDialogs.back().wait_for(timeout) == std::future_status::ready ) {
|
|
||||||
// get the filename from this file dialog
|
|
||||||
std::string open_filename = importSessionFileDialogs.back().get();
|
|
||||||
if (!open_filename.empty()) {
|
|
||||||
Mixer::manager().import(open_filename);
|
|
||||||
Settings::application.recentSessions.path = SystemToolkit::path_filename(open_filename);
|
|
||||||
}
|
|
||||||
// done with this file dialog
|
|
||||||
importSessionFileDialogs.pop_back();
|
|
||||||
fileDialogPending_ = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( !saveSessionFileDialogs.empty() ) {
|
|
||||||
// check that file dialog thread finished
|
|
||||||
if (saveSessionFileDialogs.back().wait_for(timeout) == std::future_status::ready ) {
|
|
||||||
// get the filename from this file dialog
|
|
||||||
std::string save_filename = saveSessionFileDialogs.back().get();
|
|
||||||
if (!save_filename.empty()) {
|
|
||||||
Mixer::manager().saveas(save_filename);
|
|
||||||
Settings::application.recentSessions.path = SystemToolkit::path_filename(save_filename);
|
|
||||||
}
|
|
||||||
// done with this file dialog
|
|
||||||
saveSessionFileDialogs.pop_back();
|
|
||||||
fileDialogPending_ = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// overlay to ensure file dialog is modal
|
// overlay to ensure file dialog is modal
|
||||||
if (fileDialogPending_){
|
if (DialogToolkit::FileDialog::pending){
|
||||||
ImGui::OpenPopup("Busy");
|
ImGui::OpenPopup("Busy");
|
||||||
if (ImGui::BeginPopupModal("Busy", NULL, ImGuiWindowFlags_AlwaysAutoResize))
|
if (ImGui::BeginPopupModal("Busy", NULL, ImGuiWindowFlags_AlwaysAutoResize))
|
||||||
{
|
{
|
||||||
@@ -898,10 +859,11 @@ void UserInterface::showMenuFile()
|
|||||||
|
|
||||||
if (ImGui::MenuItem( ICON_FA_FILE_EXPORT " Import")) {
|
if (ImGui::MenuItem( ICON_FA_FILE_EXPORT " Import")) {
|
||||||
// launch file dialog to open a session file
|
// launch file dialog to open a session file
|
||||||
if ( importSessionFileDialogs.empty()) {
|
sessionimportdialog->open();
|
||||||
importSessionFileDialogs.emplace_back( std::async(std::launch::async, DialogToolkit::openSessionFileDialog, Settings::application.recentSessions.path) );
|
// if ( importSessionFileDialogs.empty()) {
|
||||||
fileDialogPending_ = true;
|
// importSessionFileDialogs.emplace_back( std::async(std::launch::async, DialogToolkit::openSessionFileDialog, Settings::application.recentSessions.path) );
|
||||||
}
|
// fileDialogPending_ = true;
|
||||||
|
// }
|
||||||
navigator.hidePannel();
|
navigator.hidePannel();
|
||||||
}
|
}
|
||||||
if (ImGui::MenuItem( ICON_FA_FILE_DOWNLOAD " Save", CTRL_MOD "S")) {
|
if (ImGui::MenuItem( ICON_FA_FILE_DOWNLOAD " Save", CTRL_MOD "S")) {
|
||||||
@@ -1029,7 +991,11 @@ void UserInterface::RenderPreview()
|
|||||||
bool openInitializeSystemLoopback = false;
|
bool openInitializeSystemLoopback = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct CustomConstraints // Helper functions for aspect-ratio constraints
|
// recording location
|
||||||
|
static DialogToolkit::OpenFolderDialog recordFolderDialog("Recording Location");
|
||||||
|
|
||||||
|
// Helper functions for aspect-ratio constraints
|
||||||
|
struct CustomConstraints
|
||||||
{
|
{
|
||||||
static void AspectRatio(ImGuiSizeCallbackData* data) {
|
static void AspectRatio(ImGuiSizeCallbackData* data) {
|
||||||
float *ar = (float*) data->UserData;
|
float *ar = (float*) data->UserData;
|
||||||
@@ -1063,16 +1029,9 @@ void UserInterface::RenderPreview()
|
|||||||
preview_window_size = ImGui::GetWindowSize();
|
preview_window_size = ImGui::GetWindowSize();
|
||||||
|
|
||||||
// return from thread for folder openning
|
// return from thread for folder openning
|
||||||
if ( !recordFolderFileDialogs.empty() ) {
|
if (recordFolderDialog.closed() && !recordFolderDialog.path().empty())
|
||||||
// check that file dialog thread finished
|
// get the folder from this file dialog
|
||||||
if (recordFolderFileDialogs.back().wait_for(timeout) == std::future_status::ready ) {
|
Settings::application.record.path = recordFolderDialog.path();
|
||||||
// get the folder from this file dialog
|
|
||||||
Settings::application.record.path = recordFolderFileDialogs.back().get();
|
|
||||||
// done with this file dialog
|
|
||||||
recordFolderFileDialogs.pop_back();
|
|
||||||
fileDialogPending_ = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// menu (no title bar)
|
// menu (no title bar)
|
||||||
if (ImGui::BeginMenuBar())
|
if (ImGui::BeginMenuBar())
|
||||||
@@ -1169,12 +1128,8 @@ void UserInterface::RenderPreview()
|
|||||||
int selected_path = 0;
|
int selected_path = 0;
|
||||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||||
ImGui::Combo("Path", &selected_path, name_path, 4);
|
ImGui::Combo("Path", &selected_path, name_path, 4);
|
||||||
if (selected_path > 2) {
|
if (selected_path > 2)
|
||||||
if (recordFolderFileDialogs.empty()) {
|
recordFolderDialog.open();
|
||||||
recordFolderFileDialogs.emplace_back( std::async(std::launch::async, DialogToolkit::openFolderDialog, Settings::application.record.path) );
|
|
||||||
fileDialogPending_ = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (selected_path > 1)
|
else if (selected_path > 1)
|
||||||
Settings::application.record.path = SystemToolkit::path_filename( Mixer::manager().session()->filename() );
|
Settings::application.record.path = SystemToolkit::path_filename( Mixer::manager().session()->filename() );
|
||||||
else if (selected_path > 0)
|
else if (selected_path > 0)
|
||||||
@@ -3709,36 +3664,27 @@ void Navigator::RenderNewPannel()
|
|||||||
// File Source creation
|
// File Source creation
|
||||||
if (Settings::application.source.new_type == 0) {
|
if (Settings::application.source.new_type == 0) {
|
||||||
|
|
||||||
|
static DialogToolkit::OpenMediaDialog fileimportdialog("Open Media");
|
||||||
|
|
||||||
// clic button to load file
|
// clic button to load file
|
||||||
if ( ImGui::Button( ICON_FA_FILE_EXPORT " Open media", ImVec2(ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN, 0)) ) {
|
if ( ImGui::Button( ICON_FA_FILE_EXPORT " Open media", ImVec2(ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN, 0)) )
|
||||||
// launch async call to file dialog and get its future.
|
fileimportdialog.open();
|
||||||
if (fileImportFileDialogs.empty()) {
|
|
||||||
fileImportFileDialogs.emplace_back( std::async(std::launch::async, DialogToolkit::openMediaFileDialog, Settings::application.recentImport.path) );
|
|
||||||
fileDialogPending_ = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Indication
|
// Indication
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGuiToolkit::HelpMarker("Create a source from a file:\n- video (*.mpg, *mov, *.avi, etc.)\n- image (*.jpg, *.png, etc.)\n- vector graphics (*.svg)\n- vimix session (*.mix)\n\n(Equivalent to dropping the file in the workspace)");
|
ImGuiToolkit::HelpMarker("Create a source from a file:\n- video (*.mpg, *mov, *.avi, etc.)\n- image (*.jpg, *.png, etc.)\n- vector graphics (*.svg)\n- vimix session (*.mix)\n\n(Equivalent to dropping the file in the workspace)");
|
||||||
|
|
||||||
// if a file dialog future was registered
|
// get media file if dialog finished
|
||||||
if ( !fileImportFileDialogs.empty() ) {
|
if (fileimportdialog.closed()){
|
||||||
// check that file dialog thread finished
|
// get the filename from this file dialog
|
||||||
if (fileImportFileDialogs.back().wait_for(timeout) == std::future_status::ready ) {
|
std::string open_filename = fileimportdialog.path();
|
||||||
// get the filename from this file dialog
|
// create a source with this file
|
||||||
std::string open_filename = fileImportFileDialogs.back().get();
|
if (open_filename.empty()) {
|
||||||
// done with this file dialog
|
Log::Notify("No file selected.");
|
||||||
fileImportFileDialogs.pop_back();
|
} else {
|
||||||
fileDialogPending_ = false;
|
std::string label = BaseToolkit::transliterate( open_filename );
|
||||||
// create a source with this file
|
label = BaseToolkit::trunc_string(label, 35);
|
||||||
if (open_filename.empty()) {
|
new_source_preview_.setSource( Mixer::manager().createSourceFile(open_filename), label);
|
||||||
Log::Notify("No file selected.");
|
|
||||||
} else {
|
|
||||||
std::string label = BaseToolkit::transliterate( open_filename );
|
|
||||||
label = BaseToolkit::trunc_string(label, 35);
|
|
||||||
new_source_preview_.setSource( Mixer::manager().createSourceFile(open_filename), label);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3765,15 +3711,12 @@ void Navigator::RenderNewPannel()
|
|||||||
else if (Settings::application.source.new_type == 1){
|
else if (Settings::application.source.new_type == 1){
|
||||||
|
|
||||||
bool update_new_source = false;
|
bool update_new_source = false;
|
||||||
static std::vector< std::future< std::list<std::string> > > _selectedImagesFileDialogs;
|
static DialogToolkit::MultipleImagesDialog _selectImagesDialog("Select Images");
|
||||||
|
|
||||||
// clic button to load file
|
// clic button to load file
|
||||||
if ( ImGui::Button( ICON_FA_IMAGES " Open images", ImVec2(ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN, 0)) ) {
|
if ( ImGui::Button( ICON_FA_IMAGES " Open images", ImVec2(ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN, 0)) ) {
|
||||||
_selectedFiles.clear();
|
_selectedFiles.clear();
|
||||||
if (_selectedImagesFileDialogs.empty()) {
|
_selectImagesDialog.open();
|
||||||
_selectedImagesFileDialogs.emplace_back( std::async(std::launch::async, DialogToolkit::selectImagesFileDialog, Settings::application.recentImport.path) );
|
|
||||||
fileDialogPending_ = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Indication
|
// Indication
|
||||||
@@ -3781,20 +3724,12 @@ void Navigator::RenderNewPannel()
|
|||||||
ImGuiToolkit::HelpMarker("Create a source from a sequence of numbered images.");
|
ImGuiToolkit::HelpMarker("Create a source from a sequence of numbered images.");
|
||||||
|
|
||||||
// return from thread for folder openning
|
// return from thread for folder openning
|
||||||
if ( !_selectedImagesFileDialogs.empty() ) {
|
if (_selectImagesDialog.closed()) {
|
||||||
// check that file dialog thread finished
|
_selectedFiles = _selectImagesDialog.images();
|
||||||
if (_selectedImagesFileDialogs.back().wait_for(timeout) == std::future_status::ready ) {
|
if (_selectedFiles.empty())
|
||||||
// get the filenames from this file dialog
|
Log::Notify("No file selected.");
|
||||||
_selectedFiles = _selectedImagesFileDialogs.back().get();
|
// ask to reload the preview
|
||||||
if (_selectedFiles.empty()) {
|
update_new_source = true;
|
||||||
Log::Notify("No file selected.");
|
|
||||||
}
|
|
||||||
// done with this file dialog
|
|
||||||
_selectedImagesFileDialogs.pop_back();
|
|
||||||
fileDialogPending_ = false;
|
|
||||||
// ask to reload the preview
|
|
||||||
update_new_source = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// multiple files selected
|
// multiple files selected
|
||||||
@@ -3980,6 +3915,7 @@ void Navigator::RenderMainPannelVimix()
|
|||||||
ImGui::Text("Sessions");
|
ImGui::Text("Sessions");
|
||||||
static bool selection_session_mode_changed = true;
|
static bool selection_session_mode_changed = true;
|
||||||
static int selection_session_mode = 0;
|
static int selection_session_mode = 0;
|
||||||
|
static DialogToolkit::OpenFolderDialog customFolder("Open Folder");
|
||||||
|
|
||||||
// Show combo box of quick selection modes
|
// Show combo box of quick selection modes
|
||||||
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||||
@@ -4004,32 +3940,17 @@ void Navigator::RenderMainPannelVimix()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Option 2 : add a folder
|
// Option 2 : add a folder
|
||||||
if (ImGui::Selectable( ICON_FA_FOLDER_PLUS " Add Folder") ){
|
if (ImGui::Selectable( ICON_FA_FOLDER_PLUS " Add Folder") )
|
||||||
if (recentFolderFileDialogs.empty()) {
|
customFolder.open();
|
||||||
recentFolderFileDialogs.emplace_back( std::async(std::launch::async, DialogToolkit::openFolderDialog, Settings::application.recentFolders.path) );
|
|
||||||
fileDialogPending_ = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::EndCombo();
|
ImGui::EndCombo();
|
||||||
}
|
}
|
||||||
|
|
||||||
// return from thread for folder openning
|
// return from thread for folder openning
|
||||||
if ( !recentFolderFileDialogs.empty() ) {
|
if (customFolder.closed() && !customFolder.path().empty()) {
|
||||||
// check that file dialog thread finished
|
Settings::application.recentFolders.push(customFolder.path());
|
||||||
if (recentFolderFileDialogs.back().wait_for(timeout) == std::future_status::ready ) {
|
Settings::application.recentFolders.path.assign(customFolder.path());
|
||||||
// get the filename from this file dialog
|
selection_session_mode = 1;
|
||||||
std::string foldername = recentFolderFileDialogs.back().get();
|
selection_session_mode_changed = true;
|
||||||
if (!foldername.empty()) {
|
|
||||||
Settings::application.recentFolders.push(foldername);
|
|
||||||
Settings::application.recentFolders.path.assign(foldername);
|
|
||||||
selection_session_mode = 1;
|
|
||||||
selection_session_mode_changed = true;
|
|
||||||
}
|
|
||||||
// done with this file dialog
|
|
||||||
recentFolderFileDialogs.pop_back();
|
|
||||||
fileDialogPending_ = false;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// icon to clear list
|
// icon to clear list
|
||||||
@@ -4949,6 +4870,19 @@ void ShowSandbox(bool* p_open)
|
|||||||
ImGui::Text("Testing sandox");
|
ImGui::Text("Testing sandox");
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
|
ImGui::Text("IMAGE of Font");
|
||||||
|
|
||||||
|
ImGuiToolkit::ImageGlyph(ImGuiToolkit::FONT_DEFAULT, 'v');
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGuiToolkit::ImageGlyph(ImGuiToolkit::FONT_BOLD, 'i');
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGuiToolkit::ImageGlyph(ImGuiToolkit::FONT_ITALIC, 'm');
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGuiToolkit::ImageGlyph(ImGuiToolkit::FONT_MONO, 'i');
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGuiToolkit::ImageGlyph(ImGuiToolkit::FONT_LARGE, 'x');
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
ImGui::Text("Source list");
|
ImGui::Text("Source list");
|
||||||
Session *se = Mixer::manager().session();
|
Session *se = Mixer::manager().session();
|
||||||
for (auto sit = se->begin(); sit != se->end(); ++sit) {
|
for (auto sit = se->begin(); sit != se->end(); ++sit) {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include "SourceList.h"
|
#include "SourceList.h"
|
||||||
#include "InfoVisitor.h"
|
#include "InfoVisitor.h"
|
||||||
|
#include "DialogToolkit.h"
|
||||||
|
|
||||||
struct ImVec2;
|
struct ImVec2;
|
||||||
class MediaPlayer;
|
class MediaPlayer;
|
||||||
@@ -183,6 +184,11 @@ class UserInterface
|
|||||||
FrameGrabber *webcam_emulator_;
|
FrameGrabber *webcam_emulator_;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Dialogs
|
||||||
|
DialogToolkit::OpenSessionDialog *sessionopendialog;
|
||||||
|
DialogToolkit::OpenSessionDialog *sessionimportdialog;
|
||||||
|
DialogToolkit::SaveSessionDialog *sessionsavedialog;
|
||||||
|
|
||||||
// Private Constructor
|
// Private Constructor
|
||||||
UserInterface();
|
UserInterface();
|
||||||
UserInterface(UserInterface const& copy) = delete;
|
UserInterface(UserInterface const& copy) = delete;
|
||||||
|
|||||||
Reference in New Issue
Block a user