/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance"). // All rights reserved. // // This software and its documentation and related materials are owned by // the Alliance. The software may only be incorporated into application // programs owned by members of the Alliance, subject to a signed // Membership Agreement and Supplemental Software License Agreement with the // Alliance. The structure and organization of this software are the valuable // trade secrets of the Alliance and its suppliers. The software is also // protected by copyright law and international treaty provisions. Application // programs incorporating this software must include the following statement // with their copyright notices: // // This application incorporates Open Design Alliance software pursuant to a license // agreement with Open Design Alliance. // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// #include "OdaCommon.h" #include "OdVisualizeQtAppDialogs.h" #include "qboxlayout.h" #include "qgroupbox.h" #include "qradiobutton.h" #include "qapplication.h" #include "qthread.h" #include "qmessagebox.h" #include "Client.h" QString toQString( const OdString& sStr ) { std::wstring wstr( (wchar_t*)sStr.c_str() ); QString qsStr( QString::fromStdWString( wstr ) ); return qsStr; } OdString toOdString( const QString& sStr ) { wchar_t* pChars = new wchar_t[ sStr.length() + 1 ]; sStr.toWCharArray( pChars ); pChars[ sStr.length() ] = 0; OdString odsStr( pChars ); delete[] pChars; return odsStr; } OdTvQtStreamingDialog::OdTvQtStreamingDialog( OdTvStreamingClientPtr pClient, QWidget* pParent ) : QDialog( pParent ), m_pClient( pClient ) { QVBoxLayout* vlay = new QVBoxLayout( this ); QHBoxLayout* requestLay = new QHBoxLayout(); QHBoxLayout* filesLay = new QHBoxLayout(); QHBoxLayout* lowMemLay = new QHBoxLayout(); QHBoxLayout* buttonsLay = new QHBoxLayout(); vlay->addLayout( requestLay ); vlay->addLayout( filesLay ); vlay->addLayout( lowMemLay ); vlay->addLayout( buttonsLay ); //FileList request QGroupBox* group = new QGroupBox( tr("Mode") ); requestLay->addWidget( group ); QRadioButton* btnLinear = new QRadioButton( tr( "Linear" ) ); btnLinear->setChecked( true ); connect( btnLinear, &QPushButton::clicked, this, [this]{ onModeChanged( false ); } ); QRadioButton* btnPartial = new QRadioButton( tr( "Partial" ) ); connect( btnPartial, &QPushButton::clicked, this, [this]{ onModeChanged( true ); } ); QHBoxLayout* checksLay = new QHBoxLayout(); checksLay->addWidget( btnLinear ); checksLay->addWidget( btnPartial ); group->setLayout( checksLay ); QPushButton* requestBtn = new QPushButton( tr( "Request files list" ) ); connect( requestBtn, &QPushButton::clicked, this, &OdTvQtStreamingDialog::onRequestFileList ); requestLay->addWidget( requestBtn ); //Files QGroupBox* groupFiles = new QGroupBox( tr( "Files:" ) ); filesLay->addWidget( groupFiles ); m_pFilesCombo = new QComboBox(); connect( m_pFilesCombo, static_cast( &QComboBox::currentIndexChanged ), this, &OdTvQtStreamingDialog::onFileComboChanged ); QHBoxLayout* fileComboLay = new QHBoxLayout(); fileComboLay->addWidget( m_pFilesCombo ); fileComboLay->setAlignment( Qt::AlignTop ); groupFiles->setLayout( fileComboLay ); setupFilesList(); //Low memory m_pLowMemCheck = new QCheckBox( tr( "Low memory mode" ) ); lowMemLay->addWidget( m_pLowMemCheck ); connect( m_pLowMemCheck, static_cast( &QCheckBox::clicked ), this, &OdTvQtStreamingDialog::onLowMemoryModeChanged ); m_pLowMemEdit = new QLineEdit( tr( "1000" ) ); lowMemLay->addWidget( m_pLowMemEdit ); QLabel* lbl = new QLabel( tr( "MB" ) ); lowMemLay->addWidget( lbl ); updateLowMemoryOptions(); //Buttons m_pRequestBtn = new QPushButton( tr( "Do stream" ) ); connect( m_pRequestBtn, &QPushButton::clicked, this, &OdTvQtStreamingDialog::onOK ); buttonsLay->addWidget( m_pRequestBtn ); m_pRequestBtn->setEnabled( false ); QPushButton* btn = new QPushButton( tr( "Cancel" ) ); connect( btn, &QPushButton::clicked, this, &OdTvQtStreamingDialog::onCancel ); buttonsLay->addWidget( btn ); m_pAssemblyBtn = new QPushButton( tr( "Create Assembly" ) ); connect( m_pAssemblyBtn, &QPushButton::clicked, this, &OdTvQtStreamingDialog::onAssembly ); buttonsLay->addWidget( m_pAssemblyBtn ); m_pAssemblyBtn->setEnabled( false ); setWindowTitle( tr( "Streaming setup" ) ); } void OdTvQtStreamingDialog::onOK() { if( m_bLowMemoryMode && m_pLowMemEdit ) { m_nLimit = (OdUInt64)( m_pLowMemEdit->text().toInt() ) * 1024 * 1024; } accept(); } void OdTvQtStreamingDialog::onCancel() { reject(); } void OdTvQtStreamingDialog::setupFilesList() { if( m_files.empty() ) { m_pFilesCombo->clear(); m_pFilesCombo->setEnabled( false ); return; } m_pFilesCombo->clear(); for( unsigned i = 0; i < m_files.size(); ++i ) { m_pFilesCombo->addItem( toQString( m_files[ i ] ) ); } m_pFilesCombo->setEnabled( true ); } void OdTvQtStreamingDialog::onModeChanged( bool bPartial ) { if( m_bPartialMode != bPartial ) { m_bPartialMode = bPartial; m_files.clear(); m_pAssemblyBtn->setEnabled( false ); setupFilesList(); updateLowMemoryOptions(); } } void OdTvQtStreamingDialog::onRequestFileList() { m_files.clear(); m_pAssemblyBtn->setEnabled( false ); setupFilesList(); QApplication::setOverrideCursor( Qt::WaitCursor ); QApplication::processEvents(); OdUInt64 nCmd = m_pClient->requestFileList( m_bPartialMode ); OdTvStreamingClientDataPtr pData; while( !pData ) { if( !m_pClient->hasResponse( nCmd ) ) { QThread::msleep( 500 ); } else { pData = m_pClient->getResponse( nCmd ); } } if( pData->type() != OdTvStreamingClientData::Type::kStringList ) { QMessageBox::critical( this, tr( "Error" ), tr( "Error while parsing files list" ), QMessageBox::Ok ); QApplication::restoreOverrideCursor(); return; } OdTvStreamingClientStringListData* pFilesList = dynamic_cast( pData.get() ); for( unsigned i = 0; i < pFilesList->stringList.size(); ++i ) { m_files.push_back( pFilesList->stringList[ i ] ); } setupFilesList(); m_pAssemblyBtn->setEnabled( m_bPartialMode && !m_files.empty() ); QApplication::restoreOverrideCursor(); } void OdTvQtStreamingDialog::onFileComboChanged( int index ) { if( index < 0 ) { m_requestFile = OdString::kEmpty; if( m_pRequestBtn ) m_pRequestBtn->setEnabled( false ); } else { m_requestFile = m_files[ index ]; if( m_pRequestBtn ) m_pRequestBtn->setEnabled( true ); } } void OdTvQtStreamingDialog::updateLowMemoryOptions() { if( m_pLowMemCheck ) { m_pLowMemCheck->setEnabled( m_bPartialMode ); if( m_pLowMemEdit ) { if( m_bPartialMode ) { bool isLL = m_pLowMemCheck->isChecked(); m_pLowMemEdit->setEnabled( isLL ); } else { m_pLowMemEdit->setEnabled( false ); } } } } void OdTvQtStreamingDialog::onLowMemoryModeChanged( bool bChecked ) { m_bLowMemoryMode = bChecked; updateLowMemoryOptions(); } void OdTvQtStreamingDialog::onAssembly() { if( !m_bPartialMode || m_files.empty() ) { ODA_FAIL(); return; } if( m_bLowMemoryMode && m_pLowMemEdit ) { m_nLimit = ( OdUInt64 )( m_pLowMemEdit->text().toInt() ) * 1024 * 1024; } OdTvQtAssemblyStringSelectionDialog dlg( OD_T("Assembly creation"), OD_T("Select files:"), m_files); dlg.resize( 400, 300 ); QDialog::DialogCode retCode = (QDialog::DialogCode)dlg.exec(); if( retCode == QDialog::Accepted && !dlg.selectedResult().empty() ) { //TODO: streaming work around //m_assemblyInput = dlg.selectedFiles(); m_assemblyInput.clear(); for( const auto& it : dlg.selectedResult() ) { m_assemblyInput.push_back( it ); } m_bAssemblyMode = true; accept(); } } OdTvQtAssemblyStringSelectionDialog::OdTvQtAssemblyStringSelectionDialog( const OdString& title, const OdString& stringsTitle, const OdVector< OdString >& strings, QWidget* pParent ) : QDialog( pParent ) { setWindowTitle( toQString( title ) ); QVBoxLayout* vLay = new QVBoxLayout( this ); QVBoxLayout* vlayChecks = new QVBoxLayout(); QHBoxLayout* hLay = new QHBoxLayout(); QGroupBox* group = new QGroupBox( toQString( stringsTitle ) ); vLay->addWidget( group ); group->setLayout( vlayChecks ); vLay->addLayout( hLay ); m_checkBoxes.reserve( strings.size() ); for( const auto& it : strings ) { QCheckBox* pCheck = new QCheckBox( toQString( it ) ); pCheck->setChecked( true ); vlayChecks->addWidget( pCheck ); m_checkBoxes.push_back( pCheck ); } QPushButton* btn = new QPushButton( tr( "Ok" ) ); connect( btn, &QPushButton::clicked, this, &OdTvQtAssemblyStringSelectionDialog::onOK ); hLay->addWidget( btn ); btn = new QPushButton( tr( "Cancel" ) ); connect( btn, &QPushButton::clicked, this, &OdTvQtAssemblyStringSelectionDialog::onCancel ); hLay->addWidget( btn ); } void OdTvQtAssemblyStringSelectionDialog::onOK() { for( const auto& it : m_checkBoxes ) { if( it->isChecked() ) { m_result.push_back( toOdString( it->text() ) ); } } accept(); } void OdTvQtAssemblyStringSelectionDialog::onCancel() { reject(); } OdTvQtAssemblyTreeDialog::OdTvQtAssemblyTreeDialog( const OdTvAssemblyCreationReactor::OdTvAssemblyTemplate& assemblyTemplate, QWidget* pParent ) : QDialog( pParent ) { m_pTree = new QTreeWidget(); QTreeWidgetItem* parentItem = nullptr; QTreeWidgetItem* item = new QTreeWidgetItem( parentItem ); item->setText( 0, tr("Assembly" ) ); if( parentItem == nullptr ) { m_pTree->addTopLevelItem( item ); } parentItem = item; parentItem->setExpanded( true ); for( const auto& dev : assemblyTemplate ) { QTreeWidgetItem* deviceItem = new QTreeWidgetItem( parentItem ); deviceItem->setText( 0, toQString( dev.deviceName ) ); deviceItem->setExpanded( true ); for( const auto& view : dev.views ) { QTreeWidgetItem* viewItem = new QTreeWidgetItem( deviceItem ); viewItem->setText( 0, toQString( view.viewName ) ); viewItem->setExpanded( true ); for( const auto& ref : view.references ) { QTreeWidgetItem* refItem = new QTreeWidgetItem( viewItem ); OdString text = OD_T( "<" ) + ref.databasePath() + OD_T( ":" ) + ref.modelName() + OD_T( "> " ) + ref.referenceName(); refItem->setText( 0, toQString( text ) ); refItem->setExpanded( true ); } } } m_pTree->setHeaderHidden( true ); m_pTree->setSelectionMode( QAbstractItemView::NoSelection ); m_pTree->setFocusPolicy( Qt::NoFocus ); QVBoxLayout* vlt = new QVBoxLayout; vlt->addWidget( m_pTree ); setLayout( vlt ); QHBoxLayout* hlt = new QHBoxLayout(); vlt->addLayout( hlt ); QPushButton* btn = new QPushButton( tr( "Ok" ) ); connect( btn, &QPushButton::clicked, this, &OdTvQtAssemblyTreeDialog::onOK ); hlt->addWidget( btn ); btn = new QPushButton( tr( "Cancel" ) ); connect( btn, &QPushButton::clicked, this, &OdTvQtAssemblyTreeDialog::onCancel ); hlt->addWidget( btn ); } void OdTvQtAssemblyTreeDialog::onOK() { accept(); } void OdTvQtAssemblyTreeDialog::onCancel() { reject(); }