mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-05 23:40:02 +01:00
621 lines
21 KiB
C++
621 lines
21 KiB
C++
/*
|
|
* This file is part of vimix - video live mixer
|
|
*
|
|
* **Copyright** (C) 2020-2021 Bruno Herbelin <bruno.herbelin@gmail.com>
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
**/
|
|
|
|
|
|
// multiplatform implementation of system dialogs
|
|
//
|
|
// 'TinyFileDialog' from https://github.com/native-toolkit/tinyfiledialogs.git
|
|
// is the prefered solution, but it is not compatible with linux snap packaging
|
|
// because of 'zenity' access rights nightmare :(
|
|
// 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)
|
|
#define USE_TINYFILEDIALOG 0
|
|
#else
|
|
#define USE_TINYFILEDIALOG 1
|
|
#endif
|
|
|
|
#if USE_TINYFILEDIALOG
|
|
#include "tinyfiledialogs.h"
|
|
#else
|
|
#include <stdio.h>
|
|
#include <gtk/gtk.h>
|
|
|
|
static bool gtk_init_ok = false;
|
|
static int window_x = -1, window_y = -1;
|
|
|
|
void add_filter_any_file_dialog( GtkWidget *dialog)
|
|
{
|
|
/* append a wildcard option */
|
|
GtkFileFilter *filter;
|
|
filter = gtk_file_filter_new();
|
|
gtk_file_filter_set_name( filter, "Any file" );
|
|
gtk_file_filter_add_pattern( filter, "*" );
|
|
gtk_file_chooser_add_filter( GTK_FILE_CHOOSER(dialog), filter );
|
|
}
|
|
|
|
void add_filter_file_dialog( GtkWidget *dialog, int const countfilterPatterns, char const * const * const filterPatterns, char const * const filterDescription)
|
|
{
|
|
GtkFileFilter *filter;
|
|
filter = gtk_file_filter_new();
|
|
gtk_file_filter_set_name( filter, filterDescription );
|
|
for (int i = 0; i < countfilterPatterns; i++ )
|
|
gtk_file_filter_add_pattern( filter, filterPatterns[i] );
|
|
gtk_file_chooser_add_filter( GTK_FILE_CHOOSER(dialog), filter );
|
|
}
|
|
|
|
void wait_for_event(void)
|
|
{
|
|
while ( gtk_events_pending() )
|
|
gtk_main_iteration();
|
|
}
|
|
|
|
bool gtk_init()
|
|
{
|
|
if (!gtk_init_ok) {
|
|
if ( gtk_init_check( NULL, NULL ) )
|
|
gtk_init_ok = true;
|
|
}
|
|
return gtk_init_ok;
|
|
}
|
|
#endif
|
|
|
|
|
|
// globals
|
|
const std::chrono::milliseconds timeout = std::chrono::milliseconds(4);
|
|
bool DialogToolkit::FileDialog::busy_ = 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
|
|
path_ = promises_.back().get();
|
|
if (!path_.empty()) {
|
|
// save path location
|
|
Settings::application.dialogRecentFolder[id_] = SystemToolkit::path_filename(path_);
|
|
}
|
|
// done with this file dialog
|
|
promises_.pop_back();
|
|
busy_ = false;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//
|
|
// type specific implementations
|
|
//
|
|
std::string openImageFileDialog(const std::string &label, const std::string &path);
|
|
void DialogToolkit::OpenImageDialog::open()
|
|
{
|
|
if ( !busy_ && promises_.empty() ) {
|
|
promises_.emplace_back( std::async(std::launch::async, openImageFileDialog, id_,
|
|
Settings::application.dialogRecentFolder[id_]) );
|
|
busy_ = true;
|
|
}
|
|
}
|
|
|
|
std::string openSessionFileDialog(const std::string &label, const std::string &path);
|
|
void DialogToolkit::OpenSessionDialog::open()
|
|
{
|
|
if ( !busy_ && promises_.empty() ) {
|
|
promises_.emplace_back( std::async(std::launch::async, openSessionFileDialog, id_,
|
|
Settings::application.dialogRecentFolder[id_]) );
|
|
busy_ = true;
|
|
}
|
|
}
|
|
|
|
std::string openMediaFileDialog(const std::string &label, const std::string &path);
|
|
void DialogToolkit::OpenMediaDialog::open()
|
|
{
|
|
if ( !busy_ && promises_.empty() ) {
|
|
promises_.emplace_back( std::async(std::launch::async, openMediaFileDialog, id_,
|
|
Settings::application.dialogRecentFolder[id_]) );
|
|
busy_ = true;
|
|
}
|
|
}
|
|
|
|
std::string saveSessionFileDialog(const std::string &label, const std::string &path);
|
|
void DialogToolkit::SaveSessionDialog::open()
|
|
{
|
|
if ( !busy_ && promises_.empty() ) {
|
|
promises_.emplace_back( std::async(std::launch::async, saveSessionFileDialog, id_,
|
|
Settings::application.dialogRecentFolder[id_]) );
|
|
busy_ = true;
|
|
}
|
|
}
|
|
|
|
std::string openFolderDialog(const std::string &label, const std::string &path);
|
|
void DialogToolkit::OpenFolderDialog::open()
|
|
{
|
|
if ( !busy_ && promises_.empty() ) {
|
|
promises_.emplace_back( std::async(std::launch::async, openFolderDialog, id_,
|
|
Settings::application.dialogRecentFolder[id_]) );
|
|
busy_ = true;
|
|
}
|
|
}
|
|
|
|
std::list<std::string> selectImagesFileDialog(const std::string &label,const std::string &path);
|
|
void DialogToolkit::MultipleImagesDialog::open()
|
|
{
|
|
if ( !busy_ && promisedlist_.empty() ) {
|
|
promisedlist_.emplace_back( std::async(std::launch::async, selectImagesFileDialog, id_,
|
|
Settings::application.dialogRecentFolder[id_]) );
|
|
busy_ = 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();
|
|
busy_ = false;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
//
|
|
//
|
|
// CALLBACKS
|
|
//
|
|
//
|
|
|
|
std::string saveSessionFileDialog(const std::string &label, const std::string &path)
|
|
{
|
|
std::string filename = "";
|
|
char const * save_pattern[2] = { "*.mix", "*.MIX" };
|
|
|
|
#if USE_TINYFILEDIALOG
|
|
char const * save_file_name;
|
|
|
|
save_file_name = tinyfd_saveFileDialog( label.c_str(), path.c_str(), 2, save_pattern, "vimix session");
|
|
|
|
if (save_file_name)
|
|
filename = std::string(save_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_SAVE,
|
|
"_Cancel", GTK_RESPONSE_CANCEL,
|
|
"_Save", GTK_RESPONSE_ACCEPT, NULL );
|
|
gtk_file_chooser_set_do_overwrite_confirmation( GTK_FILE_CHOOSER(dialog), TRUE );
|
|
|
|
// set file filters
|
|
add_filter_file_dialog(dialog, 2, save_pattern, "vimix session");
|
|
add_filter_any_file_dialog(dialog);
|
|
|
|
// Set the default path
|
|
gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER(dialog), path.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 *save_file_name = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(dialog) );
|
|
if (save_file_name)
|
|
filename = std::string(save_file_name);
|
|
g_free( save_file_name );
|
|
}
|
|
|
|
// remember position
|
|
gtk_window_get_position( GTK_WINDOW(dialog), &window_x, &window_y);
|
|
|
|
// done
|
|
gtk_widget_destroy(dialog);
|
|
wait_for_event();
|
|
#endif
|
|
|
|
std::string extension = filename.substr(filename.find_last_of(".") + 1);
|
|
if (!filename.empty() && extension != "mix")
|
|
filename += ".mix";
|
|
|
|
return filename;
|
|
}
|
|
|
|
|
|
std::string openSessionFileDialog(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] = { "*.mix", "*.MIX" };
|
|
|
|
#if USE_TINYFILEDIALOG
|
|
char const * open_file_name;
|
|
open_file_name = tinyfd_openFileDialog( label.c_str(), startpath.c_str(), 2, open_pattern, "vimix session", 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, "vimix session");
|
|
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 openMediaFileDialog(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[52] = { "*.mix", "*.mp4", "*.mpg", "*.mpeg", "*.m2v", "*.m4v", "*.avi", "*.mov",
|
|
"*.mkv", "*.webm", "*.mod", "*.wmv", "*.mxf", "*.ogg",
|
|
"*.flv", "*.hevc", "*.asf", "*.jpg", "*.png", "*.gif",
|
|
"*.tif", "*.tiff", "*.webp", "*.bmp", "*.ppm", "*.svg,"
|
|
"*.MIX", "*.MP4", "*.MPG", "*.MPEG","*.M2V", "*.M4V", "*.AVI", "*.MOV",
|
|
"*.MKV", "*.WEBM", "*.MOD", "*.WMV", "*.MXF", "*.OGG",
|
|
"*.FLV", "*.HEVC", "*.ASF", "*.JPG", "*.PNG", "*.GIF",
|
|
"*.TIF", "*.TIFF", "*.WEBP", "*.BMP", "*.PPM", "*.SVG" };
|
|
#if USE_TINYFILEDIALOG
|
|
char const * open_file_name;
|
|
open_file_name = tinyfd_openFileDialog( label.c_str(), startpath.c_str(), 18, open_pattern, "All supported formats", 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, 52, open_pattern, "Supported formats (videos, images, sessions)");
|
|
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 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[10] = { "*.jpg", "*.png", "*.bmp", "*.ppm", "*.gif",
|
|
"*.JPG", "*.PNG", "*.BMP", "*.PPM", "*.GIF"};
|
|
#if USE_TINYFILEDIALOG
|
|
char const * open_file_name;
|
|
open_file_name = tinyfd_openFileDialog( label.c_str(), startpath.c_str(), 4, 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, 10, open_pattern, "Image (JPG, PNG, BMP, PPM, GIF)");
|
|
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 startpath = SystemToolkit::file_exists(path) ? path : SystemToolkit::home_path();
|
|
|
|
#if USE_TINYFILEDIALOG
|
|
char const * open_folder_name;
|
|
open_folder_name = tinyfd_selectFolderDialog(label.c_str(), startpath.c_str());
|
|
|
|
if (open_folder_name)
|
|
foldername = std::string(open_folder_name);
|
|
#else
|
|
if (!gtk_init()) {
|
|
DialogToolkit::ErrorDialog("Could not initialize GTK+ for dialog");
|
|
return foldername;
|
|
}
|
|
|
|
GtkWidget *dialog = gtk_file_chooser_dialog_new( label.c_str(), NULL,
|
|
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
|
|
"_Cancel", GTK_RESPONSE_CANCEL,
|
|
"_Select", GTK_RESPONSE_ACCEPT, NULL );
|
|
gtk_file_chooser_set_do_overwrite_confirmation( GTK_FILE_CHOOSER(dialog), TRUE );
|
|
|
|
// 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_folder_name = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(dialog) );
|
|
if (open_folder_name)
|
|
foldername = std::string(open_folder_name);
|
|
g_free( open_folder_name );
|
|
}
|
|
|
|
// remember position
|
|
gtk_window_get_position( GTK_WINDOW(dialog), &window_x, &window_y);
|
|
|
|
// done
|
|
gtk_widget_destroy(dialog);
|
|
wait_for_event();
|
|
#endif
|
|
|
|
return foldername;
|
|
}
|
|
|
|
|
|
std::list<std::string> selectImagesFileDialog(const std::string &label,const std::string &path)
|
|
{
|
|
std::list<std::string> files;
|
|
|
|
std::string startpath = SystemToolkit::file_exists(path) ? path : SystemToolkit::home_path();
|
|
char const * open_pattern[6] = { "*.jpg", "*.png", "*.tif",
|
|
"*.JPG", "*.PNG", "*.TIF" };
|
|
|
|
#if USE_TINYFILEDIALOG
|
|
char const * open_file_names;
|
|
open_file_names = tinyfd_openFileDialog(label.c_str(), startpath.c_str(), 6, open_pattern, "Images", 1);
|
|
|
|
if (open_file_names) {
|
|
|
|
const std::string& str (open_file_names);
|
|
const std::string& delimiters = "|";
|
|
// Skip delimiters at beginning.
|
|
std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
|
|
|
|
// Find first non-delimiter.
|
|
std::string::size_type pos = str.find_first_of(delimiters, lastPos);
|
|
|
|
while (std::string::npos != pos || std::string::npos != lastPos) {
|
|
// Found a token, add it to the vector.
|
|
files.push_back(str.substr(lastPos, pos - lastPos));
|
|
|
|
// Skip delimiters.
|
|
lastPos = str.find_first_not_of(delimiters, pos);
|
|
|
|
// Find next non-delimiter.
|
|
pos = str.find_first_of(delimiters, lastPos);
|
|
}
|
|
}
|
|
#else
|
|
|
|
if (!gtk_init()) {
|
|
DialogToolkit::ErrorDialog("Could not initialize GTK+ for dialog");
|
|
return files;
|
|
}
|
|
|
|
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, 6, open_pattern, "Images (JPG, PNG, TIF)");
|
|
add_filter_any_file_dialog(dialog);
|
|
|
|
// multiple files
|
|
gtk_file_chooser_set_select_multiple( GTK_FILE_CHOOSER(dialog), true );
|
|
|
|
// 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 ) {
|
|
|
|
GSList *open_file_names = gtk_file_chooser_get_filenames( GTK_FILE_CHOOSER(dialog) );
|
|
|
|
while (open_file_names) {
|
|
files.push_back( (char *) open_file_names->data );
|
|
open_file_names = open_file_names->next;
|
|
// g_free( open_file_names->data );
|
|
}
|
|
|
|
g_slist_free( open_file_names );
|
|
}
|
|
|
|
// remember position
|
|
gtk_window_get_position( GTK_WINDOW(dialog), &window_x, &window_y);
|
|
|
|
// done
|
|
gtk_widget_destroy(dialog);
|
|
wait_for_event();
|
|
#endif
|
|
|
|
|
|
return files;
|
|
}
|
|
|
|
void DialogToolkit::ErrorDialog(const char* message)
|
|
{
|
|
#if USE_TINYFILEDIALOG
|
|
tinyfd_messageBox( APP_TITLE, message, "ok", "error", 0);
|
|
#else
|
|
if (!gtk_init()) {
|
|
return;
|
|
}
|
|
|
|
GtkWidget *dialog = gtk_message_dialog_new( NULL, GTK_DIALOG_DESTROY_WITH_PARENT,
|
|
GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
|
|
"Error: %s", message);
|
|
|
|
gtk_window_set_keep_above( GTK_WINDOW(dialog), TRUE );
|
|
static int x = 0, y = 0;
|
|
if (x != 0)
|
|
gtk_window_move( GTK_WINDOW(dialog), x, y);
|
|
|
|
// show
|
|
gtk_dialog_run( GTK_DIALOG(dialog) );
|
|
|
|
// remember position
|
|
gtk_window_get_position( GTK_WINDOW(dialog), &x, &y);
|
|
|
|
// done
|
|
gtk_widget_destroy( dialog );
|
|
wait_for_event();
|
|
#endif
|
|
}
|
|
|
|
|