diff --git a/bin/assets/layouts/test.css b/bin/assets/layouts/test.css index d4513c4cb..37c362df4 100644 --- a/bin/assets/layouts/test.css +++ b/bin/assets/layouts/test.css @@ -90,7 +90,7 @@ ScrollBar { } Window { - window-flags: shadow; + window-flags: default|shadow; window-buttons-offset: -2dp 0; } diff --git a/bin/assets/ui/breeze.css b/bin/assets/ui/breeze.css index 302a599da..c5e248e24 100644 --- a/bin/assets/ui/breeze.css +++ b/bin/assets/ui/breeze.css @@ -681,7 +681,7 @@ Window { window-titlebar-size: 24dp 24dp; window-buttons-offset: -6dp 0dp; window-buttons-separation: 8dp; - window-flags: shadow; + window-flags: default|shadow; } Window::decoration { diff --git a/bin/assets/ui/uitheme.css b/bin/assets/ui/uitheme.css index 4d3a9b907..8eaf58d13 100644 --- a/bin/assets/ui/uitheme.css +++ b/bin/assets/ui/uitheme.css @@ -79,7 +79,7 @@ ScrollBar { } Window { - window-flags: shadow; + window-flags: default|shadow; window-buttons-offset: -2dp 0; } diff --git a/include/eepp/network/http.hpp b/include/eepp/network/http.hpp index 067e40d2a..89e924e35 100644 --- a/include/eepp/network/http.hpp +++ b/include/eepp/network/http.hpp @@ -185,6 +185,8 @@ class EE_API Http : NonCopyable { ContentReceived ///< Content received. }; + static std::string statusToString( Status status ); + /** @return Method from a method name string. */ static Method methodFromString( std::string methodString ); @@ -654,8 +656,10 @@ class EE_API Http : NonCopyable { const Request::FieldTable& headers = Request::FieldTable(), const std::string& body = "", const bool& validateCertificate = true, const URI& proxy = URI() ); - /** Creates an async HTTP Request using the global HTTP Client Pool */ - static void + /** Creates an async HTTP Request using the global HTTP Client Pool + ** @return The unique async request id + */ + static Uint64 requestAsync( const Http::AsyncResponseCallback& cb, const URI& uri, const Time& timeout = Time::Zero, Request::Method method = Request::Method::Get, const Request::ProgressCallback& progressCallback = Request::ProgressCallback(), @@ -663,15 +667,19 @@ class EE_API Http : NonCopyable { const std::string& body = "", const bool& validateCertificate = true, const URI& proxy = URI() ); - /** Creates an async HTTP GET Request using the global HTTP Client Pool */ - static void getAsync( + /** Creates an async HTTP GET Request using the global HTTP Client Pool + ** @return The unique async request id + */ + static Uint64 getAsync( const Http::AsyncResponseCallback& cb, const URI& uri, const Time& timeout = Time::Zero, const Request::ProgressCallback& progressCallback = Request::ProgressCallback(), const Request::FieldTable& headers = Request::FieldTable(), const std::string& body = "", const bool& validateCertificate = true, const URI& proxy = URI() ); - /** Creates an async HTTP POST Request using the global HTTP Client Pool */ - static void postAsync( + /** Creates an async HTTP POST Request using the global HTTP Client Pool + ** @return The unique async request id + */ + static Uint64 postAsync( const Http::AsyncResponseCallback& cb, const URI& uri, const Time& timeout = Time::Zero, const Request::ProgressCallback& progressCallback = Request::ProgressCallback(), const Request::FieldTable& headers = Request::FieldTable(), const std::string& body = "", diff --git a/include/eepp/network/uri.hpp b/include/eepp/network/uri.hpp index 832570c8e..36348e506 100644 --- a/include/eepp/network/uri.hpp +++ b/include/eepp/network/uri.hpp @@ -96,6 +96,8 @@ class EE_API URI { bool operator<( const URI& url ) const; + static std::string getTempPathFromURI( const URI& uri ); + /** Swaps the URI with another one. */ void swap( URI& uri ); diff --git a/include/eepp/scene/scenemanager.hpp b/include/eepp/scene/scenemanager.hpp index 194a88d58..bdb02de4b 100644 --- a/include/eepp/scene/scenemanager.hpp +++ b/include/eepp/scene/scenemanager.hpp @@ -19,6 +19,8 @@ class SceneNode; class EE_API SceneManager { SINGLETON_DECLARE_HEADERS( SceneManager ) public: + static bool isActive(); + SceneManager(); ~SceneManager(); diff --git a/include/eepp/ui/uiwindow.hpp b/include/eepp/ui/uiwindow.hpp index a6902fdc5..bfa47e29a 100644 --- a/include/eepp/ui/uiwindow.hpp +++ b/include/eepp/ui/uiwindow.hpp @@ -200,6 +200,10 @@ class EE_API UIWindow : public UIWidget { void executeKeyBindingCommand( const std::string& command ); + void setStealFocusOnShow( bool steal ); + + bool stealsFocusOnShow() const; + protected: enum UI_RESIZE_TYPE { RESIZE_NONE, @@ -236,6 +240,7 @@ class EE_API UIWindow : public UIWidget { bool mFrameBufferBound; bool mWindowReady{ false }; bool mShowWhenReady{ false }; + bool mStealFocusOnShow{ true }; bool mClosing{ false }; KeyBindings mKeyBindings; diff --git a/include/eepp/window/engine.hpp b/include/eepp/window/engine.hpp index 075c7a49e..752ccb166 100644 --- a/include/eepp/window/engine.hpp +++ b/include/eepp/window/engine.hpp @@ -152,6 +152,7 @@ class EE_API Engine { std::map mWindows; EE::Window::Window* mWindow; bool mSharedGLContext; + bool mIsShuttingDown{ false }; PlatformHelper* mPlatformHelper; Pack* mZip; DisplayManager* mDisplayManager; diff --git a/src/eepp/graphics/scopedtexture.cpp b/src/eepp/graphics/scopedtexture.cpp index 137a78d12..a130d764a 100644 --- a/src/eepp/graphics/scopedtexture.cpp +++ b/src/eepp/graphics/scopedtexture.cpp @@ -1,12 +1,19 @@ #include #include #include +#include + +using namespace EE::Window; namespace EE { namespace Graphics { namespace Private { ScopedTexture::ScopedTexture( int textureBind ) : mTextureBinded( 0 ), mTextureToBind( textureBind ) { - glGetIntegerv( GL_TEXTURE_BINDING_2D, &mTextureBinded ); + if ( Engine::isEngineRunning() ) { + glGetIntegerv( GL_TEXTURE_BINDING_2D, &mTextureBinded ); + } else { + mTextureBinded = textureBind; + } if ( mTextureToBind > 0 && mTextureBinded != mTextureToBind ) GLi->bindTexture( GL_TEXTURE_2D, mTextureToBind ); diff --git a/src/eepp/graphics/textureloader.cpp b/src/eepp/graphics/textureloader.cpp index b74ad4ef4..abf7e318a 100644 --- a/src/eepp/graphics/textureloader.cpp +++ b/src/eepp/graphics/textureloader.cpp @@ -282,7 +282,7 @@ void TextureLoader::notifyLoaded() { } void TextureLoader::loadFromPixels() { - if ( !mLoaded && mTexLoaded ) { + if ( !mLoaded && mTexLoaded && Engine::isEngineRunning() ) { Uint32 tTexId = 0; if ( NULL != mPixels ) { @@ -305,6 +305,9 @@ void TextureLoader::loadFromPixels() { { ScopedTexture scopedTexture; + if ( !Engine::isEngineRunning() ) + return; + if ( mDirectUpload ) { if ( Image::Format::DDS == mImgType ) { tTexId = SOIL_direct_load_DDS_from_memory( mPixels, mSize, diff --git a/src/eepp/network/http.cpp b/src/eepp/network/http.cpp index 3c295f479..a79bc6693 100644 --- a/src/eepp/network/http.cpp +++ b/src/eepp/network/http.cpp @@ -27,6 +27,20 @@ namespace EE { namespace Network { #define PACKET_BUFFER_SIZE ( 16384 ) +std::string Http::Request::statusToString( Http::Request::Status status ) { + switch ( status ) { + case Connected: + return "Connected"; + case Sent: + return "Sent"; + case HeaderReceived: + return "HeaderReceived"; + case ContentReceived: + return "ContentReceived"; + } + return ""; +} + Http::Request::Method Http::Request::methodFromString( std::string methodString ) { String::toLowerInPlace( methodString ); if ( "get" == methodString ) @@ -610,11 +624,11 @@ Http::Response Http::post( const URI& uri, const Time& timeout, validateCertificate, proxy ); } -void Http::requestAsync( const Http::AsyncResponseCallback& cb, const URI& uri, const Time& timeout, - Request::Method method, - const Http::Request::ProgressCallback& progressCallback, - const Http::Request::FieldTable& headers, const std::string& body, - const bool& validateCertificate, const URI& proxy ) { +Uint64 Http::requestAsync( const Http::AsyncResponseCallback& cb, const URI& uri, + const Time& timeout, Request::Method method, + const Http::Request::ProgressCallback& progressCallback, + const Http::Request::FieldTable& headers, const std::string& body, + const bool& validateCertificate, const URI& proxy ) { auto http = sGlobalHttpPool.get( uri, proxy ); Request request( uri.getPathAndQuery(), method, body, validateCertificate, validateCertificate, true, true ); @@ -623,23 +637,23 @@ void Http::requestAsync( const Http::AsyncResponseCallback& cb, const URI& uri, for ( const auto& field : headers ) request.setField( field.first, field.second ); - http->sendAsyncRequest( cb, request, timeout ); + return http->sendAsyncRequest( cb, request, timeout ); } -void Http::getAsync( const Http::AsyncResponseCallback& cb, const URI& uri, const Time& timeout, - const Http::Request::ProgressCallback& progressCallback, - const Http::Request::FieldTable& headers, const std::string& body, - const bool& validateCertificate, const URI& proxy ) { - requestAsync( cb, uri, timeout, Request::Method::Get, progressCallback, headers, body, - validateCertificate, proxy ); +Uint64 Http::getAsync( const Http::AsyncResponseCallback& cb, const URI& uri, const Time& timeout, + const Http::Request::ProgressCallback& progressCallback, + const Http::Request::FieldTable& headers, const std::string& body, + const bool& validateCertificate, const URI& proxy ) { + return requestAsync( cb, uri, timeout, Request::Method::Get, progressCallback, headers, body, + validateCertificate, proxy ); } -void Http::postAsync( const Http::AsyncResponseCallback& cb, const URI& uri, const Time& timeout, - const Http::Request::ProgressCallback& progressCallback, - const Http::Request::FieldTable& headers, const std::string& body, - const bool& validateCertificate, const URI& proxy ) { - requestAsync( cb, uri, timeout, Request::Method::Post, progressCallback, headers, body, - validateCertificate, proxy ); +Uint64 Http::postAsync( const Http::AsyncResponseCallback& cb, const URI& uri, const Time& timeout, + const Http::Request::ProgressCallback& progressCallback, + const Http::Request::FieldTable& headers, const std::string& body, + const bool& validateCertificate, const URI& proxy ) { + return requestAsync( cb, uri, timeout, Request::Method::Post, progressCallback, headers, body, + validateCertificate, proxy ); } Http::Http() : mConnection( NULL ), mHost(), mPort( 0 ), mIsSSL( false ), mHostSolved( false ) {} diff --git a/src/eepp/network/uri.cpp b/src/eepp/network/uri.cpp index d911e24c4..910090abf 100644 --- a/src/eepp/network/uri.cpp +++ b/src/eepp/network/uri.cpp @@ -1,4 +1,7 @@ #include +#include + +using namespace EE::System; namespace EE { namespace Network { @@ -21,6 +24,14 @@ const std::string URI::RESERVED_QUERY = "#"; const std::string URI::RESERVED_FRAGMENT = ""; const std::string URI::ILLEGAL = "%<>{}|\\\"^`"; +std::string URI::getTempPathFromURI( const URI& uri ) { + std::string lastSegment( uri.getLastPathSegment() ); + std::string name( String::randString( 8 ) + + ( lastSegment.empty() ? ".txt" : "." + lastSegment ) ); + std::string tmpPath( Sys::getTempPath() + name ); + return tmpPath; +} + URI::URI() : mPort( 0 ) {} URI::URI( const std::string& uri ) : mPort( 0 ) { diff --git a/src/eepp/scene/scenemanager.cpp b/src/eepp/scene/scenemanager.cpp index 62f997009..e9c6bb97b 100644 --- a/src/eepp/scene/scenemanager.cpp +++ b/src/eepp/scene/scenemanager.cpp @@ -2,11 +2,17 @@ #include #include #include +#include namespace EE { namespace Scene { SINGLETON_DECLARE_IMPLEMENTATION( SceneManager ) +bool SceneManager::isActive() { + return EE::Window::Engine::isEngineRunning() && SceneManager::existsSingleton() && + !SceneManager::instance()->isShuttingDown(); +} + SceneManager::SceneManager() : mUISceneNode( NULL ), mIsShuttingDown( false ) {} SceneManager::~SceneManager() { diff --git a/src/eepp/ui/doc/textdocument.cpp b/src/eepp/ui/doc/textdocument.cpp index f13534afc..bbbbf91c2 100644 --- a/src/eepp/ui/doc/textdocument.cpp +++ b/src/eepp/ui/doc/textdocument.cpp @@ -897,14 +897,6 @@ TextDocument::LoadStatus TextDocument::loadFromPack( Pack* pack, std::string fil return ret; } -static std::string getTempPathFromURI( const URI& uri ) { - std::string lastSegment( uri.getLastPathSegment() ); - std::string name( String::randString( 8 ) + - ( lastSegment.empty() ? ".txt" : "." + lastSegment ) ); - std::string tmpPath( Sys::getTempPath() + name ); - return tmpPath; -} - TextDocument::LoadStatus TextDocument::loadFromURL( const std::string& url, const Http::Request::FieldTable& headers ) { mLoading = true; @@ -919,7 +911,7 @@ TextDocument::LoadStatus TextDocument::loadFromURL( const std::string& url, Http::get( uri, Seconds( 10 ), nullptr, headers, "", true, Http::getEnvProxyURI() ); if ( response.getStatus() <= Http::Response::Ok ) { - std::string path( getTempPathFromURI( uri ) ); + std::string path( URI::getTempPathFromURI( uri ) ); FileSystem::fileWrite( path, (const Uint8*)response.getBody().c_str(), response.getBody().size() ); auto ret = loadFromFile( path ); @@ -950,7 +942,7 @@ bool TextDocument::loadAsyncFromURL( const std::string& url, [this, onLoaded = std::move( onLoaded ), uri = std::move( uri )]( const Http&, Http::Request&, Http::Response& response ) { if ( response.getStatus() <= Http::Response::Ok ) { - std::string path( getTempPathFromURI( uri ) ); + std::string path( URI::getTempPathFromURI( uri ) ); FileSystem::fileWrite( path, (const Uint8*)response.getBody().c_str(), response.getBody().size() ); if ( loadFromFile( path ) == LoadStatus::Loaded ) { diff --git a/src/eepp/ui/uiwindow.cpp b/src/eepp/ui/uiwindow.cpp index b1b27a56f..1ba1987cc 100644 --- a/src/eepp/ui/uiwindow.cpp +++ b/src/eepp/ui/uiwindow.cpp @@ -1053,7 +1053,8 @@ bool UIWindow::show() { setEnabled( true ); setVisible( true ); - setFocus(); + if ( mStealFocusOnShow ) + setFocus(); UIThemeManager* themeManager = getUISceneNode()->getUIThemeManager(); if ( themeManager->getDefaultEffectsEnabled() ) { @@ -1083,7 +1084,7 @@ bool UIWindow::hide( bool immediate ) { setVisible( false ); } - if ( NULL != mSceneNode ) + if ( NULL != mSceneNode && hasFocusWithin() ) mSceneNode->setFocus(); if ( NULL != mModalNode ) { @@ -1678,9 +1679,8 @@ bool UIWindow::applyProperty( const StyleSheetProperty& attribute ) { winflags |= UI_WIN_EPHEMERAL; } - /// TODO: WinFlags should replace old winFlags if ( winflags != mStyleConfig.WinFlags ) { - mStyleConfig.WinFlags |= winflags; + mStyleConfig.WinFlags = winflags; updateWinFlags(); } } @@ -1724,7 +1724,7 @@ bool UIWindow::applyProperty( const StyleSheetProperty& attribute ) { void UIWindow::loadFromXmlNode( const pugi::xml_node& node ) { UIWidget::loadFromXmlNode( node ); - + setStealFocusOnShow( false ); showWhenReady(); } @@ -1798,4 +1798,12 @@ void UIWindow::checkEphemeralClose() { closeWindow(); } +void UIWindow::setStealFocusOnShow( bool steal ) { + mStealFocusOnShow = steal; +} + +bool UIWindow::stealsFocusOnShow() const { + return mStealFocusOnShow; +} + }} // namespace EE::UI diff --git a/src/eepp/window/engine.cpp b/src/eepp/window/engine.cpp index d268fab1e..6ac13b7bc 100644 --- a/src/eepp/window/engine.cpp +++ b/src/eepp/window/engine.cpp @@ -64,6 +64,8 @@ Engine::Engine() : } Engine::~Engine() { + mIsShuttingDown = true; + GlobalBatchRenderer::destroySingleton(); NinePatchManager::destroySingleton(); @@ -243,7 +245,7 @@ bool Engine::isEngineRunning() { } bool Engine::isRunning() const { - return NULL != mWindow; + return NULL != mWindow && !mIsShuttingDown; } WindowBackend Engine::getDefaultBackend() const { diff --git a/src/tools/ecode/appconfig.cpp b/src/tools/ecode/appconfig.cpp index 3b8ec3135..5ae086b65 100644 --- a/src/tools/ecode/appconfig.cpp +++ b/src/tools/ecode/appconfig.cpp @@ -543,7 +543,7 @@ json AppConfig::saveNode( Node* node ) { } void AppConfig::saveProject( std::string projectFolder, UICodeEditorSplitter* editorSplitter, - const std::string& configPath, const ProjectDocumentConfig& docConfig, + const std::string& configPath, const ProjectConfig& docConfig, const ProjectBuildConfiguration& buildConfig, bool onlyIfNeeded, bool sessionSnapshot, PluginManager* pluginManager ) { FileSystem::dirAddSlashAtEnd( projectFolder ); @@ -817,7 +817,7 @@ void AppConfig::loadDocuments( UICodeEditorSplitter* editorSplitter, json j, } void AppConfig::loadProject( std::string projectFolder, UICodeEditorSplitter* editorSplitter, - const std::string& configPath, ProjectDocumentConfig& docConfig, + const std::string& configPath, ProjectConfig& docConfig, ecode::App* app, bool sessionSnapshot, PluginManager* pluginManager ) { FileSystem::dirAddSlashAtEnd( projectFolder ); std::string projectsPath( configPath + "projects" + FileSystem::getOSSlash() ); diff --git a/src/tools/ecode/appconfig.hpp b/src/tools/ecode/appconfig.hpp index b437f6361..84a8f4be6 100644 --- a/src/tools/ecode/appconfig.hpp +++ b/src/tools/ecode/appconfig.hpp @@ -141,13 +141,13 @@ struct LanguagesExtensions { std::map priorities; }; -struct ProjectDocumentConfig { +struct ProjectConfig { bool useGlobalSettings{ true }; HExtLanguageType hExtLanguageType{ HExtLanguageType::AutoDetect }; DocumentConfig doc; LanguagesExtensions languagesExtensions; - ProjectDocumentConfig() {} - ProjectDocumentConfig( const DocumentConfig& doc ) { this->doc = doc; } + ProjectConfig() {} + ProjectConfig( const DocumentConfig& doc ) { this->doc = doc; } }; struct ProjectBuildConfiguration { @@ -259,12 +259,12 @@ class AppConfig { bool terminalMode ); void saveProject( std::string projectFolder, UICodeEditorSplitter* editorSplitter, - const std::string& configPath, const ProjectDocumentConfig& docConfig, + const std::string& configPath, const ProjectConfig& docConfig, const ProjectBuildConfiguration& buildConfig, bool onlyIfNeeded, bool sessionSnapshot, PluginManager* ); void loadProject( std::string projectFolder, UICodeEditorSplitter* editorSplitter, - const std::string& configPath, ProjectDocumentConfig& docConfig, + const std::string& configPath, ProjectConfig& docConfig, ecode::App* app, bool sessionSnapshot, PluginManager* pluginManager ); void addTabWidgetType( const std::string& type, TabWidgetCbs tabWidget ) { diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index c66b22d65..25edfcdf6 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -6,6 +6,7 @@ #include "settingsactions.hpp" #include "settingsmenu.hpp" #include "uibuildsettings.hpp" +#include "uidownloadwindow.hpp" #include "uitreeviewfs.hpp" #include "uiwelcomescreen.hpp" #include "version.hpp" @@ -62,6 +63,10 @@ void appLoop() { appInstance->mainLoop(); } +App* App::instance() { + return appInstance; +} + bool App::isAnyTerminalDirty() const { bool dirty = false; mSplitter->forEachWidgetTypeStoppable( UI_TYPE_TERMINAL, [&dirty]( UIWidget* widget ) -> bool { @@ -555,7 +560,7 @@ void App::downloadFileWebDialog() { } void App::downloadFileWeb( const std::string& url ) { - loadFileFromPath( url, true ); + UIDownloadWindow::downloadFileWeb( url ); } UIFileDialog* App::saveFileDialog( UICodeEditor* editor, bool focusOnClose ) { @@ -989,7 +994,9 @@ static void fsRemoveAll( const std::string& fpath ) { } App::~App() { + appInstance = nullptr; mDestroyingApp = true; + if ( mProjectBuildManager ) mProjectBuildManager.reset(); @@ -1303,7 +1310,7 @@ App::makeAutoClosePairs( const std::string& strPairs ) { return pairs; } -ProjectDocumentConfig& App::getProjectDocConfig() { +ProjectConfig& App::getProjectConfig() { return mProjectDocConfig; } @@ -2128,7 +2135,7 @@ void App::closeEditors() { if ( mFileSystemListener ) mFileSystemListener->setDirTree( mDirTree ); - mProjectDocConfig = ProjectDocumentConfig( mConfig.doc ); + mProjectDocConfig = ProjectConfig( mConfig.doc ); mSettings->updateProjectSettingsMenu(); if ( !mSplitter->getTabWidgets().empty() && mSplitter->getTabWidgets()[0]->getTabCount() == 0 ) mSplitter->createCodeEditorInTabWidget( mSplitter->getTabWidgets()[0] ); diff --git a/src/tools/ecode/ecode.hpp b/src/tools/ecode/ecode.hpp index eda4fd6cc..e2035e289 100644 --- a/src/tools/ecode/ecode.hpp +++ b/src/tools/ecode/ecode.hpp @@ -34,6 +34,8 @@ class SettingsMenu; class App : public UICodeEditorSplitter::Client, public PluginContextProvider { public: + static App* instance(); + explicit App( const size_t& jobs = 0, const std::vector& args = {} ); ~App(); @@ -468,7 +470,7 @@ class App : public UICodeEditorSplitter::Client, public PluginContextProvider { std::vector> makeAutoClosePairs( const std::string& strPairs ); - ProjectDocumentConfig& getProjectDocConfig(); + ProjectConfig& getProjectConfig(); const std::string& getWindowTitle() const; @@ -603,6 +605,8 @@ class App : public UICodeEditorSplitter::Client, public PluginContextProvider { std::map& getCurrentLanguageExtensionsPriorities(); + bool isDestroyingApp() const { return mDestroyingApp; } + protected: std::vector mArgs; EE::Window::Window* mWindow{ nullptr }; @@ -667,7 +671,7 @@ class App : public UICodeEditorSplitter::Client, public PluginContextProvider { bool mIncognito{ false }; Clock mLastRender; Clock mSecondsCounter; - ProjectDocumentConfig mProjectDocConfig; + ProjectConfig mProjectDocConfig; std::unordered_set mTmpDocs; std::string mCurrentProject; std::string mCurrentProjectName; diff --git a/src/tools/ecode/globalsearchcontroller.cpp b/src/tools/ecode/globalsearchcontroller.cpp index 78f26e5e8..9b4781856 100644 --- a/src/tools/ecode/globalsearchcontroller.cpp +++ b/src/tools/ecode/globalsearchcontroller.cpp @@ -698,7 +698,7 @@ void GlobalSearchController::updateGlobalSearchBarResults( const std::string& search, std::shared_ptr model, bool searchReplace, bool isEscaped ) { updateGlobalSearchBar(); - mGlobalSearchTree->hExtLanguageType = mApp->getProjectDocConfig().hExtLanguageType; + mGlobalSearchTree->hExtLanguageType = mApp->getProjectConfig().hExtLanguageType; mGlobalSearchTree->setSearchStr( search ); mGlobalSearchTree->setModel( model ); if ( mGlobalSearchTree->getModel()->rowCount() < 50 ) diff --git a/src/tools/ecode/plugins/aiassistant/chatui.cpp b/src/tools/ecode/plugins/aiassistant/chatui.cpp index 6f16c8959..736714cb1 100644 --- a/src/tools/ecode/plugins/aiassistant/chatui.cpp +++ b/src/tools/ecode/plugins/aiassistant/chatui.cpp @@ -649,7 +649,7 @@ void LLMChatUI::showChatHistory() { hideAttachFile(); static const char* CHAT_HISTORY_LAYOUT = R"xml( - diff --git a/src/tools/ecode/settingsmenu.cpp b/src/tools/ecode/settingsmenu.cpp index ff9858701..7e5584f74 100644 --- a/src/tools/ecode/settingsmenu.cpp +++ b/src/tools/ecode/settingsmenu.cpp @@ -792,7 +792,7 @@ UIMenu* SettingsMenu::createDocumentMenu() { mProjectDocMenu = UIPopUpMenu::New(); mProjectDocMenu ->addCheckBox( i18n( "use_global_settings", "Use Global Settings" ), - mApp->getProjectDocConfig().useGlobalSettings ) + mApp->getProjectConfig().useGlobalSettings ) ->setOnShouldCloseCb( shouldCloseCb ) ->setId( "use_global_settings" ); @@ -801,73 +801,73 @@ UIMenu* SettingsMenu::createDocumentMenu() { i18n( "auto_detect_indent_type_and_width", "Auto Detect Indent Type & Width" ), mApp->getConfig().doc.autoDetectIndentType ) ->setId( "auto_indent" ) - ->setEnabled( !mApp->getProjectDocConfig().useGlobalSettings ); + ->setEnabled( !mApp->getProjectConfig().useGlobalSettings ); UIPopUpMenu* tabTypeMenuProject = UIPopUpMenu::New(); tabTypeMenuProject->addRadioButton( i18n( "tabs", "Tabs" ) ) - ->setActive( !mApp->getProjectDocConfig().doc.indentSpaces ) + ->setActive( !mApp->getProjectConfig().doc.indentSpaces ) ->setId( "tabs" ); tabTypeMenuProject->addRadioButton( i18n( "spaces", "Spaces" ) ) - ->setActive( mApp->getProjectDocConfig().doc.indentSpaces ) + ->setActive( mApp->getProjectConfig().doc.indentSpaces ) ->setId( "spaces" ); mProjectDocMenu ->addSubMenu( i18n( "indentation_type", "Indentation Type" ), nullptr, tabTypeMenuProject ) ->setId( "indent_type" ) - ->setEnabled( !mApp->getProjectDocConfig().useGlobalSettings ); + ->setEnabled( !mApp->getProjectConfig().useGlobalSettings ); tabTypeMenuProject->on( Event::OnItemClicked, [this]( const Event* event ) { const String& text = event->getNode()->asType()->getId(); - mApp->getProjectDocConfig().doc.indentSpaces = text != "tabs"; + mApp->getProjectConfig().doc.indentSpaces = text != "tabs"; } ); UIPopUpMenu* indentWidthMenuProject = UIPopUpMenu::New(); for ( int w = 2; w <= 12; w++ ) indentWidthMenuProject ->addRadioButton( String::toString( w ), - mApp->getProjectDocConfig().doc.indentWidth == w ) + mApp->getProjectConfig().doc.indentWidth == w ) ->setId( String::format( "indent_width_%d", w ) ) ->setData( w ); mProjectDocMenu ->addSubMenu( i18n( "indent_width", "Indent Width" ), nullptr, indentWidthMenuProject ) ->setId( "indent_width" ) - ->setEnabled( !mApp->getProjectDocConfig().useGlobalSettings ); + ->setEnabled( !mApp->getProjectConfig().useGlobalSettings ); indentWidthMenuProject->on( Event::OnItemClicked, [this]( const Event* event ) { int width = event->getNode()->getData(); - mApp->getProjectDocConfig().doc.indentWidth = width; + mApp->getProjectConfig().doc.indentWidth = width; } ); UIPopUpMenu* tabWidthMenuProject = UIPopUpMenu::New(); for ( int w = 2; w <= 12; w++ ) tabWidthMenuProject - ->addRadioButton( String::toString( w ), mApp->getProjectDocConfig().doc.tabWidth == w ) + ->addRadioButton( String::toString( w ), mApp->getProjectConfig().doc.tabWidth == w ) ->setId( String::format( "tab_width_%d", w ) ) ->setData( w ); mProjectDocMenu->addSubMenu( i18n( "tab_width", "Tab Width" ), nullptr, tabWidthMenuProject ) ->setId( "tab_width" ) - ->setEnabled( !mApp->getProjectDocConfig().useGlobalSettings ); + ->setEnabled( !mApp->getProjectConfig().useGlobalSettings ); tabWidthMenuProject->on( Event::OnItemClicked, [this]( const Event* event ) { int width = event->getNode()->getData(); - mApp->getProjectDocConfig().doc.tabWidth = width; + mApp->getProjectConfig().doc.tabWidth = width; } ); UIPopUpMenu* lineEndingsProjectMenu = UIPopUpMenu::New(); lineEndingsProjectMenu - ->addRadioButton( "Windows (CR/LF)", mApp->getProjectDocConfig().doc.lineEndings == + ->addRadioButton( "Windows (CR/LF)", mApp->getProjectConfig().doc.lineEndings == TextFormat::LineEnding::CRLF ) ->setId( "CRLF" ); lineEndingsProjectMenu - ->addRadioButton( "Unix (LF)", mApp->getProjectDocConfig().doc.lineEndings == + ->addRadioButton( "Unix (LF)", mApp->getProjectConfig().doc.lineEndings == TextFormat::LineEnding::LF ) ->setId( "LF" ); lineEndingsProjectMenu - ->addRadioButton( "Macintosh (CR)", mApp->getProjectDocConfig().doc.lineEndings == + ->addRadioButton( "Macintosh (CR)", mApp->getProjectConfig().doc.lineEndings == TextFormat::LineEnding::CR ) ->setId( "CR" ); mProjectDocMenu ->addSubMenu( i18n( "line_endings", "Line Endings" ), nullptr, lineEndingsProjectMenu ) ->setId( "line_endings" ) - ->setEnabled( !mApp->getProjectDocConfig().useGlobalSettings ); + ->setEnabled( !mApp->getProjectConfig().useGlobalSettings ); lineEndingsProjectMenu->on( Event::OnItemClicked, [this]( const Event* event ) { - mApp->getProjectDocConfig().doc.lineEndings = + mApp->getProjectConfig().doc.lineEndings = TextFormat::stringToLineEnding( event->getNode()->asType()->getId() ); } ); @@ -875,19 +875,19 @@ UIMenu* SettingsMenu::createDocumentMenu() { ->addCheckBox( i18n( "trim_trailing_whitespaces", "Trim Trailing Whitespaces" ), mApp->getConfig().doc.trimTrailingWhitespaces ) ->setId( "trim_whitespaces" ) - ->setEnabled( !mApp->getProjectDocConfig().useGlobalSettings ); + ->setEnabled( !mApp->getProjectConfig().useGlobalSettings ); mProjectDocMenu ->addCheckBox( i18n( "force_new_line_at_end_of_file", "Force New Line at End of File" ), mApp->getConfig().doc.forceNewLineAtEndOfFile ) ->setId( "force_nl" ) - ->setEnabled( !mApp->getProjectDocConfig().useGlobalSettings ); + ->setEnabled( !mApp->getProjectConfig().useGlobalSettings ); mProjectDocMenu ->addCheckBox( i18n( "write_unicode_bom", "Write Unicode BOM" ), mApp->getConfig().doc.writeUnicodeBOM ) ->setId( "write_bom" ) - ->setEnabled( !mApp->getProjectDocConfig().useGlobalSettings ); + ->setEnabled( !mApp->getProjectConfig().useGlobalSettings ); mProjectDocMenu->addSeparator(); @@ -904,16 +904,16 @@ UIMenu* SettingsMenu::createDocumentMenu() { if ( event->getNode()->isType( UI_TYPE_MENUCHECKBOX ) ) { UIMenuCheckBox* item = event->getNode()->asType(); if ( "use_global_settings" == id ) { - mApp->getProjectDocConfig().useGlobalSettings = item->isActive(); + mApp->getProjectConfig().useGlobalSettings = item->isActive(); updateProjectSettingsMenu(); } else if ( "trim_whitespaces" == id ) { - mApp->getProjectDocConfig().doc.trimTrailingWhitespaces = item->isActive(); + mApp->getProjectConfig().doc.trimTrailingWhitespaces = item->isActive(); } else if ( "force_nl" == id ) { - mApp->getProjectDocConfig().doc.forceNewLineAtEndOfFile = item->isActive(); + mApp->getProjectConfig().doc.forceNewLineAtEndOfFile = item->isActive(); } else if ( "write_bom" == id ) { - mApp->getProjectDocConfig().doc.writeUnicodeBOM = item->isActive(); + mApp->getProjectConfig().doc.writeUnicodeBOM = item->isActive(); } else if ( "auto_indent" == id ) { - mApp->getProjectDocConfig().doc.autoDetectIndentType = item->isActive(); + mApp->getProjectConfig().doc.autoDetectIndentType = item->isActive(); } } else if ( "line_breaking_column" == id ) { UIMessageBox* msgBox = UIMessageBox::New( @@ -924,12 +924,12 @@ UIMenu* SettingsMenu::createDocumentMenu() { msgBox->setCloseShortcut( { KEY_ESCAPE, 0 } ); msgBox->getTextInput()->setAllowOnlyNumbers( true, false ); msgBox->getTextInput()->setText( - String::toString( mApp->getProjectDocConfig().doc.lineBreakingColumn ) ); + String::toString( mApp->getProjectConfig().doc.lineBreakingColumn ) ); msgBox->showWhenReady(); msgBox->on( Event::OnConfirm, [this, msgBox]( const Event* ) { int val; if ( String::fromString( val, msgBox->getTextInput()->getText() ) && val >= 0 ) { - mApp->getProjectDocConfig().doc.lineBreakingColumn = val; + mApp->getProjectConfig().doc.lineBreakingColumn = val; mSplitter->forEachEditor( [val]( UICodeEditor* editor ) { editor->setLineBreakingColumn( val ); } ); msgBox->closeWindow(); @@ -2268,43 +2268,43 @@ void SettingsMenu::updateProjectSettingsMenu() { ->setEnabled( !mApp->getCurrentProject().empty() ); auto item = mHExtLanguageTypeMenu->find( - HExtLanguageTypeHelper::toString( mApp->getProjectDocConfig().hExtLanguageType ) ); + HExtLanguageTypeHelper::toString( mApp->getProjectConfig().hExtLanguageType ) ); if ( item && item->isType( UI_TYPE_MENURADIOBUTTON ) ) item->asType()->setActive( true ); for ( size_t i = 0; i < mProjectDocMenu->getCount(); i++ ) { mProjectDocMenu->getItem( i )->setEnabled( !mApp->getCurrentProject().empty() && - !mApp->getProjectDocConfig().useGlobalSettings ); + !mApp->getProjectConfig().useGlobalSettings ); } mSplitter->forEachEditor( [this]( UICodeEditor* editor ) { editor->setLineBreakingColumn( !mApp->getCurrentProject().empty() && - !mApp->getProjectDocConfig().useGlobalSettings - ? mApp->getProjectDocConfig().doc.lineBreakingColumn + !mApp->getProjectConfig().useGlobalSettings + ? mApp->getProjectConfig().doc.lineBreakingColumn : mApp->getConfig().doc.lineBreakingColumn ); } ); mProjectDocMenu->getItemId( "trim_whitespaces" ) ->asType() - ->setActive( mApp->getProjectDocConfig().doc.trimTrailingWhitespaces ); + ->setActive( mApp->getProjectConfig().doc.trimTrailingWhitespaces ); mProjectDocMenu->getItemId( "force_nl" ) ->asType() - ->setActive( mApp->getProjectDocConfig().doc.forceNewLineAtEndOfFile ); + ->setActive( mApp->getProjectConfig().doc.forceNewLineAtEndOfFile ); mProjectDocMenu->getItemId( "write_bom" ) ->asType() - ->setActive( mApp->getProjectDocConfig().doc.writeUnicodeBOM ); + ->setActive( mApp->getProjectConfig().doc.writeUnicodeBOM ); mProjectDocMenu->getItemId( "auto_indent" ) ->asType() - ->setActive( mApp->getProjectDocConfig().doc.autoDetectIndentType ); + ->setActive( mApp->getProjectConfig().doc.autoDetectIndentType ); auto* curIndent = mProjectDocMenu->find( "indent_width" ) ->asType() ->getSubMenu() ->find( String::format( "indent_width_%d", - mApp->getProjectDocConfig().doc.indentWidth ) ); + mApp->getProjectConfig().doc.indentWidth ) ); if ( curIndent ) curIndent->asType()->setActive( true ); @@ -2312,28 +2312,28 @@ void SettingsMenu::updateProjectSettingsMenu() { mProjectDocMenu->find( "indent_type" ) ->asType() ->getSubMenu() - ->find( !mApp->getProjectDocConfig().doc.indentSpaces ? "tabs" : "spaces" ) + ->find( !mApp->getProjectConfig().doc.indentSpaces ? "tabs" : "spaces" ) ->asType() ->setActive( true ); mProjectDocMenu->find( "tab_width" ) ->asType() ->getSubMenu() - ->find( String::format( "tab_width_%d", mApp->getProjectDocConfig().doc.tabWidth ) ) + ->find( String::format( "tab_width_%d", mApp->getProjectConfig().doc.tabWidth ) ) ->asType() ->setActive( true ); mProjectDocMenu->find( "line_endings" ) ->asType() ->getSubMenu() - ->find( TextFormat::lineEndingToString( mApp->getProjectDocConfig().doc.lineEndings ) ) + ->find( TextFormat::lineEndingToString( mApp->getProjectConfig().doc.lineEndings ) ) ->asType() ->setActive( true ); mProjectDocMenu->getItemId( "use_global_settings" ) ->setEnabled( true ) ->asType() - ->setActive( mApp->getProjectDocConfig().useGlobalSettings ); + ->setActive( mApp->getProjectConfig().useGlobalSettings ); } void SettingsMenu::updateTerminalMenu() { @@ -2818,7 +2818,7 @@ void SettingsMenu::createProjectMenu() { owner->on( Event::OnMenuShow, [owner, this]( auto ) { mProjectDocMenu->setOwnerNode( owner ); } ); - HExtLanguageType hExtLanguageType = mApp->getProjectDocConfig().hExtLanguageType; + HExtLanguageType hExtLanguageType = mApp->getProjectConfig().hExtLanguageType; mHExtLanguageTypeMenu = UIPopUpMenu::New(); mHExtLanguageTypeMenu->setId( "h_ext_files_submenu" ); mHExtLanguageTypeMenu @@ -2847,11 +2847,11 @@ void SettingsMenu::createProjectMenu() { if ( event->getNode()->isType( UI_TYPE_MENURADIOBUTTON ) ) { UIMenuCheckBox* item = event->getNode()->asType(); - mApp->getProjectDocConfig().hExtLanguageType = + mApp->getProjectConfig().hExtLanguageType = HExtLanguageTypeHelper::fromString( item->getId() ); mApp->getSplitter()->forEachEditor( [this]( UICodeEditor* editor ) { editor->getDocument().setHExtLanguageType( - mApp->getProjectDocConfig().hExtLanguageType ); + mApp->getProjectConfig().hExtLanguageType ); if ( editor->getDocument().getFileInfo().getExtension() == "h" ) { editor->resetSyntaxDefinition(); if ( mSplitter->isCurEditor( editor ) ) diff --git a/src/tools/ecode/uidownloadwindow.cpp b/src/tools/ecode/uidownloadwindow.cpp new file mode 100644 index 000000000..f337a1d62 --- /dev/null +++ b/src/tools/ecode/uidownloadwindow.cpp @@ -0,0 +1,95 @@ +#include "uidownloadwindow.hpp" +#include "ecode.hpp" + +namespace ecode { + +void UIDownloadWindow::downloadFileWeb( const std::string& url ) { + static const char* DOWNLOAD_WINDOW = R"xml( + + + + + + + + )xml"; + UIWidgetCreator::registerWidget( "downloadwindow", UIDownloadWindow::New ); + SceneManager::instance() + ->getUISceneNode() + ->loadLayoutFromString( DOWNLOAD_WINDOW ) + ->asType() + ->startDownload( url ) + ->center(); +} + +UIDownloadWindow* UIDownloadWindow::New() { + return eeNew( UIDownloadWindow, () ); +} + +UIDownloadWindow::UIDownloadWindow() : UIWindow() { + setId( "window-" + UUID().toString() ); +} + +UIDownloadWindow::~UIDownloadWindow() { + if ( mStatus == Status::Running && Http::Pool::getGlobal().exists( mURI, mProxyURI ) ) { + auto http = Http::Pool::getGlobal().get( mURI, mProxyURI ); + http->setCancelRequest( mReqId ); + } +} + +UIDownloadWindow* UIDownloadWindow::startDownload( const std::string& url ) { + findByClass( "download_url" )->asType()->setText( url ); + URI uri( url ); + mURI = uri; + mProxyURI = Http::getEnvProxyURI(); + mStatus = Status::Running; + auto id = getId(); + mReqId = Http::getAsync( + [uri, id]( const Http&, Http::Request&, Http::Response& response ) { + std::string path( URI::getTempPathFromURI( uri ) ); + FileSystem::fileWrite( path, (const Uint8*)response.getBody().c_str(), + response.getBody().size() ); + if ( App::instance() && !App::instance()->isDestroyingApp() ) { + App::instance()->getUISceneNode()->runOnMainThread( [path] { + if ( App::instance() && !App::instance()->isDestroyingApp() ) + App::instance()->loadFileFromPath( path, true, nullptr, nullptr, false, + true ); + } ); + } + + if ( SceneManager::isActive() ) { + auto nodeWin = SceneManager::instance()->getUISceneNode()->getRoot()->find( id ); + if ( nodeWin ) { + auto me = nodeWin->asType(); + me->mStatus = Status::Completed; + me->closeWindow(); + } + } + }, + url, Seconds( 10 ), + [id]( const Http& http, const Http::Request& request, const Http::Response& response, + const Http::Request::Status& status, std::size_t totalBytes, + std::size_t currentBytes ) { + if ( SceneManager::isActive() ) { + auto nodeWin = SceneManager::instance()->getUISceneNode()->getRoot()->find( id ); + if ( nodeWin ) { + auto me = nodeWin->asType(); + auto progress = me->findByType( UI_TYPE_PROGRESSBAR ); + if ( status == Http::Request::Status::HeaderReceived || + status == Http::Request::Status::ContentReceived ) { + progress->runOnMainThread( [progress, currentBytes, totalBytes] { + progress->setProgress( + totalBytes > 0 + ? ( static_cast( currentBytes ) / totalBytes ) * 100.f + : 50 ); + } ); + } + } + } + return true; + }, + {}, "", true, mProxyURI ); + return this; +} + +} // namespace ecode diff --git a/src/tools/ecode/uidownloadwindow.hpp b/src/tools/ecode/uidownloadwindow.hpp new file mode 100644 index 000000000..ecba83a8d --- /dev/null +++ b/src/tools/ecode/uidownloadwindow.hpp @@ -0,0 +1,37 @@ +#pragma once +#include +#include + +using namespace EE; +using namespace EE::Network; +using namespace EE::UI; + +namespace ecode { + +class UIDownloadWindow : public UIWindow { + public: + enum class Status { + NotStarted, + Running, + Completed, + Canceled, + }; + + static void downloadFileWeb( const std::string& url ); + + static UIDownloadWindow* New(); + + UIDownloadWindow(); + + virtual ~UIDownloadWindow(); + + UIDownloadWindow* startDownload( const std::string& url ); + + protected: + Uint64 mReqId{ 0 }; + URI mURI; + URI mProxyURI; + Status mStatus{ Status::NotStarted }; +}; + +} // namespace ecode