mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-10-27 16:38:20 +03:00
Improvements when opening binary files from drag and drop and from the tree-view (SpartanJ/ecode#589).
Fixes a bug that prevented signature help to not be displayed.
This commit is contained in:
@@ -37,9 +37,11 @@ struct DocumentContentChange {
|
||||
|
||||
class EE_API TextDocument {
|
||||
public:
|
||||
static bool isTextDocummentCommand( std::string_view cmd );
|
||||
static bool isTextDocummentCommand( std::string_view cmd );
|
||||
|
||||
static bool isTextDocummentCommand( String::HashType cmdHash );
|
||||
static bool isTextDocummentCommand( String::HashType cmdHash );
|
||||
|
||||
static bool fileMightBeBinary( const std::string& file );
|
||||
|
||||
enum class UndoRedo { Undo, Redo };
|
||||
|
||||
|
||||
@@ -28,6 +28,34 @@ static constexpr char DEFAULT_NON_WORD_CHARS[] = " \t\n/\\()\"':,.;<>~!@#$%^&*|+
|
||||
|
||||
static UnorderedSet<String::HashType> TEXT_DOCUMENT_COMMANDS = {};
|
||||
|
||||
bool TextDocument::fileMightBeBinary( const std::string& file ) {
|
||||
static constexpr std::array<char, 4> BINARY_STR = { 0, 0, 0, 0 };
|
||||
static constexpr size_t MAX_READ = 4096;
|
||||
|
||||
IOStreamFile f( file );
|
||||
if ( !f.isOpen() ) {
|
||||
// Handle file opening failure (e.g., return false or throw)
|
||||
return false;
|
||||
}
|
||||
|
||||
std::array<char, MAX_READ> buffer;
|
||||
size_t bytesToRead = std::min<size_t>( MAX_READ, f.getSize() );
|
||||
if ( bytesToRead < BINARY_STR.size() ) {
|
||||
// File is too small to contain the binary sequence
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t bytesRead = f.read( buffer.data(), bytesToRead );
|
||||
if ( bytesRead < BINARY_STR.size() ) {
|
||||
// Not enough bytes read to contain the binary sequence
|
||||
return false;
|
||||
}
|
||||
|
||||
auto res = std::search( buffer.begin(), buffer.begin() + bytesRead, BINARY_STR.begin(),
|
||||
BINARY_STR.end() );
|
||||
return res != buffer.begin() + bytesRead;
|
||||
}
|
||||
|
||||
bool TextDocument::isTextDocummentCommand( std::string_view cmd ) {
|
||||
return TEXT_DOCUMENT_COMMANDS.contains( String::hash( cmd ) );
|
||||
}
|
||||
|
||||
+77
-21
@@ -2230,21 +2230,32 @@ void App::loadImageFromPath( const std::string& path ) {
|
||||
loadImageFromMedium( path, false );
|
||||
}
|
||||
|
||||
static bool isVideoExtension( std::string_view ext ) {
|
||||
static constexpr std::array<std::string_view, 10> videoExtensions = {
|
||||
"mp4", "mov", "mkv", "avi", "wmv", "webm", "flv", "mpg", "mpeg", "m4v" };
|
||||
for ( const auto& videoExt : videoExtensions )
|
||||
if ( String::iequals( ext, videoExt ) )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isDocumentExtension( std::string_view ext ) {
|
||||
static constexpr std::array<std::string_view, 3> videoExtensions = { "doc", "docx", "pdf" };
|
||||
for ( const auto& videoExt : videoExtensions )
|
||||
if ( String::iequals( ext, videoExt ) )
|
||||
return true;
|
||||
return false;
|
||||
void App::openFileFromPath( const std::string& path ) {
|
||||
std::string ext = FileSystem::fileExtension( path );
|
||||
bool canOpenBinaryFile = PathHelper::isOpenExternalExtension( ext );
|
||||
if ( !canOpenBinaryFile && TextDocument::fileMightBeBinary( path ) ) {
|
||||
auto msgBox = UIMessageBox::New(
|
||||
UIMessageBox::YES_NO,
|
||||
i18n( "open_binary_file_warning",
|
||||
"File looks like a binary file. Are you sure "
|
||||
"you want to open it as a document?\nOtherwise it will try to open the "
|
||||
"file with an external application." ) );
|
||||
msgBox->getButtonOK()->setText( i18n( "open_as_document", "Open as document" ) );
|
||||
msgBox->getButtonOK()->getIcon()->setVisible( false );
|
||||
msgBox->getButtonCancel()->setText( i18n( "open_externally", "Open externally" ) );
|
||||
msgBox->getButtonCancel()->getIcon()->setVisible( false );
|
||||
msgBox->on( Event::OnConfirm, [this, path]( auto ) { loadFileFromPath( path ); } );
|
||||
msgBox->on( Event::OnCancel, [path]( auto ) {
|
||||
FileInfo f( path );
|
||||
if ( f.isExecutable() )
|
||||
Sys::execute( path );
|
||||
else
|
||||
Engine::instance()->openURI( path );
|
||||
} );
|
||||
msgBox->showWhenReady();
|
||||
} else {
|
||||
loadFileFromPath( path );
|
||||
}
|
||||
}
|
||||
|
||||
bool App::loadFileFromPath(
|
||||
@@ -2263,7 +2274,7 @@ bool App::loadFileFromPath(
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( isVideoExtension( ext ) || isDocumentExtension( ext ) ) {
|
||||
if ( PathHelper::isOpenExternalExtension( ext ) ) {
|
||||
Engine::instance()->openURI( path );
|
||||
} else if ( Image::isImageExtension( path ) && Image::isImage( path ) && ext != "svg" ) {
|
||||
loadImageFromPath( path );
|
||||
@@ -3010,7 +3021,7 @@ void App::initProjectTreeViewUI() {
|
||||
if ( !tab ) {
|
||||
FileInfo fileInfo( path );
|
||||
if ( fileInfo.exists() && fileInfo.isRegularFile() )
|
||||
loadFileFromPath( path );
|
||||
openFileFromPath( path );
|
||||
} else {
|
||||
tab->getTabWidget()->setTabSelected( tab );
|
||||
}
|
||||
@@ -3797,10 +3808,55 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe
|
||||
if ( onlyDirectories ) {
|
||||
loadFolder( mPathsToLoad[lastDirIdx] );
|
||||
} else {
|
||||
// Load only files even if there are directories
|
||||
for ( const auto& file : mPathsToLoad ) {
|
||||
if ( !FileSystem::isDirectory( file ) )
|
||||
onFileDropped( file );
|
||||
int mightBeBinaryCount = 0;
|
||||
for ( const auto& file : mPathsToLoad )
|
||||
if ( !FileSystem::isDirectory( file ) &&
|
||||
TextDocument::fileMightBeBinary( file ) )
|
||||
mightBeBinaryCount++;
|
||||
|
||||
if ( mightBeBinaryCount ) {
|
||||
if ( mightBeBinaryCount == 1 && mPathsToLoad.size() == 1 ) {
|
||||
FileInfo f( mPathsToLoad[0] );
|
||||
if ( f.isExecutable() )
|
||||
Sys::execute( mPathsToLoad[0] );
|
||||
else
|
||||
Engine::instance()->openURI( mPathsToLoad[0] );
|
||||
} else {
|
||||
UIMessageBox* msgBox = UIMessageBox::New(
|
||||
UIMessageBox::OK_CANCEL,
|
||||
i18n( "dropped_binary_files_open_warn",
|
||||
"Some of the files seem to be binary.\nDo you want to "
|
||||
"open them as document? Otherwise they will be ignored "
|
||||
"for loading." ) );
|
||||
msgBox->getButtonOK()->setText( i18n( "open", "Open" ) );
|
||||
msgBox->getButtonOK()->getIcon()->setVisible( false );
|
||||
msgBox->getButtonCancel()->setText( i18n( "ignore", "Ignore" ) );
|
||||
msgBox->getButtonCancel()->getIcon()->setVisible( false );
|
||||
msgBox->on( Event::OnConfirm,
|
||||
[this, pathsToLoad = mPathsToLoad]( const Event* ) {
|
||||
for ( const auto& file : pathsToLoad ) {
|
||||
if ( !FileSystem::isDirectory( file ) )
|
||||
onFileDropped( file );
|
||||
}
|
||||
} );
|
||||
msgBox->on( Event::OnCancel,
|
||||
[this, pathsToLoad = mPathsToLoad]( const Event* ) {
|
||||
for ( const auto& file : pathsToLoad ) {
|
||||
if ( !FileSystem::isDirectory( file ) &&
|
||||
!TextDocument::fileMightBeBinary( file ) )
|
||||
onFileDropped( file );
|
||||
}
|
||||
} );
|
||||
msgBox->setTitle( i18n( "warning", "Warning" ) );
|
||||
msgBox->center();
|
||||
msgBox->showWhenReady();
|
||||
}
|
||||
} else {
|
||||
// Load only files even if there are directories
|
||||
for ( const auto& file : mPathsToLoad ) {
|
||||
if ( !FileSystem::isDirectory( file ) )
|
||||
onFileDropped( file );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -88,6 +88,8 @@ class App : public UICodeEditorSplitter::Client, public PluginContextProvider {
|
||||
|
||||
std::shared_ptr<ThreadPool> getThreadPool() const;
|
||||
|
||||
void openFileFromPath( const std::string& path );
|
||||
|
||||
bool loadFileFromPath( std::string path, bool inNewTab = true,
|
||||
UICodeEditor* codeEditor = nullptr,
|
||||
std::function<void( UICodeEditor*, const std::string& )> onLoaded =
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "pathhelper.hpp"
|
||||
|
||||
namespace ecode {
|
||||
|
||||
bool PathHelper::isVideoExtension( std::string_view ext ) {
|
||||
static constexpr std::array<std::string_view, 10> extensions = {
|
||||
"mp4", "mov", "mkv", "avi", "wmv", "webm", "flv", "mpg", "mpeg", "m4v" };
|
||||
for ( const auto& cext : extensions )
|
||||
if ( String::iequals( ext, cext ) )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PathHelper::isDocumentExtension( std::string_view ext ) {
|
||||
static constexpr std::array<std::string_view, 5> extensions = { "doc", "docx", "pdf", "xls",
|
||||
"xlsx" };
|
||||
for ( const auto& cext : extensions )
|
||||
if ( String::iequals( ext, cext ) )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PathHelper::isOpenExternalExtension( std::string_view ext ) {
|
||||
return isVideoExtension( ext ) || isDocumentExtension( ext );
|
||||
}
|
||||
|
||||
} // namespace ecode
|
||||
@@ -51,6 +51,14 @@ template <typename T> static std::pair<T, TextPosition> getPathAndPosition( cons
|
||||
return { path, { 0, 0 } };
|
||||
}
|
||||
|
||||
struct PathHelper {
|
||||
static bool isVideoExtension( std::string_view ext );
|
||||
|
||||
static bool isDocumentExtension( std::string_view ext );
|
||||
|
||||
static bool isOpenExternalExtension( std::string_view ext );
|
||||
};
|
||||
|
||||
} // namespace ecode
|
||||
|
||||
#endif // ECODE_PATHHELPER_HPP
|
||||
|
||||
@@ -904,6 +904,8 @@ AutoCompletePlugin::processSignatureHelp( const LSPSignatureHelp& signatureHelp
|
||||
editor->runOnMainThread( [this, editor, signatures = std::move( signatures )] {
|
||||
mSignatureHelpVisible = true;
|
||||
mSignatureHelp = signatures;
|
||||
if ( mSignatureHelpSelected >= static_cast<Int32>( mSignatureHelp.signatures.size() ) )
|
||||
mSignatureHelpSelected = 0;
|
||||
if ( mSignatureHelp.signatures.empty() )
|
||||
resetSignatureHelp();
|
||||
editor->invalidateDraw();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "settingsmenu.hpp"
|
||||
|
||||
#include <filesystem>
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
@@ -2354,7 +2355,7 @@ void SettingsMenu::createProjectTreeMenu( const FileInfo& file ) {
|
||||
} else if ( "new_folder" == id ) {
|
||||
mApp->newFolder( file );
|
||||
} else if ( "open_file" == id ) {
|
||||
mApp->loadFileFromPath( file.getFilepath() );
|
||||
mApp->openFileFromPath( file.getFilepath() );
|
||||
} else if ( "remove" == id ) {
|
||||
deleteFileDialog( file );
|
||||
} else if ( "duplicate_file" == id ) {
|
||||
@@ -2552,8 +2553,8 @@ UIMenu* SettingsMenu::createFontHintMenu() {
|
||||
|
||||
const auto fontHintMenuRefresh = [this] {
|
||||
const auto& cfg = mApp->getConfig();
|
||||
auto el =
|
||||
mFontHintMenu->find( "hint_" + FontTrueType::fontHintingToString( cfg.ui.fontHinting ) );
|
||||
auto el = mFontHintMenu->find( "hint_" +
|
||||
FontTrueType::fontHintingToString( cfg.ui.fontHinting ) );
|
||||
if ( el && el->isType( UI_TYPE_MENURADIOBUTTON ) )
|
||||
el->asType<UIMenuRadioButton>()->setActive( true );
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user