mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-14 11:49:59 +01:00
New button to reorder the list of sessions and of media files
In navigator panel, the list of sessions can be reordered either alphabetically or by file modification date. Same for list of media files for creating a new media source.
This commit is contained in:
Binary file not shown.
@@ -321,10 +321,12 @@ struct Application
|
||||
std::vector<WindowConfig> windows;
|
||||
|
||||
// recent files histories
|
||||
int orderingSessions;
|
||||
History recentSessions;
|
||||
History recentFolders;
|
||||
History recentImport;
|
||||
History recentImportFolders;
|
||||
int orderingImportFolder;
|
||||
History recentRecordings;
|
||||
std::map< std::string, std::string > dialogRecentFolder;
|
||||
|
||||
@@ -361,6 +363,8 @@ struct Application
|
||||
windows = std::vector<WindowConfig>(1+MAX_OUTPUT_WINDOW);
|
||||
windows[0].w = 1600;
|
||||
windows[0].h = 900;
|
||||
orderingSessions = 3;
|
||||
orderingImportFolder = 3;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -280,6 +280,70 @@ string SystemToolkit::full_filename(const std::string& path, const string &filen
|
||||
return fullfilename;
|
||||
}
|
||||
|
||||
unsigned long SystemToolkit::file_modification_time(const std::string& path)
|
||||
{
|
||||
if (file_exists(path)) {
|
||||
struct stat statsfile;
|
||||
// fill statistics of given file path
|
||||
if( stat( path.c_str(), &statsfile) > -1 ) {
|
||||
// return modification time
|
||||
return (unsigned long) statsfile.st_mtime;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string SystemToolkit::file_modification_time_string(const std::string& path)
|
||||
{
|
||||
ostringstream oss;
|
||||
|
||||
if (file_exists(path)) {
|
||||
struct stat statsfile;
|
||||
// fill statistics of given file path
|
||||
if( stat( path.c_str(), &statsfile) > -1 ) {
|
||||
// read modification time
|
||||
tm *datetime = localtime(&statsfile.st_mtime);
|
||||
ostringstream oss;
|
||||
oss << setw(4) << setfill('0') << to_string(datetime->tm_year + 1900);
|
||||
oss << setw(2) << setfill('0') << to_string(datetime->tm_mon + 1);
|
||||
oss << setw(2) << setfill('0') << to_string(datetime->tm_mday );
|
||||
oss << setw(2) << setfill('0') << to_string(datetime->tm_hour );
|
||||
oss << setw(2) << setfill('0') << to_string(datetime->tm_min );
|
||||
oss << setw(2) << setfill('0') << to_string(datetime->tm_sec );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
|
||||
void SystemToolkit::reorder_file_list(std::list<string> &filelist, Ordering m)
|
||||
{
|
||||
if ( m >= DATE ) {
|
||||
auto dateComparator = [](const std::string &a, const std::string &b) {
|
||||
return SystemToolkit::file_modification_time(a) < SystemToolkit::file_modification_time(b);
|
||||
};
|
||||
filelist.sort( dateComparator );
|
||||
if ( m == DATE_INVERSE )
|
||||
filelist.reverse();
|
||||
}
|
||||
else {
|
||||
auto alphaComparator = [](const std::string &a, const std::string &b) {
|
||||
std::string _a = a;
|
||||
std::string _b = b;
|
||||
std::transform(_a.begin(), _a.end(), _a.begin(), ::tolower);
|
||||
std::transform(_b.begin(), _b.end(), _b.begin(), ::tolower);
|
||||
return _a < _b;
|
||||
};
|
||||
filelist.sort( alphaComparator );
|
||||
if ( m == ALPHA_INVERSE )
|
||||
filelist.reverse();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool SystemToolkit::file_exists(const string& path)
|
||||
{
|
||||
if (path.empty())
|
||||
@@ -307,7 +371,7 @@ string SystemToolkit::path_directory(const string& path)
|
||||
return directorypath;
|
||||
}
|
||||
|
||||
list<string> SystemToolkit::list_directory(const string& path, const list<string>& patterns)
|
||||
list<string> SystemToolkit::list_directory(const string& path, const list<string>& patterns, Ordering m)
|
||||
{
|
||||
list<string> ls;
|
||||
|
||||
@@ -329,7 +393,7 @@ list<string> SystemToolkit::list_directory(const string& path, const list<string
|
||||
closedir (dir);
|
||||
}
|
||||
|
||||
ls.sort();
|
||||
reorder_file_list( ls, m );
|
||||
|
||||
return ls;
|
||||
}
|
||||
|
||||
@@ -49,9 +49,6 @@ namespace SystemToolkit
|
||||
// tests if dir is a directory and return its path, empty string otherwise
|
||||
std::string path_directory(const std::string& path);
|
||||
|
||||
// list all files of a directory mathing the given filter extension (if any)
|
||||
std::list<std::string> list_directory(const std::string& path, const std::list<std::string> &patterns);
|
||||
|
||||
// builds a path relative to 'relativeTo' to reach file at 'absolutePath' (e.g. /a/b/c/d rel to /a/b/e -> ../c/d)
|
||||
std::string path_relative_to_path(const std::string& absolutePath, const std::string& relativeTo);
|
||||
|
||||
@@ -64,6 +61,23 @@ namespace SystemToolkit
|
||||
// generates a filename at given path, with basename and date prefix
|
||||
std::string filename_dateprefix(const std::string& path, const std::string& base, const std::string& extension);
|
||||
|
||||
// Get modification time of file, as string YYYYMMDDHHmmss
|
||||
unsigned long file_modification_time(const std::string& path);
|
||||
std::string file_modification_time_string(const std::string& path);
|
||||
|
||||
|
||||
typedef enum {
|
||||
ALPHA = 0,
|
||||
ALPHA_INVERSE = 1,
|
||||
DATE = 2,
|
||||
DATE_INVERSE = 3
|
||||
} Ordering;
|
||||
//
|
||||
void reorder_file_list(std::list<std::string> &filelist, Ordering m);
|
||||
|
||||
// list all files of a directory mathing the given filter extension (if any)
|
||||
std::list<std::string> list_directory(const std::string& path, const std::list<std::string> &patterns, Ordering m = ALPHA);
|
||||
|
||||
// true of file exists
|
||||
bool file_exists(const std::string& path);
|
||||
|
||||
|
||||
@@ -2649,6 +2649,11 @@ void UserInterface::RenderHelp()
|
||||
///
|
||||
/// NAVIGATOR
|
||||
///
|
||||
///
|
||||
|
||||
std::vector< std::pair<int, int> > Navigator::icons_ordering_files = { {2,12}, {3,12}, {4,12}, {5,12} };
|
||||
std::vector< std::string > Navigator::tooltips_ordering_files = { "Alphabetical", "Invert alphabetical", "Older files first", "Recent files first" };
|
||||
|
||||
Navigator::Navigator()
|
||||
{
|
||||
// default geometry
|
||||
@@ -3480,7 +3485,8 @@ void Navigator::RenderNewPannel()
|
||||
// MODE LIST FOLDER
|
||||
else if ( new_media_mode == MEDIA_FOLDER) {
|
||||
// show list of media files in folder
|
||||
sourceMediaFiles = SystemToolkit::list_directory( Settings::application.recentImportFolders.path, { MEDIA_FILES_PATTERN });
|
||||
sourceMediaFiles = SystemToolkit::list_directory( Settings::application.recentImportFolders.path, { MEDIA_FILES_PATTERN },
|
||||
(SystemToolkit::Ordering) Settings::application.orderingImportFolder);
|
||||
}
|
||||
// indicate the list changed (do not change at every frame)
|
||||
new_media_mode_changed = false;
|
||||
@@ -3524,9 +3530,10 @@ void Navigator::RenderNewPannel()
|
||||
ImGui::ListBoxFooter();
|
||||
}
|
||||
|
||||
// Supplementary icons to manage the list
|
||||
ImVec2 pos_bot = ImGui::GetCursorPos();
|
||||
// Bottom Right side of the list: helper and options of Recent Recordings
|
||||
if (new_media_mode == MEDIA_RECORDING) {
|
||||
// Bottom Right side of the list: helper and options
|
||||
ImVec2 pos_bot = ImGui::GetCursorPos();
|
||||
ImGui::SetCursorPos( ImVec2( pannel_width_ IMGUI_RIGHT_ALIGN, pos_bot.y - 2.f * ImGui::GetFrameHeightWithSpacing()));
|
||||
ImGuiToolkit::HelpToolTip("Recently recorded videos (lastest on top). Clic on a filename to open.\n\n"
|
||||
ICON_FA_CHEVRON_CIRCLE_RIGHT " Auto-preload prepares this panel with the "
|
||||
@@ -3541,9 +3548,18 @@ void Navigator::RenderNewPannel()
|
||||
new_source_preview_.setSource( Mixer::manager().createSourceFile(sourceMediaFileCurrent), label);
|
||||
}
|
||||
}
|
||||
// come back...
|
||||
ImGui::SetCursorPos(pos_bot);
|
||||
}
|
||||
// Top right of Media folder list
|
||||
else if (new_media_mode == MEDIA_FOLDER) {
|
||||
// ordering list
|
||||
ImGui::SetCursorPos( ImVec2( pannel_width_ IMGUI_RIGHT_ALIGN, pos_top.y) );
|
||||
ImGui::PushID("##new_media_mode_changed");
|
||||
if ( ImGuiToolkit::IconMultistate(icons_ordering_files, &Settings::application.orderingImportFolder, tooltips_ordering_files) )
|
||||
new_media_mode_changed = true;
|
||||
ImGui::PopID();
|
||||
}
|
||||
// come back...
|
||||
ImGui::SetCursorPos(pos_bot);
|
||||
|
||||
}
|
||||
// Sequence Source creator
|
||||
@@ -4103,14 +4119,18 @@ void Navigator::RenderMainPannelVimix()
|
||||
// show list of recent sessions
|
||||
Settings::application.recentSessions.validate();
|
||||
sessions_list = Settings::application.recentSessions.filenames;
|
||||
Settings::application.recentSessions.changed = false;
|
||||
SystemToolkit::reorder_file_list( sessions_list, (SystemToolkit::Ordering) Settings::application.orderingSessions);
|
||||
}
|
||||
// selection MODE 1 : LIST FOLDER
|
||||
else if ( selection_session_mode == 1) {
|
||||
// show list of vimix files in folder
|
||||
sessions_list = SystemToolkit::list_directory( Settings::application.recentFolders.path, { VIMIX_FILE_PATTERN });
|
||||
sessions_list = SystemToolkit::list_directory( Settings::application.recentFolders.path, { VIMIX_FILE_PATTERN },
|
||||
(SystemToolkit::Ordering) Settings::application.orderingSessions);
|
||||
}
|
||||
|
||||
// indicate the list changed (do not change at every frame)
|
||||
Settings::application.recentSessions.changed = false;
|
||||
Settings::application.recentFolders.changed = false;
|
||||
selection_session_mode_changed = false;
|
||||
_file_over = sessions_list.end();
|
||||
_displayed_over = sessions_list.end();
|
||||
@@ -4219,8 +4239,16 @@ void Navigator::RenderMainPannelVimix()
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGuiToolkit::ToolTip("New session", SHORTCUT_NEW_FILE);
|
||||
|
||||
// ordering list
|
||||
ImGui::SetCursorPos( ImVec2( pannel_width_ IMGUI_RIGHT_ALIGN, pos_top.y + ImGui::GetFrameHeightWithSpacing()) );
|
||||
ImGui::PushID("##selection_session_mode_changed");
|
||||
if ( ImGuiToolkit::IconMultistate(icons_ordering_files, &Settings::application.orderingSessions, tooltips_ordering_files) )
|
||||
selection_session_mode_changed = true;
|
||||
ImGui::PopID();
|
||||
|
||||
// help indicator
|
||||
ImGui::SetCursorPos( ImVec2( pannel_width_ IMGUI_RIGHT_ALIGN, pos_bot.y - 2.f * ImGui::GetFrameHeightWithSpacing()));
|
||||
ImGuiToolkit::HelpToolTip("Here are listed either all recent files or all the sessions files inside a selected folder (*.mix) .\n\n"
|
||||
ImGuiToolkit::HelpToolTip("Here are listed either the recent files or all the sessions files (*.mix) in a selected folder.\n\n"
|
||||
"Double-clic on a filename to open the session.\n\n"
|
||||
ICON_FA_ARROW_CIRCLE_RIGHT " Smooth transition "
|
||||
"performs cross fading to the opened session.");
|
||||
@@ -4262,35 +4290,6 @@ void Navigator::RenderMainPannelVimix()
|
||||
ImGui::InputText("##Info", (char *)info.c_str(), info.size(), ImGuiInputTextFlags_ReadOnly);
|
||||
ImGui::PopStyleColor(1);
|
||||
|
||||
// Kept for later? Larger info box with more details on the session file...
|
||||
// ImGuiTextBuffer info;
|
||||
// if (!sessionfilename.empty())
|
||||
// info.appendf("%s\n", SystemToolkit::filename(sessionfilename).c_str());
|
||||
// else
|
||||
// info.append("<unsaved>\n");
|
||||
// info.appendf("%dx%dpx", output->width(), output->height());
|
||||
// if (p.x > -1)
|
||||
// info.appendf(", %s", FrameBuffer::aspect_ratio_name[p.x]);
|
||||
// // content info
|
||||
// const uint N = Mixer::manager().session()->numSource();
|
||||
// if (N > 1)
|
||||
// info.appendf("\n%d sources", N);
|
||||
// else if (N > 0)
|
||||
// info.append("\n1 source");
|
||||
// const size_t M = MediaPlayer::registered().size();
|
||||
// if (M > 0) {
|
||||
// info.appendf("\n%d media files:", M);
|
||||
// for (auto mit = MediaPlayer::begin(); mit != MediaPlayer::end(); ++mit)
|
||||
// info.appendf("\n- %s", SystemToolkit::filename((*mit)->filename()).c_str());
|
||||
// }
|
||||
// // Show info text bloc (multi line, dark background)
|
||||
// ImGuiToolkit::PushFont( ImGuiToolkit::FONT_MONO );
|
||||
// ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.14f, 0.14f, 0.14f, 0.9f));
|
||||
// ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
|
||||
// ImGui::InputTextMultiline("##Info", (char *)info.c_str(), info.size(), ImVec2(IMGUI_RIGHT_ALIGN, 2*ImGui::GetTextLineHeightWithSpacing()), ImGuiInputTextFlags_ReadOnly);
|
||||
// ImGui::PopStyleColor(1);
|
||||
// ImGui::PopFont();
|
||||
|
||||
// change resolution (height only)
|
||||
// get parameters to edit resolution
|
||||
glm::ivec2 preset = RenderView::presetFromResolution(output->resolution());
|
||||
@@ -4375,7 +4374,7 @@ void Navigator::RenderMainPannelVimix()
|
||||
// Thumbnail
|
||||
static Thumbnail _file_thumbnail;
|
||||
static FrameBufferImage *thumbnail = nullptr;
|
||||
if ( ImGui::Button( ICON_FA_TAG " New thumbnail", ImVec2(IMGUI_RIGHT_ALIGN, 0)) ) {
|
||||
if ( ImGui::Button( ICON_FA_TAG " Create thumbnail", ImVec2(IMGUI_RIGHT_ALIGN, 0)) ) {
|
||||
Mixer::manager().session()->setThumbnail();
|
||||
thumbnail = nullptr;
|
||||
}
|
||||
@@ -4647,8 +4646,8 @@ void Navigator::RenderMainPannelVimix()
|
||||
ImGui::SetCursorPos( ImVec2( pannel_width_ IMGUI_RIGHT_ALIGN, pos_bot.y - 2.f * ImGui::GetFrameHeightWithSpacing()));
|
||||
ImGuiToolkit::HelpToolTip("Previous versions of the session (latest on top). "
|
||||
"Double-clic on a version to restore it.\n\n"
|
||||
ICON_FA_CODE_BRANCH " Iterative saving automatically "
|
||||
"keeps a version each time a session is saved.");
|
||||
ICON_FA_CODE_BRANCH " With iterative saving on, a new version "
|
||||
"is kept each time the session is saved.");
|
||||
// toggle button for versioning
|
||||
ImGui::SetCursorPos( ImVec2( pannel_width_ IMGUI_RIGHT_ALIGN, pos_bot.y - ImGui::GetFrameHeightWithSpacing()) );
|
||||
ImGuiToolkit::ButtonToggle(" " ICON_FA_CODE_BRANCH " ", &Settings::application.save_version_snapshot,"Iterative saving");
|
||||
@@ -4803,8 +4802,8 @@ void Navigator::RenderMousePointerSelector(const ImVec2 &size)
|
||||
ImGui::SameLine(0, IMGUI_SAME_LINE * 3);
|
||||
ImGuiToolkit::ButtonToggle(Settings::application.mouse_pointer_lock ? ICON_FA_LOCK ALT_LOCK : ICON_FA_UNLOCK ALT_LOCK,
|
||||
&Settings::application.mouse_pointer_lock,
|
||||
"Activate the selected snap mouse pointer by pressing the [" ALT_MOD "] key.\n\n"
|
||||
ICON_FA_LOCK ALT_LOCK " keeps the snap mouse pointer active.");
|
||||
"Activate the selected Snap mouse cursor by pressing the [" ALT_MOD "] key.\n\n"
|
||||
ICON_FA_LOCK ALT_LOCK " keeps the Snap mouse cursor active.");
|
||||
|
||||
// slider to adjust strength of the mouse pointer
|
||||
ImGui::SetNextItemWidth( IMGUI_RIGHT_ALIGN );
|
||||
@@ -4821,12 +4820,15 @@ void Navigator::RenderMousePointerSelector(const ImVec2 &size)
|
||||
}
|
||||
// special case of GRID
|
||||
else {
|
||||
static const char* grid_names[Grid::UNIT_ONE+1] = { "Precise (0.05)", "Small (0.1)", "Default (0.2)", "Large (0.5)", "Huge (1.0)"};
|
||||
static const char* grid_names[Grid::UNIT_ONE+1] = { "Precise", "Small", "Default", "Large", "Huge"};
|
||||
int grid_current = (Grid::Units) round( *val * 4.f) ;
|
||||
const char* grid_current_name = (grid_current >= 0 && grid_current <= Grid::UNIT_ONE) ?
|
||||
grid_names[grid_current] : "Unknown";
|
||||
if (ImGui::SliderInt("##slidergrid", &grid_current, 0, Grid::UNIT_ONE, grid_current_name) ) {
|
||||
if (ImGui::SliderInt("##slidergrid", &grid_current, 0, Grid::UNIT_ONE, grid_current_name) )
|
||||
*val = (float) grid_current * 0.25f;
|
||||
if (ImGui::IsItemHovered() && g.IO.MouseWheel != 0.f ){
|
||||
*val += 0.25f * g.IO.MouseWheel;
|
||||
*val = CLAMP( *val, 0.f, 1.f);
|
||||
}
|
||||
}
|
||||
ImGui::SameLine(0, IMGUI_SAME_LINE);
|
||||
|
||||
@@ -110,6 +110,9 @@ private:
|
||||
MediaCreateMode new_media_mode;
|
||||
bool new_media_mode_changed;
|
||||
Source *source_to_replace;
|
||||
|
||||
static std::vector< std::pair<int, int> > icons_ordering_files;
|
||||
static std::vector< std::string > tooltips_ordering_files;
|
||||
};
|
||||
|
||||
class ToolBox
|
||||
|
||||
Reference in New Issue
Block a user