2025-06-22 17:18:53 +02:00
# include "explorer.h"
2025-08-31 16:46:10 +02:00
2026-04-05 09:45:10 +02:00
# include "../../src-interface/main_ui.h"
2025-07-24 21:55:57 +02:00
# include "core/exception.h"
2025-04-15 19:06:12 +01:00
# include "core/plugin.h"
2026-04-05 09:45:10 +02:00
# include "core/resources.h"
2025-04-27 12:24:09 +02:00
# include "core/style.h"
2026-04-05 09:45:10 +02:00
# include "image/image.h"
# include "image/io.h"
# include "imgui/imgui.h"
# include "imgui/imgui_filedrop.h"
# include "imgui/imgui_image.h"
# include <cstddef>
# include <cstdint>
# include <fstream>
# include <memory>
# include <string>
2025-04-21 23:17:21 +02:00
# include "dsp/flowgraph/dsp_flowgraph_handler.h"
2025-05-19 22:26:32 +02:00
# include "handlers/dataset/dataset_handler.h"
# include "handlers/dummy_handler.h"
2026-02-16 19:28:20 +01:00
# include "handlers/experimental/decoupled/rec_backend.h"
# include "handlers/experimental/decoupled/rec_frontend.h"
# include "handlers/experimental/decoupled/test/test_http.h"
2026-02-17 12:04:49 +01:00
# include "handlers/experimental/decoupled/test/test_http_client.h"
2026-04-05 09:45:10 +02:00
# include "handlers/product/product_handler.h"
2025-05-19 22:26:32 +02:00
# include "handlers/projection/projection_handler.h"
# include "handlers/vector/shapefile_handler.h"
2024-12-29 20:13:58 +01:00
2025-03-15 23:37:59 +01:00
// TODOREWORK
2026-02-16 19:28:20 +01:00
# include "handlers/experimental/dsp/cyclo_test.h"
# include "handlers/experimental/dsp/fm_test.h"
# include "handlers/experimental/dsp/newrec.h"
2025-03-15 23:37:59 +01:00
2024-12-29 20:13:58 +01:00
namespace satdump
{
2025-06-22 17:18:53 +02:00
namespace explorer
2024-12-29 20:13:58 +01:00
{
2025-07-23 12:21:02 +02:00
ExplorerApplication : : ExplorerApplication ( )
2024-12-29 20:13:58 +01:00
{
2025-06-22 17:18:53 +02:00
master_handler = std : : make_shared < handlers : : DummyHandler > ( " MasterHandlerExplorer " ) ;
2025-03-22 11:51:53 +01:00
2025-07-13 14:40:31 +02:00
// Add processing handler "spot"
processing_handler = std : : make_shared < handlers : : DummyHandler > ( " ProcessingHandlerExplorer " ) ;
processing_handler - > setCanBeDraggedTo ( false ) ;
2025-07-18 10:52:31 +02:00
// Enable dropping files onto the explorer.
2025-04-15 19:06:12 +01:00
eventBus - > register_handler < imgui_utils : : FileDropEvent > (
[ this ] ( const imgui_utils : : FileDropEvent & v )
{
for ( auto & f : v . files )
2025-06-22 17:18:53 +02:00
tryOpenFileInExplorer ( f ) ;
2025-04-15 19:06:12 +01:00
} ) ;
2025-06-22 17:18:53 +02:00
// Enable adding handlers to the explorer externally
2025-07-24 11:53:20 +02:00
eventBus - > register_handler < ExplorerAddHandlerEvent > ( [ this ] ( const ExplorerAddHandlerEvent & e ) { addHandler ( e . h , e . open , e . is_processing ) ; } ) ;
2025-06-14 21:56:36 +02:00
2026-04-03 18:43:01 +01:00
// Enable adding handlers to the explorer externally
eventBus - > register_handler < ExplorerSelectHandlerEvent > ( [ this ] ( const ExplorerSelectHandlerEvent & e ) { curr_handler = e . h ; } ) ;
2025-08-05 19:07:45 +02:00
2026-03-12 07:55:22 +01:00
// Returns all handlers of a specific type if available
eventBus - > register_handler < GetAllOfTypeEvent > (
[ this ] ( const GetAllOfTypeEvent & v )
{
std : : function < void ( std : : shared_ptr < handlers : : Handler > & ) > recf ;
recf = [ & v , & recf ] ( std : : shared_ptr < handlers : : Handler > & h )
{
for ( auto & hs : h - > getAllSubHandlers ( ) )
{
if ( hs - > getID ( ) = = v . type )
v . hs . push_back ( hs ) ;
recf ( hs ) ;
}
} ;
recf ( processing_handler ) ;
for ( auto & sh : groups_handlers )
recf ( sh . second ) ;
recf ( master_handler ) ;
} ) ;
2026-03-13 07:54:12 +01:00
// Returns all handlers of a specific type if available
eventBus - > register_handler < ExplorerLoadFileEvent > ( [ this ] ( const ExplorerLoadFileEvent & v ) { tryOpenFileInExplorer ( v . path ) ; } ) ;
2026-03-05 21:35:34 +01:00
// Load tip of the day if we can, "randomly"
# ifdef BUILD_IS_DEBUG
std : : string tod_res = " todd.txt " ;
# else
std : : string tod_res = " tod.txt " ;
# endif
if ( resources : : resourceExists ( tod_res ) )
2025-08-05 19:07:45 +02:00
{
2026-03-05 21:35:34 +01:00
std : : ifstream message_of_the_day_f ( resources : : getResourcePath ( tod_res ) ) ;
2025-08-05 19:07:45 +02:00
std : : vector < std : : string > lines ;
std : : string l ;
while ( std : : getline ( message_of_the_day_f , l ) )
lines . push_back ( l ) ;
2026-03-12 07:55:22 +01:00
if ( lego_debug_mode )
lines = {
{ 0x57 , 0x65 , 0x20 , 0x73 , 0x74 , 0x69 , 0x6c , 0x6c , 0x20 , 0x77 , 0x6f , 0x6e , 0x64 , 0x65 , 0x72 , 0x20 , 0x77 , 0x68 , 0x61 , 0x74 , 0x20 , 0x68 , 0x61 , 0x70 , 0x70 ,
0x65 , 0x6e , 0x65 , 0x64 , 0x20 , 0x74 , 0x6f , 0x20 , 0x74 , 0x68 , 0x65 , 0x20 , 0x70 , 0x6f , 0x6f , 0x72 , 0x20 , 0x6c , 0x65 , 0x67 , 0x6f , 0x30 , 0x31 , 0x20 , 0x74 ,
0x6f , 0x20 , 0x6c , 0x65 , 0x67 , 0x6f , 0x31 , 0x30 , 0x2e , 0x2e , 0x2e , 0x20 , 0x41 , 0x6e , 0x64 , 0x20 , 0x6c , 0x65 , 0x67 , 0x6f , 0x31 , 0x32 , 0x20 , 0x73 , 0x65 ,
0x65 , 0x6d , 0x73 , 0x20 , 0x74 , 0x6f , 0x20 , 0x68 , 0x61 , 0x76 , 0x65 , 0x20 , 0x76 , 0x61 , 0x6e , 0x69 , 0x73 , 0x68 , 0x65 , 0x64 , 0x2c , 0x20 , 0x69 , 0x74 , 0x27 ,
2026-03-13 22:51:45 +01:00
0x73 , 0x20 , 0x65 , 0x78 , 0x74 , 0x72 , 0x65 , 0x6d , 0x65 , 0x6c , 0x79 , 0x20 , 0x77 , 0x6f , 0x72 , 0x72 , 0x79 , 0x69 , 0x6e , 0x67 , 0x2e , 0x2e , 0x2e , 0x00 } , //
2026-03-12 07:55:22 +01:00
{ 0x4c , 0x65 , 0x67 , 0x6f , 0x20 , 0x70 , 0x6c , 0x65 , 0x61 , 0x73 , 0x65 , 0x20 , 0x66 , 0x69 , 0x6e , 0x64 , 0x20 , 0x73 , 0x6f , 0x6d , 0x65 , 0x74 , 0x68 , 0x69 ,
0x6e , 0x67 , 0x20 , 0x6f , 0x74 , 0x68 , 0x65 , 0x72 , 0x20 , 0x74 , 0x68 , 0x61 , 0x6e , 0x20 , 0x6d , 0x6f , 0x73 , 0x71 , 0x75 , 0x69 , 0x74 , 0x74 , 0x6f , 0x65 ,
0x73 , 0x20 , 0x74 , 0x68 , 0x69 , 0x73 , 0x20 , 0x74 , 0x69 , 0x6d , 0x65 , 0x2e , 0x20 , 0x54 , 0x68 , 0x65 , 0x72 , 0x65 , 0x27 , 0x73 , 0x20 , 0x61 , 0x20 , 0x73 ,
2026-03-13 22:51:45 +01:00
0x68 , 0x6f , 0x72 , 0x74 , 0x61 , 0x67 , 0x65 , 0x20 , 0x6f , 0x66 , 0x20 , 0x62 , 0x75 , 0x67 , 0x20 , 0x72 , 0x65 , 0x70 , 0x6f , 0x72 , 0x74 , 0x73 , 0x21 , 0x00 } , //
{ 0x44 , 0x69 , 0x64 , 0x20 , 0x61 , 0x20 , 0x63 , 0x6f , 0x6d , 0x70 , 0x6f , 0x73 , 0x69 , 0x74 , 0x65 , 0x20 , 0x62 , 0x72 , 0x65 , 0x61 ,
0x6b , 0x20 , 0x61 , 0x67 , 0x61 , 0x69 , 0x6e , 0x3f , 0x20 , 0x50 , 0x72 , 0x6f , 0x62 , 0x61 , 0x62 , 0x6c , 0x79 , 0x2e , 0x00 } , //
2026-03-12 07:55:22 +01:00
{ 0x42 , 0x44 , 0x41 , 0x44 , 0x61 , 0x74 , 0x61 , 0x45 , 0x78 , 0x20 , 0x70 , 0x72 , 0x6f , 0x62 , 0x61 , 0x62 , 0x6c , 0x79 , 0x20 , 0x63 , 0x72 , 0x61 , 0x73 , 0x68 , 0x65 , 0x64 ,
2026-03-13 22:51:45 +01:00
0x20 , 0x61 , 0x67 , 0x61 , 0x69 , 0x6e , 0x2c , 0x20 , 0x79 , 0x6f , 0x75 , 0x20 , 0x73 , 0x68 , 0x6f , 0x75 , 0x6c , 0x64 , 0x20 , 0x63 , 0x68 , 0x65 , 0x63 , 0x6b , 0x2e , 0x00 } , //
2026-03-12 07:55:22 +01:00
{ 0x59 , 0x6f , 0x75 , 0x20 , 0x73 , 0x74 , 0x69 , 0x6c , 0x6c , 0x20 , 0x6e , 0x65 , 0x65 , 0x64 , 0x20 , 0x74 , 0x6f , 0x20 , 0x61 , 0x64 , 0x64 , 0x20 , 0x74 , 0x68 , 0x65 , 0x20 , 0x52 , 0x45 ,
0x52 , 0x20 , 0x43 , 0x20 , 0x28 , 0x69 , 0x6e , 0x20 , 0x66 , 0x75 , 0x6c , 0x6c , 0x2c , 0x20 , 0x70 , 0x72 , 0x65 , 0x2d , 0x4c , 0x69 , 0x6e , 0x65 , 0x2d , 0x56 , 0x20 , 0x76 , 0x65 , 0x72 ,
2026-03-13 22:51:45 +01:00
0x73 , 0x69 , 0x6f , 0x6e , 0x29 , 0x20 , 0x6f , 0x6e , 0x20 , 0x79 , 0x6f , 0x75 , 0x72 , 0x20 , 0x73 , 0x69 , 0x6d , 0x75 , 0x6c , 0x61 , 0x74 , 0x6f , 0x72 , 0x2e , 0x2e , 0x2e , 0x00 } , //
{ 0x44 , 0X6F , 0X65 , 0X73 , 0X20 , 0X74 , 0X68 , 0X61 , 0X74 , 0X20 , 0X74 , 0X69 , 0X6E , 0X79 , 0X20 , 0X69 , 0X6E , 0X73 , 0X69 , 0X67 , 0X6E , 0X69 , 0X66 , 0X69 ,
0X63 , 0X61 , 0X6E , 0X74 , 0X20 , 0X6C , 0X69 , 0X74 , 0X74 , 0X6C , 0X65 , 0X20 , 0X62 , 0X75 , 0X74 , 0X74 , 0X6F , 0X6E , 0X20 , 0X62 , 0X6F , 0X74 , 0X68 , 0X65 ,
0X72 , 0X20 , 0X79 , 0X6F , 0X75 , 0X20 , 0X61 , 0X67 , 0X61 , 0X69 , 0X6E , 0X3F , 0X20 , 0X54 , 0X6F , 0X6F , 0X20 , 0X62 , 0X61 , 0X64 , 0X2E , 0x00 } , //
2026-03-12 07:55:22 +01:00
} ;
2025-08-05 19:07:45 +02:00
int this_line = time ( 0 ) % lines . size ( ) ;
tip_of_the_day = lines [ this_line ] ;
}
2024-12-31 17:01:12 +01:00
}
2024-12-29 20:13:58 +01:00
2025-07-18 12:19:40 +02:00
ExplorerApplication : : ~ ExplorerApplication ( ) { }
2024-12-29 20:13:58 +01:00
2025-07-24 11:53:20 +02:00
void ExplorerApplication : : addHandler ( std : : shared_ptr < handlers : : Handler > h , bool open , bool is_processing )
{
if ( is_processing )
processing_handler - > addSubHandler ( h ) ;
else
{
// Try adding to a group if possible
bool added = false ;
for ( auto & v : group_definitions )
{
for ( auto & v2 : v . second )
{
if ( v2 = = h - > getID ( ) )
{
if ( groups_handlers . count ( v . first ) = = 0 )
groups_handlers . emplace ( v . first , std : : make_shared < handlers : : DummyHandler > ( v . first + " HandlerExplorer " ) ) ;
groups_handlers [ v . first ] - > addSubHandler ( h ) ;
added = true ;
}
}
}
if ( ! added )
master_handler - > addSubHandler ( h ) ;
}
if ( open )
curr_handler = h ;
}
2025-06-22 17:18:53 +02:00
void ExplorerApplication : : drawPanel ( )
2024-12-29 20:13:58 +01:00
{
2024-12-31 17:01:12 +01:00
ImGui : : SetNextItemWidth ( ImGui : : GetWindowWidth ( ) / 2 ) ;
2024-12-29 20:13:58 +01:00
2025-08-02 15:41:29 +02:00
bool handler_present = false ;
2025-08-11 16:15:55 +02:00
if ( ImGui : : CollapsingHeader ( " Root " , ImGuiTreeNodeFlags_DefaultOpen ) )
2024-12-29 20:13:58 +01:00
{
2024-12-31 17:01:12 +01:00
if ( ImGui : : BeginTable ( " ##masterhandlertable " , 1 , ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders ) )
{
ImGui : : TableSetupColumn ( " ##masterhandlertable_col " , ImGuiTableColumnFlags_None ) ;
ImGui : : TableNextColumn ( ) ;
2024-12-29 20:13:58 +01:00
2025-07-24 11:53:20 +02:00
bool rendering_separators = false ;
if ( processing_handler - > hasSubhandlers ( ) )
2025-07-13 14:40:31 +02:00
{
2025-07-24 11:53:20 +02:00
ImGui : : TableNextRow ( ) ;
ImGui : : TableSetColumnIndex ( 0 ) ;
ImGui : : SeparatorText ( " Processing " ) ;
2025-08-02 15:41:29 +02:00
handler_present | = processing_handler - > drawTreeMenu ( curr_handler ) ;
2025-07-24 11:53:20 +02:00
for ( auto & h : processing_handler - > getAllSubHandlers ( ) )
2025-07-13 14:40:31 +02:00
if ( h - > getName ( ) = = " PROCESSING_DONE " ) // TODOREWORK MASSIVE HACK
2025-07-24 11:53:20 +02:00
processing_handler - > delSubHandler ( h ) ;
rendering_separators = true ;
}
for ( auto & v : groups_handlers )
{
if ( v . second - > hasSubhandlers ( ) )
{
ImGui : : TableNextRow ( ) ;
ImGui : : TableSetColumnIndex ( 0 ) ;
ImGui : : SeparatorText ( v . first . c_str ( ) ) ;
2025-08-02 15:41:29 +02:00
handler_present | = v . second - > drawTreeMenu ( curr_handler ) ;
2025-07-24 11:53:20 +02:00
rendering_separators = true ;
}
2025-07-13 14:40:31 +02:00
}
2025-07-24 11:53:20 +02:00
if ( rendering_separators )
{
ImGui : : TableNextRow ( ) ;
ImGui : : TableSetColumnIndex ( 0 ) ;
ImGui : : SeparatorText ( " Others " ) ;
}
2025-08-02 15:41:29 +02:00
handler_present | = master_handler - > drawTreeMenu ( curr_handler ) ;
2024-12-29 20:13:58 +01:00
2025-12-15 20:00:10 +01:00
// If the handler still exist but is not in the tree, we must destroy it
2025-12-25 15:36:19 +01:00
// also destroy it in the last_of_type cache
2025-12-15 20:00:10 +01:00
if ( ! handler_present & & curr_handler )
curr_handler . reset ( ) ;
2025-12-11 13:57:19 +01:00
if ( ( ! master_handler - > hasSubhandlers ( ) ) & & ( ! groups_handlers . size ( ) ) )
2025-12-10 22:35:41 +01:00
{
ImGui : : TableNextRow ( ) ;
ImGui : : TableSetColumnIndex ( 0 ) ;
ImGui : : TextDisabled ( " Handlers will appear here... " ) ;
}
2024-12-31 17:01:12 +01:00
ImGui : : EndTable ( ) ;
}
2025-01-02 17:04:32 +01:00
}
2025-07-08 22:01:05 +02:00
2025-08-02 15:41:29 +02:00
if ( ! handler_present )
curr_handler . reset ( ) ;
2025-07-08 22:01:05 +02:00
if ( curr_handler )
curr_handler - > drawMenu ( ) ;
2025-01-02 17:04:32 +01:00
}
2025-06-22 17:18:53 +02:00
void ExplorerApplication : : drawMenuBar ( )
2025-01-02 17:04:32 +01:00
{
2025-01-03 10:03:04 +01:00
// Handle File Stuff TODOREWORK?
{
2025-05-19 22:26:32 +02:00
if ( file_open_dialog . update ( ) )
2025-01-03 10:03:04 +01:00
{
2025-05-19 22:26:32 +02:00
std : : string prod_path = file_open_dialog . getPath ( ) ;
2025-05-03 12:12:36 +02:00
if ( prod_path . size ( ) > 0 )
2025-06-22 17:18:53 +02:00
tryOpenFileInExplorer ( prod_path ) ;
2025-05-03 12:12:36 +02:00
else
logger - > trace ( " No file selected " ) ;
2025-01-03 10:03:04 +01:00
}
}
2025-01-02 17:04:32 +01:00
if ( ImGui : : BeginMenuBar ( ) )
{
2025-05-19 22:26:32 +02:00
// Main "Open" menu, for files, other handlers, etc
2025-01-02 17:04:32 +01:00
if ( ImGui : : BeginMenu ( " File " ) )
2025-01-01 05:57:58 +01:00
{
2025-05-19 22:26:32 +02:00
file_open_dialog . render ( " Open File " , " Open File " , " " , { { " All Files " , " * " } } ) ;
2025-01-02 17:04:32 +01:00
2025-05-23 12:30:42 +02:00
if ( ImGui : : BeginMenu ( " Quick Open " ) )
{
ImGui : : InputText ( " ##quickvieweropen " , & quickOpenString ) ;
2025-06-25 20:23:10 +02:00
bool go = ImGui : : IsItemDeactivatedAfterEdit ( ) ;
ImGui : : SameLine ( ) ;
if ( ImGui : : Button ( " Go##loadfromhttpgo " ) | | go )
2025-05-23 12:30:42 +02:00
{
2025-06-22 17:18:53 +02:00
tryOpenFileInExplorer ( quickOpenString ) ;
2025-05-23 12:30:42 +02:00
quickOpenString . clear ( ) ;
}
2025-06-25 20:23:10 +02:00
ImGui : : SameLine ( ) ;
2025-06-09 00:06:07 +02:00
if ( ImGui : : Button ( " Paste & Load " ) )
2025-08-17 13:17:36 +02:00
{
// Returns nullptr if clipboard didn't have text or failed for some reason
if ( ImGui : : GetClipboardText ( ) ! = nullptr )
{
tryOpenFileInExplorer ( std : : string ( ImGui : : GetClipboardText ( ) ) ) ;
}
}
2025-05-23 12:30:42 +02:00
ImGui : : EndMenu ( ) ;
}
2025-08-11 16:15:55 +02:00
ImGui : : EndMenu ( ) ;
}
if ( ImGui : : BeginMenu ( " Add " ) )
{
if ( ImGui : : MenuItem ( " Projection " ) )
addHandler ( std : : make_shared < handlers : : ProjectionHandler > ( ) ) ;
2025-06-22 18:09:25 +02:00
if ( ImGui : : BeginMenu ( " Tools " ) )
2025-05-19 22:26:32 +02:00
{ // TODOREWORK?
2025-03-09 10:16:40 +01:00
if ( ImGui : : MenuItem ( " DSP Flowgraph " ) )
2025-07-24 11:53:20 +02:00
addHandler ( std : : make_shared < handlers : : DSPFlowGraphHandler > ( ) ) ;
2026-02-18 20:59:16 +01:00
ImGui : : EndMenu ( ) ;
}
if ( ImGui : : BeginMenu ( " Experimental " ) )
{ // TODOREWORK?
2025-03-22 11:51:53 +01:00
if ( ImGui : : MenuItem ( " NewRec TEST " ) )
2025-07-24 11:53:20 +02:00
addHandler ( std : : make_shared < handlers : : NewRecHandler > ( ) ) ;
2025-04-12 09:07:02 +02:00
if ( ImGui : : MenuItem ( " CycloHelper TEST " ) )
2025-07-24 11:53:20 +02:00
addHandler ( std : : make_shared < handlers : : CycloHelperHandler > ( ) ) ;
2026-01-30 20:24:27 +01:00
if ( ImGui : : MenuItem ( " FM Test " ) )
addHandler ( std : : make_shared < handlers : : FMTestHandler > ( ) ) ;
2026-02-18 20:59:16 +01:00
if ( ImGui : : MenuItem ( " TestRemoteRec " ) )
addHandler ( std : : make_shared < handlers : : RecFrontendHandler > ( std : : make_shared < handlers : : TestHttpBackend > ( std : : make_shared < handlers : : RecBackend > ( ) ) ) ) ;
if ( ImGui : : MenuItem ( " TestRemoteClient " ) )
addHandler ( std : : make_shared < handlers : : RecFrontendHandler > ( std : : make_shared < handlers : : TestHttpClientBackend > ( ) ) ) ;
2025-01-02 17:04:32 +01:00
ImGui : : EndMenu ( ) ;
2025-01-01 05:57:58 +01:00
}
2025-05-19 22:26:32 +02:00
2025-06-22 18:09:25 +02:00
ImGui : : EndMenu ( ) ;
}
if ( ImGui : : BeginMenu ( " Handler " , bool ( curr_handler ) ) )
{
2025-01-04 23:03:13 +01:00
if ( curr_handler & & ImGui : : BeginMenu ( " Config " ) )
{
if ( ImGui : : MenuItem ( " JSON To Clipboard " ) )
2025-06-22 11:50:58 +02:00
{
2025-01-04 23:03:13 +01:00
ImGui : : SetClipboardText ( curr_handler - > getConfig ( ) . dump ( 4 ) . c_str ( ) ) ;
2025-06-22 11:50:58 +02:00
logger - > warn ( " Copied to clipboard! " ) ;
}
2025-01-04 23:03:13 +01:00
if ( ImGui : : MenuItem ( " JSON From Clipboard " ) )
2025-06-22 11:50:58 +02:00
{
2025-01-04 23:03:13 +01:00
curr_handler - > setConfig ( nlohmann : : json : : parse ( ImGui : : GetClipboardText ( ) ) ) ;
2025-06-22 11:50:58 +02:00
logger - > warn ( " Copied from clipboard! " ) ;
}
2025-01-04 23:03:13 +01:00
ImGui : : EndMenu ( ) ;
}
2025-01-02 17:04:32 +01:00
ImGui : : EndMenu ( ) ;
}
2025-06-22 18:09:25 +02:00
// TODOREWORK
2025-01-02 17:04:32 +01:00
if ( curr_handler )
{
2026-01-16 23:18:13 +01:00
ImGui : : MenuItem ( " | " , NULL , false , false ) ;
curr_handler - > drawMenuBar ( ) ;
2025-01-01 05:57:58 +01:00
}
2024-12-29 20:13:58 +01:00
2025-05-18 20:05:55 +02:00
eventBus - > fire_event < RenderLoadMenuElementsEvent > ( { curr_handler , master_handler } ) ;
2025-03-25 21:33:06 +01:00
2025-01-02 17:04:32 +01:00
ImGui : : EndMenuBar ( ) ;
2024-12-29 20:13:58 +01:00
}
}
2025-08-01 00:39:05 +02:00
void ExplorerApplication : : drawContents ( )
{
if ( ImGui : : BeginChild ( " WelcomeChild " ) )
{
if ( satdump_logo_texture = = 0 )
{
image : : Image img ;
image : : load_png ( img , resources : : getResourcePath ( " icon.png " ) ) ;
satdump_logo_texture = makeImageTexture ( ) ;
uint32_t * px = new uint32_t [ img . width ( ) * img . height ( ) ] ;
image : : image_to_rgba ( img , px ) ;
updateImageTexture ( satdump_logo_texture , ( uint32_t * ) px , img . width ( ) , img . height ( ) ) ;
delete [ ] px ;
}
2026-02-10 18:28:35 +01:00
# if 1
2025-08-02 14:56:42 +02:00
std : : pair < float , float > dims = { ImGui : : GetWindowWidth ( ) , ImGui : : GetWindowHeight ( ) } ;
float scale = backend : : device_scale ;
2026-03-12 07:55:22 +01:00
std : : string title = lego_debug_mode ? //
std : : string { 0x57 , 0x65 , 0x6c , 0x63 , 0x6f , 0x6d , 0x65 , 0x20 , 0x74 , 0x6f , 0x20 , 0x42 , 0x75 , 0x67 , 0x44 , 0x75 , 0x6d , 0x70 , ' ? ' } //
: " Welcome to SatDump! " ;
2025-08-02 14:56:42 +02:00
2025-08-01 00:39:05 +02:00
{
ImGui : : PushFont ( style : : bigFont ) ;
ImVec2 title_size = ImGui : : CalcTextSize ( title . c_str ( ) ) ;
2025-08-05 19:07:45 +02:00
ImGui : : SetCursorPos ( { ( ( float ) dims . first / 2 ) - ( 75 * scale ) , ( ( float ) dims . second / 2.f ) - title_size . y - ( 90 * scale ) } ) ;
2025-08-01 00:39:05 +02:00
ImGui : : Image ( ( void * ) satdump_logo_texture , ImVec2 ( 150 * scale , 150 * scale ) ) ;
2025-08-05 19:07:45 +02:00
ImGui : : SetCursorPos ( { ( ( float ) dims . first / 2 ) - ( title_size . x / 2 ) , ( ( float ) dims . second / 2.0f ) - title_size . y + ( 75 * scale ) } ) ;
2025-08-01 00:39:05 +02:00
ImGui : : TextUnformatted ( title . c_str ( ) ) ;
ImGui : : PopFont ( ) ;
2025-08-07 07:28:53 +02:00
float last_pos = 0 ;
2025-08-05 19:07:45 +02:00
for ( int p = 0 , i = 0 ; p < tip_of_the_day . length ( ) ; )
{
int cutLength = 0 ;
2026-03-27 18:03:11 +01:00
2026-03-27 13:08:00 +01:00
for ( int pp = p + std : : min < int > ( 50 , tip_of_the_day . length ( ) - p ) ; pp < tip_of_the_day . length ( ) ; pp + + )
2025-08-05 19:07:45 +02:00
{
cutLength = pp ;
if ( tip_of_the_day [ pp ] = = ' ' )
break ;
}
2026-03-27 18:03:11 +01:00
2026-03-27 13:08:00 +01:00
if ( tip_of_the_day . size ( ) > ( p + cutLength ) )
{
if ( tip_of_the_day [ p + cutLength ] = = ' . ' | | tip_of_the_day [ p + cutLength ] = = ' ? ' | | tip_of_the_day [ p + cutLength ] = = ' ! ' )
cutLength + + ;
}
2026-03-27 18:03:11 +01:00
if ( cutLength = = 0 )
cutLength = tip_of_the_day . length ( ) ;
2025-08-05 19:07:45 +02:00
std : : string line = tip_of_the_day . substr ( p , cutLength - p ) ;
ImVec2 line_size = ImGui : : CalcTextSize ( line . c_str ( ) ) ;
2025-08-07 07:28:53 +02:00
last_pos = ( ( float ) dims . second / 2 ) + ( ( 80 + i * 20 ) * scale ) ;
ImGui : : SetCursorPos ( { ( ( float ) dims . first / 2 ) - ( line_size . x / 2 ) , last_pos } ) ;
2026-03-05 21:35:34 +01:00
# ifdef BUILD_IS_DEBUG
ImGui : : TextColored ( ImColor ( 255 , 0 , 0 ) , " %s " , line . c_str ( ) ) ;
# else
2025-08-05 19:07:45 +02:00
ImGui : : TextDisabled ( " %s " , line . c_str ( ) ) ;
2026-03-05 21:35:34 +01:00
# endif
2025-08-05 19:07:45 +02:00
p + = line . size ( ) ;
i + + ;
2026-03-27 18:03:11 +01:00
// Avoid getting stuck in a loop, just in case
if ( i > 20 )
break ;
2025-08-05 19:07:45 +02:00
}
2025-08-05 23:16:31 +02:00
{
ImVec2 line_size = ImGui : : CalcTextSize ( " Start Processing " ) ;
2025-08-07 07:28:53 +02:00
ImGui : : SetCursorPos ( { ( ( float ) dims . first / 2 ) - ( line_size . x / 2 ) , last_pos + ( 26 * 1 ) * scale } ) ;
2025-08-12 22:43:29 +02:00
if ( ImGui : : Button ( " Start Processing " ) )
2025-12-08 17:50:52 +01:00
eventBus - > fire_event < ShowProcesingEvent > ( { } ) ; // TODOREWORK do not bind this directly.
2025-08-05 23:16:31 +02:00
}
2026-03-12 07:55:22 +01:00
if ( lego_debug_mode )
{
ImVec2 line_size = ImGui : : CalcTextSize ( " Add New Recorder " ) ;
ImGui : : SetCursorPos ( { ( ( float ) dims . first / 2 ) - ( line_size . x / 2 ) , last_pos + ( 26 * 2 ) * scale } ) ;
if ( ImGui : : Button ( " Add Buggy Recorder " ) )
2026-04-06 17:16:27 +02:00
// addHandler(std::make_shared<handlers::NewRecHandler>());
addHandler ( std : : make_shared < handlers : : RecFrontendHandler > ( std : : make_shared < handlers : : RecBackend > ( ) ) ) ;
2026-03-12 07:55:22 +01:00
}
else
2025-08-05 23:16:31 +02:00
{
ImVec2 line_size = ImGui : : CalcTextSize ( " Add Recorder " ) ;
2025-08-07 07:28:53 +02:00
ImGui : : SetCursorPos ( { ( ( float ) dims . first / 2 ) - ( line_size . x / 2 ) , last_pos + ( 26 * 2 ) * scale } ) ;
2025-08-12 22:43:29 +02:00
if ( ImGui : : Button ( " Add Recorder " ) )
2025-12-08 17:50:52 +01:00
eventBus - > fire_event < AddRecorderEvent > ( { } ) ; // TODOREWORK do not bind this directly.
2025-08-05 23:16:31 +02:00
}
2025-08-01 00:39:05 +02:00
}
2025-08-02 14:56:42 +02:00
# endif
2025-08-01 00:39:05 +02:00
ImGui : : EndChild ( ) ;
}
}
2024-12-29 20:13:58 +01:00
2025-07-23 12:21:02 +02:00
void ExplorerApplication : : draw ( )
2024-12-29 20:13:58 +01:00
{
2025-07-05 22:22:17 +02:00
drawMenuBar ( ) ;
2025-06-22 17:18:53 +02:00
ImVec2 explorer_size = ImGui : : GetContentRegionAvail ( ) ;
2026-01-30 20:24:27 +01:00
if ( explorer_size . x < 0.0f | | explorer_size . y < 0.0f )
return ;
2024-12-29 20:13:58 +01:00
2026-01-23 21:29:48 +01:00
if ( show_panel )
2024-12-29 20:13:58 +01:00
{
2026-01-23 21:29:48 +01:00
if ( ImGui : : BeginTable ( " ##explorer_table " , 2 , ImGuiTableFlags_Resizable | ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_BordersInnerV ) )
{
ImGui : : TableSetupColumn ( " ##panel_v " , ImGuiTableColumnFlags_None , explorer_size . x * panel_ratio ) ;
ImGui : : TableSetupColumn ( " ##view " , ImGuiTableColumnFlags_None , explorer_size . x * ( 1.0f - panel_ratio ) ) ;
ImGui : : TableNextColumn ( ) ;
float left_width = ImGui : : GetColumnWidth ( 0 ) ;
float right_width = explorer_size . x - left_width ;
if ( left_width ! = last_width & & last_width ! = - 1 )
panel_ratio = left_width / explorer_size . x ;
last_width = left_width ;
2026-04-03 12:53:14 +02:00
ImGui : : BeginChild ( " ExplorerChildPanel " , { left_width , float ( explorer_size . y ) } , false ) ;
2026-01-23 21:29:48 +01:00
drawPanel ( ) ;
ImGui : : EndChild ( ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : BeginGroup ( ) ;
2024-12-29 20:13:58 +01:00
2026-01-23 21:29:48 +01:00
if ( curr_handler )
curr_handler - > drawContents ( { float ( right_width - 9 * ui_scale ) , float ( explorer_size . y ) } ) ;
else
drawContents ( ) ;
ImGui : : EndGroup ( ) ;
ImGui : : EndTable ( ) ;
}
}
else
{
2024-12-31 17:01:12 +01:00
ImGui : : BeginGroup ( ) ;
2024-12-29 20:13:58 +01:00
2024-12-31 17:01:12 +01:00
if ( curr_handler )
2026-01-24 00:04:14 +01:00
curr_handler - > drawContents ( { float ( explorer_size . x ) , float ( explorer_size . y ) } ) ;
2025-01-02 17:04:32 +01:00
else
drawContents ( ) ;
2024-12-29 20:13:58 +01:00
2024-12-31 17:01:12 +01:00
ImGui : : EndGroup ( ) ;
2024-12-29 20:13:58 +01:00
}
}
2025-01-03 10:03:04 +01:00
2025-06-22 17:18:53 +02:00
void ExplorerApplication : : tryOpenFileInExplorer ( std : : string path )
2025-01-03 10:03:04 +01:00
{
auto fun = [ this , path ] ( )
{
2025-07-14 21:21:55 +02:00
eventBus - > fire_event < SetIsProcessingEvent > ( { } ) ;
2025-04-06 10:27:54 +02:00
try
2025-01-03 10:03:04 +01:00
{
2025-07-24 21:55:57 +02:00
// Get available loaders
std : : vector < std : : pair < std : : string , std : : function < void ( std : : string , ExplorerApplication * ) > > > loaders ;
2025-01-03 10:03:04 +01:00
2025-07-24 21:55:57 +02:00
// Default stuff
2025-04-06 10:27:54 +02:00
if ( std : : filesystem : : path ( path ) . extension ( ) . string ( ) = = " .cbor " )
2025-07-24 21:55:57 +02:00
loaders . push_back ( { " Product Loader " , [ ] ( std : : string path , ExplorerApplication * e )
{
logger - > trace ( " Explorer loading product " + path ) ;
try
{
auto prod_h = handlers : : getProductHandlerForProduct ( products : : loadProduct ( path ) ) ;
e - > addHandler ( prod_h ) ;
}
catch ( std : : exception & e )
{
logger - > error ( " Error loading product! Maybe not a valid product? (Reminder : Pre-2.0.0 products are NOT compatible with 2.0.0) Details : %s " ,
e . what ( ) ) ;
}
} } ) ;
2025-04-06 10:27:54 +02:00
else if ( std : : filesystem : : path ( path ) . extension ( ) . string ( ) = = " .json " )
2025-07-24 21:55:57 +02:00
loaders . push_back (
{ " Dataset Loader " , [ ] ( std : : string path , ExplorerApplication * e )
{
logger - > trace ( " Viewer loading dataset " + path ) ;
try
{
products : : DataSet dataset ;
dataset . load ( path ) ;
std : : shared_ptr < handlers : : DatasetHandler > dat_h = std : : make_shared < handlers : : DatasetHandler > ( std : : filesystem : : path ( path ) . parent_path ( ) . string ( ) , dataset ) ;
e - > addHandler ( dat_h ) ;
}
catch ( std : : exception & e )
{
logger - > error ( " Error loading dataset! Maybe not a valid dataset? (Reminder : Pre-2.0.0 datasets are NOT compatible with 2.0.0) Details : %s " , e . what ( ) ) ;
}
} } ) ;
else if ( std : : filesystem : : path ( path ) . extension ( ) . string ( ) = = " .shp " )
loaders . push_back ( { " Shapefile Loader " , [ ] ( std : : string path , ExplorerApplication * e )
{
logger - > trace ( " Viewer loading shapefile " + path ) ;
e - > addHandler ( std : : make_shared < handlers : : ShapefileHandler > ( path ) ) ;
} } ) ;
2026-01-22 19:11:05 +01:00
else if ( std : : filesystem : : path ( path ) . extension ( ) . string ( ) = = " .satdump_dsp_flowgraph " )
loaders . push_back ( { " DSP Flowgraph Loader " , [ ] ( std : : string path , ExplorerApplication * e )
{
logger - > trace ( " Viewer loading DSP flowgraph " + path ) ;
2026-01-23 21:29:48 +01:00
e - > addHandler ( std : : make_shared < handlers : : DSPFlowGraphHandler > ( path ) , true ) ;
2026-01-22 19:11:05 +01:00
} } ) ;
2025-08-25 20:01:59 +02:00
// Plugin loaders
eventBus - > fire_event < ExplorerRequestFileLoad > ( { path , loaders } ) ;
# if 1 // TODOREWORK ADD MENU
if ( loaders . size ( ) = = 0 )
2025-07-24 21:55:57 +02:00
loaders . push_back ( { " Image Loader " , [ ] ( std : : string path , ExplorerApplication * e )
{
logger - > trace ( " Viewer loading image " + path ) ;
image : : Image img ;
image : : load_img ( img , path ) ;
if ( img . size ( ) > 0 )
e - > addHandler ( std : : make_shared < handlers : : ImageHandler > ( img , std : : filesystem : : path ( path ) . stem ( ) . string ( ) ) ) ;
else
logger - > error ( " Could not open this file as image! " ) ;
} } ) ;
# endif
// Load it
if ( loaders . size ( ) = = 1 )
2025-01-03 22:43:40 +01:00
{
2025-07-24 21:55:57 +02:00
loaders [ 0 ] . second ( path , this ) ;
2025-01-03 22:43:40 +01:00
}
2025-07-24 21:55:57 +02:00
else if ( loaders . size ( ) > 1 )
2025-01-03 22:43:40 +01:00
{
2025-08-25 19:58:55 +02:00
logger - > error ( " More than one loader available! TODO SELECTION MENU! " ) ;
loaders [ loaders . size ( ) - 1 ] . second ( path , this ) ;
2025-01-03 22:43:40 +01:00
}
2025-04-06 10:27:54 +02:00
else
2025-01-03 22:43:40 +01:00
{
2025-07-24 21:55:57 +02:00
throw satdump_exception ( " No loader found for file : " + path + " ! " ) ;
2025-01-03 22:43:40 +01:00
}
2025-01-03 10:03:04 +01:00
}
2025-04-06 10:27:54 +02:00
catch ( std : : exception & e )
2025-02-03 07:52:21 +01:00
{
2025-04-06 10:27:54 +02:00
logger - > error ( " Error opening file! => %s " , e . what ( ) ) ;
2025-02-03 07:52:21 +01:00
}
2025-07-14 21:21:55 +02:00
eventBus - > fire_event < SetIsDoneProcessingEvent > ( { } ) ;
2025-01-03 10:03:04 +01:00
} ;
2025-07-18 12:19:40 +02:00
file_open_queue . push ( fun ) ;
2025-01-03 10:03:04 +01:00
}
2025-08-13 13:52:48 +02:00
void ExplorerApplication : : tryOpenSomethingInExplorer ( std : : function < void ( ExplorerApplication * ) > f )
{
auto fun = [ f , this ] ( )
{
eventBus - > fire_event < SetIsProcessingEvent > ( { } ) ;
try
{
f ( this ) ;
}
catch ( std : : exception & e )
{
logger - > error ( " Error opening file! => %s " , e . what ( ) ) ;
}
eventBus - > fire_event < SetIsDoneProcessingEvent > ( { } ) ;
} ;
file_open_queue . push ( fun ) ;
}
2025-06-22 17:18:53 +02:00
} // namespace explorer
2025-04-15 19:06:12 +01:00
} ; // namespace satdump