#include "uibuildsettings.hpp" #include #include #include #include #include #include using namespace EE::UI::Models; namespace ecode { class UIBuildStep : public UILinearLayout { public: static UIBuildStep* New( bool isBuildStep, UIBuildSettings* buildSettings, size_t stepNum, ProjectBuildStep* buildStep ) { return eeNew( UIBuildStep, ( isBuildStep, buildSettings, stepNum, buildStep ) ); } void clearBindings() { mDataBindHolder.clear(); } void updateStep( size_t stepNum, ProjectBuildStep* buildStep ) { clearBindings(); removeClass( String::toString( mStepNum ) ); mStepNum = stepNum; mStep = buildStep; addClass( String::toString( mStepNum ) ); findByClass( "step_name" ) ->setText( String::format( mBuildSettings->getUISceneNode() ->i18n( "build_step_num", "Step %u: %s" ) .toUtf8() .c_str(), mStepNum + 1, mStep->cmd.c_str() ) ); mDataBindHolder += UIDataBindBool::New( &mStep->enabled, findByClass( "enabled_checkbox" ) ); auto placeholder = UIDataBindString::New( &mStep->cmd, findByClass( "input_cmd" ) ); mDataBindHolder += UIDataBindString::New( &mStep->args, findByClass( "input_args" ) ); mDataBindHolder += UIDataBindString::New( &mStep->workingDir, findByClass( "input_working_dir" ) ); } protected: UIBuildStep( bool isBuildStep, UIBuildSettings* buildSettings, size_t stepNum, ProjectBuildStep* buildStep ) : UILinearLayout( "buildstep", UIOrientation::Vertical ), mIsBuildStep( isBuildStep ), mBuildSettings( buildSettings ), mStepNum( stepNum ), mStep( buildStep ) { setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::WrapContent ); addClass( "build_step" ); addClass( String::toString( stepNum ) ); static const auto BUILD_STEP_XML = R"xml( )xml"; getUISceneNode()->loadLayoutFromString( BUILD_STEP_XML, this ); findByClass( "details_but" )->onClick( [this]( const MouseEvent* event ) { auto me = event->getNode()->asType(); findByClass( "details" )->setVisible( me->hasClass( "contracted" ) ); me->toggleClass( "contracted" ); } ); findByClass( "move_down" )->onClick( [this]( auto ) { mBuildSettings->moveStepDown( mStepNum, !mIsBuildStep ); } ); findByClass( "move_up" )->onClick( [this]( auto ) { mBuildSettings->moveStepUp( mStepNum, !mIsBuildStep ); } ); findByClass( "remove_item" )->onClick( [this]( auto ) { mBuildSettings->deleteStep( mStepNum, !mIsBuildStep ); } ); updateStep( mStepNum, mStep ); } bool mIsBuildStep{ true }; UIBuildSettings* mBuildSettings{ nullptr }; size_t mStepNum{ 0 }; ProjectBuildStep* mStep; UIDataBindHolder mDataBindHolder; }; static const auto SETTINGS_PANEL_XML = R"xml( generic )xml"; UIBuildSettings* UIBuildSettings::New( ProjectBuild& build, ProjectBuildConfiguration& config ) { return eeNew( UIBuildSettings, ( build, config ) ); } UIBuildSettings::~UIBuildSettings() { for ( const auto& cbs : mCbs ) { for ( const auto& cb : cbs.second ) cbs.first->removeEventListener( cb ); } } UIBuildSettings::UIBuildSettings( ProjectBuild& build, ProjectBuildConfiguration& config ) : mBuild( build ), mConfig( config ), mOldName( mBuild.getName() ) { addClass( "build_settings" ); mUISceneNode->loadLayoutFromString( SETTINGS_PANEL_XML, this, String::hash( "build_settings" ) ); auto buildNameInput = find( "build_name" ); mDataBindHolder += UIDataBindString::New( &mBuild.mName, buildNameInput ); auto panelBuildNameDDL = getUISceneNode() ->getRoot() ->querySelector( " #build_tab #build_list" ) ->asType(); buildNameInput->on( Event::OnValueChange, [this, panelBuildNameDDL]( auto ) { refreshTab(); if ( panelBuildNameDDL ) { auto idx = panelBuildNameDDL->getListBox()->getItemIndex( mOldName ); if ( idx != eeINDEX_NOT_FOUND ) panelBuildNameDDL->getListBox()->setItemText( idx, mBuild.getName() ); } mOldName = mBuild.getName(); } ); auto oses = find( "os_select" )->querySelectorAll( "CheckBox" ); for ( const auto os : oses ) { if ( mBuild.mOS.find( os->getId() ) != mBuild.mOS.end() ) os->asType()->setChecked( true ); os->on( Event::OnValueChange, [this]( const Event* ) { updateOS(); } ); } if ( mBuild.mBuild.empty() ) mBuild.mBuild.push_back( {} ); if ( mBuild.mClean.empty() ) mBuild.mClean.push_back( {} ); auto buildStepsParent = find( "build_steps_cont" ); for ( size_t step = 0; step < mBuild.mBuild.size(); ++step ) { auto bs = UIBuildStep::New( true, this, step, &mBuild.mBuild[step] ); bs->setParent( buildStepsParent ); } find( "add_build_step" )->onClick( [this, buildStepsParent]( const Event* ) { mBuild.mBuild.push_back( {} ); auto step = mBuild.mBuild.size() - 1; UIBuildStep::New( true, this, step, &mBuild.mBuild[step] )->setParent( buildStepsParent ); } ); auto buildCleanStepsParent = find( "build_clean_steps_cont" ); for ( size_t step = 0; step < mBuild.mClean.size(); ++step ) { UIBuildStep::New( false, this, step, &mBuild.mClean[step] ) ->setParent( buildCleanStepsParent ); } find( "add_clean_step" )->onClick( [this, buildCleanStepsParent]( const Event* ) { mBuild.mClean.push_back( {} ); auto step = mBuild.mClean.size() - 1; UIBuildStep::New( false, this, step, &mBuild.mClean[step] ) ->setParent( buildCleanStepsParent ); } ); auto buildTypeDropDown = find( "build_type_list" ); auto panelBuildTypeDDL = getUISceneNode() ->getRoot() ->querySelector( "#build_tab #build_type_list" ) ->asType(); std::vector buildTypes; for ( const auto& type : mBuild.mBuildTypes ) buildTypes.push_back( type ); buildTypeDropDown->getListBox()->addListBoxItems( buildTypes ); buildTypeDropDown->getListBox()->setSelected( mConfig.buildType ); buildTypeDropDown->on( Event::OnItemSelected, [this, buildTypeDropDown, panelBuildTypeDDL]( const Event* ) { mConfig.buildType = buildTypeDropDown->getListBox()->getItemSelectedText().toUtf8(); if ( panelBuildTypeDDL ) panelBuildTypeDDL->getListBox()->setSelected( mConfig.buildType ); } ); if ( panelBuildTypeDDL ) { mCbs[panelBuildTypeDDL].push_back( panelBuildTypeDDL->on( Event::OnItemSelected, [this, buildTypeDropDown, panelBuildTypeDDL]( const Event* ) { mConfig.buildType = panelBuildTypeDDL->getListBox()->getItemSelectedText().toUtf8(); if ( buildTypeDropDown ) buildTypeDropDown->getListBox()->setSelected( mConfig.buildType ); } ) ); mCbs[panelBuildTypeDDL].push_back( panelBuildTypeDDL->on( Event::OnClose, [this, panelBuildTypeDDL]( auto ) { mCbs.erase( panelBuildTypeDDL ); } ) ); } auto advTitle = querySelector( ".settings_panel > .advanced_options > .title" ); advTitle->onClick( [this]( const MouseEvent* event ) { auto img = event->getNode()->findByType( UI_TYPE_IMAGE )->asType(); findByClass( "inner_box" )->toggleClass( "visible" ); img->toggleClass( "expanded" ); } ); mDataBindHolder += UIDataBindBool::New( &mBuild.mConfig.clearSysEnv, find( "clear_sys_env" ) ); UITableView* tableEnvs = find( "table_vars" ); auto modelEnvs = ItemPairListModel::create( mBuild.mEnvs ); modelEnvs->setIsEditable( true ); modelEnvs->setColumnName( 0, getTranslatorString( "env_name", "Name" ) ); modelEnvs->setColumnName( 1, getTranslatorString( "env_value", "Value" ) ); tableEnvs->setAutoColumnsWidth( true ); tableEnvs->setModel( modelEnvs ); tableEnvs->setEditable( true ); tableEnvs->setEditTriggers( UIAbstractView::EditTrigger::DoubleClicked ); tableEnvs->onCreateEditingDelegate = []( const ModelIndex& ) { return StringModelEditingDelegate::New(); }; UITableView* tableVars = find( "table_vars" ); auto modelVars = ItemPairListModel::create( mBuild.mVars ); modelVars->setColumnName( 0, getTranslatorString( "var_name", "Name" ) ); modelVars->setColumnName( 1, getTranslatorString( "var_value", "Value" ) ); modelVars->setIsEditable( true ); tableVars->setAutoColumnsWidth( true ); tableVars->setModel( modelVars ); tableVars->setEditable( true ); tableVars->setEditTriggers( UIAbstractView::EditTrigger::DoubleClicked ); tableVars->onCreateEditingDelegate = []( const ModelIndex& ) { return StringModelEditingDelegate::New(); }; find( "build_type_add" )->onClick( [this, buildTypeDropDown, panelBuildTypeDDL]( auto ) { UIMessageBox* msgBox = UIMessageBox::New( UIMessageBox::INPUT, i18n( "build_type_name", "Build Type Name:" ) ); msgBox->setTitle( i18n( "build_settings", "Build Settings" ) ); msgBox->setCloseShortcut( { KEY_ESCAPE, KEYMOD_NONE } ); msgBox->showWhenReady(); msgBox->addEventListener( Event::OnConfirm, [this, msgBox, buildTypeDropDown, panelBuildTypeDDL]( const Event* ) { const auto& buildType = msgBox->getTextInput()->getText(); mBuild.mBuildTypes.insert( buildType.toUtf8() ); buildTypeDropDown->getListBox()->addListBoxItem( buildType ); buildTypeDropDown->getListBox()->setSelected( buildType ); if ( panelBuildTypeDDL ) { panelBuildTypeDDL->getListBox()->addListBoxItem( buildType ); panelBuildTypeDDL->getListBox()->setSelected( buildType ); } msgBox->closeWindow(); } ); } ); find( "build_type_del" )->onClick( [this, buildTypeDropDown, panelBuildTypeDDL]( auto ) { const auto& txt = buildTypeDropDown->getListBox()->getItemSelectedText(); UIMessageBox* msgBox = UIMessageBox::New( UIMessageBox::OK_CANCEL, String::format( i18n( "build_type_name_del", "Delete Build Type: %s?" ).toUtf8().c_str(), txt.toUtf8().c_str() ) ); msgBox->setTitle( i18n( "build_settings", "Build Settings" ) ); msgBox->setCloseShortcut( { KEY_ESCAPE, KEYMOD_NONE } ); msgBox->showWhenReady(); msgBox->addEventListener( Event::OnConfirm, [this, msgBox, buildTypeDropDown, panelBuildTypeDDL, txt]( const Event* ) { mBuild.mBuildTypes.erase( txt.toUtf8() ); buildTypeDropDown->getListBox()->removeListBoxItem( txt ); if ( panelBuildTypeDDL ) { panelBuildTypeDDL->getListBox()->removeListBoxItem( txt ); } msgBox->closeWindow(); } ); } ); auto outputParserPresetsDDL = find( "output_parsers_presets_list" ); outputParserPresetsDDL->getListBox()->setSelected( mBuild.mOutputParser.mPreset ); outputParserPresetsDDL->on( Event::OnItemSelected, [this]( const Event* event ) { std::string txt( event->getNode() ->asType() ->getListBox() ->getItemSelectedText() .toUtf8() ); mBuild.mOutputParser.mPreset = txt; if ( ProjectBuildOutputParser::existsPreset( txt ) ) { mBuild.mOutputParser.mPresetConfig = ProjectBuildOutputParser::getPresets()[mBuild.mOutputParser.mPreset].mConfig; } } ); } void UIBuildSettings::updateOS() { mBuild.mOS.clear(); auto oses = find( "os_select" )->querySelectorAll( "CheckBox" ); for ( const auto os : oses ) { if ( os->asType()->isChecked() ) mBuild.mOS.insert( os->getId() ); } } void UIBuildSettings::setTab( UITab* tab ) { if ( tab != mTab ) { mTab = tab; refreshTab(); } } UITab* UIBuildSettings::getTab() const { return mTab; } void UIBuildSettings::refreshTab() { if ( !mTab ) return; mTab->setText( String::format( ( i18n( "build_seetings", "Build Settings" ) + ": %s" ).toUtf8().c_str(), mBuild.mName.c_str() ) ); mTab->setId( "build_settings_" + mBuild.mName ); } void UIBuildSettings::moveStepUp( size_t stepNum, bool isClean ) { moveStepDir( stepNum, isClean, -1 ); } void UIBuildSettings::moveStepDown( size_t stepNum, bool isClean ) { moveStepDir( stepNum, isClean, 1 ); } void UIBuildSettings::moveStepDir( size_t stepNum, bool isClean, int dir ) { ProjectBuildSteps& steps = isClean ? mBuild.mClean : mBuild.mBuild; UIWidget* cont = isClean ? find( "build_clean_steps_cont" ) : find( "build_steps_cont" ); int newStep = (int)stepNum + dir; std::swap( steps[stepNum], steps[newStep] ); auto bs1 = cont->findByClass( String::toString( stepNum ) ); auto bs2 = cont->findByClass( String::toString( newStep ) ); bs1->updateStep( stepNum, &steps[stepNum] ); bs2->updateStep( newStep, &steps[newStep] ); } void UIBuildSettings::deleteStep( size_t stepNum, bool isClean ) { ProjectBuildSteps& steps = isClean ? mBuild.mClean : mBuild.mBuild; UIWidget* cont = isClean ? find( "build_clean_steps_cont" ) : find( "build_steps_cont" ); for ( auto step = stepNum; step < steps.size(); step++ ) cont->findByClass( String::toString( step ) )->clearBindings(); // cppcheck-suppress mismatchingContainerIterator steps.erase( steps.begin() + stepNum ); cont->findByClass( String::toString( stepNum ) )->close(); for ( auto step = stepNum + 1; step < steps.size(); step++ ) cont->findByClass( String::toString( step ) ) ->updateStep( step, &steps[step] ); } } // namespace ecode