#include "qggrifobeamupform.h" #include "ui_qggrifobeamupform.h" #include #include "qgpropertywidget.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "qzip.h" #include "bsk_tftp_pfs.h" #include #include "downloadablefile.h" #include "mydebug.h" #include "historydbform.h" #include "fpgabeammeupstring.h" #include "fpgaflashxml.h" #define TFTP_DEFAULT_PORT 50069 bool IS_TFTP_CONNECTED; QString TMP_FOLDER; struct fileToWrite_s { bool validConfig; // true if i read a valid config from xml file present into zip files QString targetFlash; // namePrefix of valid config QString primaryFile; // bin file to write on first spi port (primary) QString primaryMD5; // md5 for primary file bool primaryDone; // true if write is done QString secondaryFile; // bin file to write on second spi port (secondary) QString secondaryMD5; // md5 for secondary file bool secondaryDone; //true if write is done }; static fileToWrite_s fileToWrite; void resetFileToWrite() { fileToWrite.validConfig = false; fileToWrite.targetFlash = ""; fileToWrite.primaryDone = false; fileToWrite.primaryFile = ""; fileToWrite.primaryMD5 = ""; fileToWrite.secondaryDone = false; fileToWrite.secondaryFile = ""; fileToWrite.secondaryMD5 = ""; } enum fpga_t { fpga_no_specific = 0, fpga_carrier1_fpga1 = 1, fpga_carrier1_fpga2 = 2, fpga_carrier2_fpga1 = 3, fpga_carrier2_fpga2 = 4, fpga_digital_ctrl = 5 }; //QString ShowFileInfo(const QString& fname, bool popup=true); static QString probeNetworks(const QString& prefered_net, QComboBox* cb) { unsigned int prefered_index=0; static bool privateSubnet=false; static QString preferedNetwork("127.0.0.1"); if (!prefered_net.isEmpty()) preferedNetwork=prefered_net; QHostInfo hi=QHostInfo::fromName(QHostInfo::localHostName()); //ui->groupBox->setTitle(QString("Host: %1").arg(hi.hostName())); QList hal=QNetworkInterface::allInterfaces(); if (hal.isEmpty()) { MyDebug.logMsg(type_log_error, origin_msg_generic, "Network Config: NO HOST ADDRESSES"); cb->addItem(""); cb->setEnabled(false); } else { foreach(QNetworkInterface nif, hal) { //QList nhal=nif.allAddresses(); QList nhal=nif.addressEntries(); foreach(QNetworkAddressEntry aentry, nhal) { bool private_subnet=false; QHostAddress a=aentry.ip(); if (!(a.toString().startsWith("192.168") || a.toString().startsWith("169.254") || a.toString().startsWith("127."))) continue; cb->addItem(QString("%1 (%2) [%3]").arg(nif.humanReadableName()).arg(a.toString()).arg(nif.index()), a.toString()); int currentIndex=cb->count()-1; //if (a.toString().startsWith("192.168.0") ||a.toString().startsWith("192.168.2")) if (a.toString().startsWith(preferedNetwork)) { prefered_index=currentIndex; private_subnet=true; privateSubnet=privateSubnet; } cb->setItemData(currentIndex, private_subnet, Qt::UserRole+1); cb->setItemData(currentIndex, nif.index(), Qt::UserRole+2); //ui->comboBoxInterface->seIif (nif.flags() & QNetworkInterface::IsUp) } } if (prefered_index) cb->setCurrentIndex(prefered_index); } return hi.hostName(); } #define MAX_TARGETS 64 struct targets_t { unsigned int valid; QgGrifoDownloadSite sites[MAX_TARGETS]; }; static targets_t targets; struct PgmSteps { QLabel* lbl; QCheckBox* chk; }; static PgmSteps pgmSteps[10]; QgGrifoBeamUpForm::QgGrifoBeamUpForm(QWidget *parent) : QWidget(parent), props(QgGrifoBeamupProperties::instance()), ui(new Ui::QgGrifoBeamUpForm), settings("./grifo_beamup.ini", QSettings::IniFormat) { IS_TFTP_CONNECTED = false; fileToWrite.validConfig = false; QStyle* st=QApplication::style(); ui->setupUi(this); ui->tbRefresh->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); ui->tbRefresh->setIcon(st->standardIcon(QStyle::SP_DriveNetIcon) ); ui->tbRefresh->setText("Connect"); ui->tbFileSelect->setIcon(st->standardIcon(QStyle::SP_FileIcon) ); ui->tbGo->setIcon(st->standardIcon(QStyle::SP_ArrowUp) ); ui->tbDropSelect->setIcon(st->standardIcon(QStyle::SP_FileDialogNewFolder) ); ui->tbSettings->setIcon(st->standardIcon(QStyle::SP_FileDialogListView) ); ui->tbFileInfo->setIcon(st->standardIcon(QStyle::SP_FileDialogInfoView)); ui->tbHistory->setIcon(st->standardIcon(QStyle::SP_DirHomeIcon) ); entitiesForm=new QgGrifoDownloadEntitiesForm; int ipos=ui->verticalLayout->indexOf(ui->placeholder); ui->verticalLayout->insertWidget(ipos, entitiesForm); ui->placeholder->setVisible(false); ui->leMsg->setMaximumBlockCount(5000); entitiesForm->setVisible(false); { QHostInfo hi=QHostInfo::fromName(QHostInfo::localHostName()); QString host=QString("Host: %1").arg(hi.hostName()); ui->hostName->setText(host); } ui->progressBar->setValue(0); ui->progressBar->setEnabled(false); ui->progressBar->setTextVisible(false); //setState(1); fileSelector.setObjectName("GrifoBeamUpFileSelector"); fileSelector.setOption(QFileDialog::ReadOnly, true); fileSelector.setViewMode(QFileDialog::Detail); fileSelector.setNameFilters( QStringList()<<"archive (*.zip)"<<"Binary (*.bin)"<<"ELF (*.elf *.out)"<<"Any files (*)"); connect(ui->tbFileSelect, &QToolButton::clicked, this, [this](bool) { QString tmp=fileSelector.directory().absolutePath(); fileSelector.setOption(QFileDialog::ReadOnly, true); fileSelector.setFileMode(QFileDialog::AnyFile); fileSelector.setDirectory(tmp); if (fileSelector.exec()) { ui->leFile->setText(fileSelector.selectedFiles().at(0)); //stateReady(); selectByFile(fileSelector.selectedFiles().at(0)); } } ); connect(ui->tbDropSelect, &QToolButton::clicked, this, [this](bool) { fileSelector.setFileMode(QFileDialog::Directory); if (fileSelector.exec()) { selectWatchDir(fileSelector.selectedFiles().at(0)); } }); connect(&fileWatcher, &QFileSystemWatcher::directoryChanged, this, &QgGrifoBeamUpForm::updateWatchedDirectory); connect(&fileWatcher, &QFileSystemWatcher::fileChanged, this, &QgGrifoBeamUpForm::updateWatchedFile); connect(ui->tbGo, &QToolButton::clicked, this, &QgGrifoBeamUpForm::uploadGo); #if 0 connect(&tftp, &QgGrifoBeamUpTftp::progressInfo, this, [this](int n, const QString& msg) { if (n==-1) ui->progressBar->setRange(0, 0); else { ui->progressBar->setRange(0, 100); ui->progressBar->setValue(n); } ui->progressLabel->setText(msg); }); connect(&tftp, &QgGrifoBeamUpTftp::sendTerminated, this, [this]() { ui->progressBar->setRange(0, 100); ui->progressBar->setValue(100); showMessage("Completed"); //ui->progressLabel->setText("Completed"); stateReady(); }); connect(&tftp, &QgGrifoBeamUpTftp::transferError, this, [this](int code, const QString& msg) { showMessage(QString("%1 (%2)").arg(msg).arg(code)); //ui->progressLabel->setText(QString("%1 (%2)").arg(msg).arg(code)); ui->progressBar->reset(); ui->progressBar->setRange(0, 100); ui->progressBar->setValue(0); ui->progressBar->setEnabled(false); QMessageBox::critical(this, QString(), QString("Transfer Error: %1 (%2)").arg(msg).arg(code)); stateReady(); }); connect(&tftp, &QgGrifoBeamUpTftp::serverHello, this, [this](unsigned int ip, int port, const QString& msg) { ui->leMsg->appendPlainText(msg); //setText(msg); serverHello(ip, port, msg); }); #endif //general configuration of app { QSettings& s=settings;//("./grifo_beamup.ini", QSettings::IniFormat); s.beginGroup("GrifoBeamUp"); QString prefnet=s.value("preferedNetwork", QString("$127.0.0")).toString(); if (prefnet.startsWith('$')) prefnet=prefnet.remove('$'); probeNetworks(prefnet, ui->cbNetwork); QgNetworkInterface::setNetworkIP(prefnet); ui->leFile->setText(s.value("file", QString()).toString()); fileSelector.restoreState(s.value("fileselector").toByteArray()); s.endGroup(); } #if 0 tftp.bind(QHostAddress(QgNetworkInterface::networkIP())); ui->tbNetwork->setText(netDlg->hostNetworkName()); QgNetworkInterface::setNetworkIP(netDlg->hostAddress()); connect(ui->tbNetwork, &QToolButton::clicked, this, [this](bool) { netDlg->exec(); if (netDlg->result()==QDialog::Accepted) { QgNetworkInterface::setNetworkInterface(QHostAddress(netDlg->hostAddress())); ui->tbNetwork->setText(netDlg->hostNetworkName()); //QgNetworkInterface::networkIP()); } }); #endif connect(ui->tbRefresh, &QToolButton::clicked, this, [this](bool) { refreshServers(); }); connect(ui->tbSettings, &QToolButton::clicked, this, [this](bool) { static QgPropertyDialog dlg(&props, this); dlg.show(); }); props.restoreSettings(settings); if (!props.property("lastDirectory").toString().isEmpty()) fileSelector.setDirectory(props.property("lastDirectory").toString()); pingTimer.setSingleShot(true); pingTimer.setInterval(2000); connect(&pingTimer, &QTimer::timeout, this, [this]() { ui->tbRefresh->setEnabled(true); }); ui->cbTarget->setDuplicatesEnabled(false); ui->cbPartition->setDuplicatesEnabled(false); ui->cbTarget->addItem(QgNetworkInterface::networkIP()+":"+QString("%1").arg(props.property("tftpFirstPort").toInt())); connect(entitiesForm, &QgGrifoDownloadEntitiesForm::itemSelected, this, [this](void*xs, void*xp) { bsk_download_site_t* s=(bsk_download_site_t*)xs; bsk_download_partition_t* p=(bsk_download_partition_t*)xp; updateSelected(s, p); }); stateReady(); /* * Configuration target from file */ flashTargets = flashTargetClass::instance(); if (flashTargets->readTargets()) { //QStringList list = flashTargets->getInfoLists(); //ui->cbTgt->addItems(list); setTargetOnScreen(); default_ip = flashTargets->getDefIp(); } else { qDebug()<<"Error read targets file config!"; } //readConfigFile(); programmer=new FgpaProgrammer; connect(ui->leFile, &QLineEdit::editingFinished, this, [this]() { selectByFile(ui->leFile->text()); }); selectWatchDir(props.property("watchedDirectory").toString()); setAcceptDrops(true); ui->groupBox->setEnabled(false); connect(entitiesForm, &QgGrifoDownloadEntitiesForm::fileDroppped, this, [this](QTreeWidgetItem* i, const QString& name) { selectByFile(name, i); }); { QGridLayout* g=ui->gridLayout_2; for(int i=0; i<7; ++i) { pgmSteps[i].chk=new QCheckBox; if (i<1) pgmSteps[i].chk->setChecked(false); else pgmSteps[i].chk->setChecked(true); pgmSteps[i].lbl=new QLabel("..."); g->addWidget(pgmSteps[i].chk, i+1, 0); g->addWidget(pgmSteps[i].lbl, i+1, 2); } } connect(programmer, &FgpaProgrammer::statusChanged, this, &QgGrifoBeamUpForm::statusUpdated, Qt::QueuedConnection); programmer->setSimulate(ui->cbSimulate->isChecked()); programmer->setSRIOMemory(ui->cb_TargetAddress->isChecked()); _dbHistory = dbHistory::instance(); QHostInfo hi=QHostInfo::fromName(QHostInfo::localHostName()); _dbHistory->setParam(hi.hostName()); _dbHistory->refreshList(); ui->groupBox_3->hide(); ui->groupBox_2->hide(); ui->label_2->hide(); ui->leDir->hide(); ui->tbDropSelect->hide(); ui->tbGo->hide(); ui->cbPartition->hide(); ui->cbTarget->hide(); ui->lbServer->hide(); statusBar = new QStatusBar(this); ui->verticalLayout->addWidget(statusBar); statusBar->showMessage("Ready", 3000); ui->leMsg->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); ui->tabWidget->setCurrentIndex(1); ui->btnWrite->setStyleSheet("QPushButton { background-color: green; color:white; }\n" "QPushButton:enabled { background-color: rgb(0,200,0); color:white; }\n"); TMP_FOLDER = QApplication::applicationDirPath() + "/tmp"; } QgGrifoBeamUpForm::~QgGrifoBeamUpForm() { delete ui; } void QgGrifoBeamUpForm::updateSelected(const bsk_download_site_t* site,const bsk_download_partition_t* p) { if (!site) return; MyDebug.logMsg(type_log_info, origin_msg_generic, QString("select: %1 %2").arg(site->name).arg(p->name)); ShowTargetInfo(true); } #include void QgGrifoBeamUpForm::selectByFile(const QString& fname, QTreeWidgetItem*) { /* * in base al file selezionato devo capire queste cose * * le flash da programmare sono EIF 1 con 2 flash da 128 mega 0x73, EIF 2 con altre due flash da 128 mega ???? * DFE 1 con 2 flash da 256 mega 0x16, DFE 2 con altre due flash da 256 mega ???? * Quindi in totale sono 8 flash da programmare. * * 1 se si tratta di un file binario devo chiedere su quale flash devo programmarlo in maniera selettiva tra le 8 disponibili, in quanto * deve essere salvato su di una flash sola tra quelle disponibili, quindi occorre chiedere su quale scheda e se primaria o secondaria * * 2 se si tratta di un file zip, occorre verificare che si tratti di un file zip valido, con dentro i due file binari corretti, devi chiedere * su quale scheda devo andare senza chiedere primaria/secondaria in quanto che ne sono due da caricare. * DA FARE - Potrei chiedere se devo caricare entrambe le flash oppure sono una delle due * * * IMPORTANTE: * nell'history, inserire un bottone che mi permetta di recuperare una vecchia installazione per riprocessarla. * Per semplificare la fase di recupero dovrei poter selezionare se rifare la programmazione su entrambe le flash, oppure solo su primaria/secondaria. * */ QFileInfo finfo(fname); QString n=finfo.fileName(); resetFileToWrite(); if (finfo.completeSuffix()=="zip") { // file zip with 2 binary file and xml info file. MyDebug.logMsg(type_log_info, origin_msg_generic, "file zip with info"); if (!extractInfoFromZip(fname)) { MyDebug.logMsg(type_log_error, origin_msg_generic, "Config present into zip file is not valid!"); } MyDebug.logMsg(type_log_info, origin_msg_generic, QString("target fpga-flash : %1").arg(fileToWrite.targetFlash)); entitiesForm->setUnCheckedAll(); //for every targets read from configuration files for (int i = 0; icountTarget(); i++) { targetItem tgt = flashTargets->getTarget(i); if (tgt.filePrefix==fileToWrite.targetFlash) { entitiesForm->setChecked(tgt.name); } } } else if (finfo.completeSuffix()=="bin") { // file binary, without info MyDebug.logMsg(type_log_info, origin_msg_generic, "file binary without info"); } } //************************************************* // connect to server selected from combobox //************************************************* void QgGrifoBeamUpForm::refreshServers() { if (ui->cbNetwork->count()<1) return; if (ui->cbNetwork->isEnabled()) { QString ip=ui->cbNetwork->itemData(ui->cbNetwork->currentIndex()).toString(); bool match=ip.startsWith("127.0.", Qt::CaseInsensitive); QString msg = ""; if (match) { tftp.bindRemote(QHostAddress("127.0.0.1"), TFTP_DEFAULT_PORT); //ui->cbTarget->setCurrentText(QString("%1:%2").arg("127.0.0.1").arg(TFTP_DEFAULT_PORT)); ui->lbServer->setText(QString("TFTP server: %1:%2").arg("127.0.0.1").arg(TFTP_DEFAULT_PORT)); msg = QString("Connected to TFTP server at %1:%2").arg("127.0.0.1").arg(TFTP_DEFAULT_PORT); } else { tftp.bindRemote(QHostAddress(default_ip), TFTP_DEFAULT_PORT); tftp.fixServerBug((default_ip==DSP_ETHERNET_IP) ? 2 : 0); //ui->cbTarget->setCurrentText(QString("%1:%2").arg(default_ip).arg(TFTP_DEFAULT_PORT)); ui->lbServer->setText(QString("TFTP server: %1:%2").arg(default_ip).arg(TFTP_DEFAULT_PORT)); msg = QString("Connected to TFTP server at %1:%2").arg(default_ip).arg(TFTP_DEFAULT_PORT); } QgNetworkInterface::setNetworkInterface(QHostAddress(ip)); QgNetworkInterface::setNetworkIP(ip); MyDebug.logMsg(type_log_info, origin_msg_tftp, QString("%1").arg(QgNetworkInterface::networkIP())); tftp.bind(QHostAddress(QgNetworkInterface::networkIP())); IS_TFTP_CONNECTED = true; ui->cbNetwork->setEnabled(false); //ui->groupBox->setEnabled(true); ui->lbServer->show(); addToLog(msg); statusBar->showMessage(msg); } ui->tbRefresh->setEnabled(false); programmer->setTftp(&tftp); programmer->setHistory(_dbHistory); } void QgGrifoBeamUpForm::serverHello(unsigned int /*ip*/, int /*port*/, const QString &/*msg*/) { #if 0 QgGrifoDownloadSite* s=&targets.sites[targets.valid]; memset(&s->site, 0, sizeof s->site); bsk_download_site_t* site=&s->site; int r=bsk_tftp_mfs_decode_site(site, msg.toLatin1().constData()); site->media_address=ip; site->media_port=port; s->tgt=0; if (r==0) { TgtMatch* tgt=tgtMatchSet.lookupCSCI(site->name, site->address); if (tgt) s->tgt=tgt; //appName=tgt->appName; entitiesForm->addSite(s); QHostAddress ha(site->media_address); QString n=QString("%1:%2/%3").arg(ha.toString()).arg(site->media_port).arg(site->name); ui->cbTarget->addItem(n, (quint64)site); ++targets.valid; for(int i=0; ipartitions[i].name[0]==0) break; QString queryStr=QString("$PGM:%1/$version$").arg(site->partitions[i].name); tftp.queryVersion(ip, port, queryStr); } pingTimer.start(); } entitiesForm->setVisible(true); #endif } void QgGrifoBeamUpForm::partitionUpdate(unsigned int /*ip*/, int /*port*/, const QString& /*msg*/) { } void QgGrifoBeamUpForm::saveSettings() { { QSettings& s=settings; //("./grifo_beamup.ini", QSettings::IniFormat); s.beginGroup("GrifoBeamUp"); s.setValue("preferedNetwork", QString('$')+QgNetworkInterface::networkIP()); s.setValue("file", ui->leFile->text()); s.setValue("fileselector", fileSelector.saveState()); props.setProperty("lastDirectory", fileSelector.directory().absolutePath()); s.setValue("dirHistory", fileSelector.history()); s.endGroup(); props.saveSettings(settings); } } void QgGrifoBeamUpForm::updateWatchedDirectory(const QString& path) { QDir dir(path); QStringList currentList=dir.entryList(); QStringList changed; foreach(QString s, currentList) { bool hit=watchedFiles.contains(s); if (!hit) changed.append(s); } watchedFiles=currentList; MyDebug.logMsg(type_log_info, origin_msg_generic, QString("Directory update: %1 %2").arg(path).arg(changed.count())); if (changed.size()>0) { for(int i=0; ileFile->setText(dir.absoluteFilePath(changed.at(0))); } } } void QgGrifoBeamUpForm::updateWatchedFile(const QString& path) { MyDebug.logMsg(type_log_info, origin_msg_generic, QString("File update: %1").arg(path)); } void QgGrifoBeamUpForm::setState(int s) { state=s; bool enable=false; if (state==0) { enable=true; //ui->cbNetowrkSelection->setEnabled(false); ui->tbGo->setText("Upload..."); } else ui->tbGo->setText("Break..."); //ui->tbNetwork->setEnabled(enable); ui->tbRefresh->setEnabled(enable); //ui->tbGo->setEnabled(enable); ui->tbFileSelect->setEnabled(enable); ui->tbDropSelect->setEnabled(enable); ui->leFile->setEnabled(enable); //ui->leDir->setEnabled(enable); ui->cbPartition->setEnabled(enable); ui->cbTarget->setEnabled(enable); entitiesForm->setEnabled(enable); if (enable) { if (ui->progressBar->minimum()==ui->progressBar->maximum()) { ui->progressBar->setRange(0, 100); ui->progressBar->setValue(0); ui->progressBar->setEnabled(false); } } ui->groupBox->setEnabled(enable); } void QgGrifoBeamUpForm::stateReady() { setState(0); if (pendingList.count()) { QString tmp=pendingList.at(0); pendingList.pop_front(); if (tmp.isEmpty()) { return; } ui->leFile->setText(tmp); selectByFile(tmp); uploadGo(); } } void QgGrifoBeamUpForm::stateBusy() { setState(1); } void QgGrifoBeamUpForm::uploadGo() { /*if (state!=0) { QMessageBox::question(this, QString(), QString("Break operation?")); return; } int n=ui->cbTarget->currentIndex(); //controlla se è stato selezionato un indirizzo target valido if (n<0) { ui->progressLabel->setText("Target not selected"); ui->leMsg->appendPlainText(QString("Target not selected")); QMessageBox::critical(this, QString(), QString("Target not selected")); return; } //controlla se il file da spedire è leggibile QFileInfo finfo(ui->leFile->text()); if (!finfo.isReadable()) { ui->leMsg->appendPlainText(QString("File not readable")); QMessageBox::critical(this, QString(), QString("File not readable")); return; } //controlla se l'indirizzo ftp del server a cui collegarci è valido QString tgtStr=ui->cbTarget->currentText(); tgtStr="ftp://"+ui->cbTarget->currentText(); QUrl url(tgtStr); if (!url.isValid()) { QString msg=QString("Invalid URL %1").arg(tgtStr); ui->progressLabel->setText(msg); ui->leMsg->appendPlainText(msg); QMessageBox::critical(this, QString(), msg); return; } //apertura connessione con server tftp remoto QHostAddress ha(url.host()); int port=url.port(); tftp.bindRemote(ha, port); //ui->progressLabel->setText(tmp); { MyDebug.logMsg(type_log_info, origin_msg_generic, QString("Upload to %1 %2@%3:%4...").arg(tgtStr).arg("?").arg(ha.toString()).arg(port)); } QString partName; n=ui->cbPartition->currentIndex(); if (n>=0) { unsigned long long p=ui->cbPartition->currentData().toULongLong(); if (p && !ui->cbPartition->currentText().isEmpty()) partName="$PGM:"+ui->cbPartition->currentText()+"/%1"; } if (partName=="") { partName ="$PGM:uploadfile/%1"; } QString fnameStr=finfo.fileName(); #if 0 { QZipReader zip(ui->leFile->text()); QList zlst=zip.fileInfoList(); if(zlst.size()) { QString tmpname=zlst.at(0).filePath; //standardDialog()->setFileInfo(QString("%1 (%2)").arg(tmpname).arg(params.simplifiedFileName)); fnameStr+="("+tmpname+")"; } } #endif QString opmsg=QString("%1 -> %2/%3").arg(fnameStr).arg(ui->cbTarget->currentText()).arg(partName); showMessage(opmsg); int qr=QMessageBox::question(this, QString(), opmsg, QMessageBox::Yes|QMessageBox::No|QMessageBox::Abort); if (qr!=QMessageBox::Yes) { if (qr==QMessageBox::Abort) pendingList.clear(); return; } //ui->progressLabel->setText("Upload start..."); bool ok=tftp.sendFile(ui->leFile->text(), partName); //ui->tbNetwork->setEnabled(false); ui->lbOperation->setText(opmsg); if (ok) { stateBusy(); //ui->tbGo->setEnabled(false); ui->progressBar->reset(); ui->progressBar->setRange(0, 0); ui->progressBar->setEnabled(true); }*/ } void QgGrifoBeamUpForm::dragEnterEvent(QDragEnterEvent * event) { if (event->mimeData()->hasUrls()) { QList lst=event->mimeData()->urls(); if ((lst.size()>0) && lst.size()<10) { //if (lst.at(0).isLocalFile()) event->acceptProposedAction(); } } } void QgGrifoBeamUpForm::dropEvent(QDropEvent * event) { QList lst=event->mimeData()->urls(); if (lst.size()>0) { for(int i=0; ileFile->setText(lst.at(0).path()); //selectByFile(lst.at(0).path()); addPendingList(lst.at(i).toLocalFile()); } } } } void QgGrifoBeamUpForm::selectWatchDir(const QString& dName) { if (dName.isEmpty()) return; QDir dir(dName); if (!dir.isReadable()) return; ui->leDir->setText(dName); fileWatcher.removePaths(fileWatcher.directories()); fileWatcher.addPath(dName); props.setProperty("watchedDirectory", dName); watchedFiles.clear(); watchedFiles=dir.entryList(QDir::Files|QDir::NoDotAndDotDot); } void QgGrifoBeamUpForm::addPendingList(const QString& file) { pendingList.append(file); if (state==0) { stateReady(); //ui->leFile->setText(lst.at(0).path()); selectByFile(file); //lst.at(0).path()); //uploadGo(); } } void QgGrifoBeamUpForm::showMessage(const QString& msg) { //ui->progressLabel->setText(msg); //ui->leMsg->appendPlainText(msg); addToLog(msg); } QString QgGrifoBeamUpForm::ShowFileInfo(const QString& fname, bool popup) { QFileInfo finfo(fname); if (!finfo.exists()) { QMessageBox::critical(0, "ERROR open file", "File

"+fname +"

is not available."); return ""; } DownloadableFile df; df.open(fname); BinaryFileInfo bfi=df.info(); BinaryInfo bi=bfi.binaryInfo; QString infoText=""; if (finfo.completeSuffix()=="zip") { if (!extractInfoFromZip(fname)) return ""; infoText= "File: "+bfi.filename+"

\n" +"File CRC32: "+QString("%1").arg(bfi.zip_crc32, 0, 16).toUpper()+"

\n"; infoText+= +" target flash: " +fileToWrite.targetFlash +"

\n" +" primary file: " +QFileInfo( fileToWrite.primaryFile ).fileName() +"

\n" +" primary file MD5: " +fileToWrite.primaryMD5 +"

\n" +" primary file: " +QFileInfo( fileToWrite.secondaryFile ).fileName() +"

\n" +" primary file MD5: " +fileToWrite.secondaryMD5 +"

\n"; entitiesForm->setUnCheckedAll(); //for every targets read from configuration files for (int i = 0; icountTarget(); i++) { targetItem tgt = flashTargets->getTarget(i); if (tgt.filePrefix==fileToWrite.targetFlash) { entitiesForm->setChecked(tgt.name); } } } else if (finfo.completeSuffix()=="bin") { infoText= "File: "+bfi.filename+"

\n" +"  Size: "+QString("%1").arg(bfi.uncompressed_size)+" ("+QString("%1").arg(bfi.compressed_size)+")

\n" +"  Container hash: "+bfi.file_md5+"

\n" +"File CRC32: "+QString("%1").arg(bfi.zip_crc32, 0, 16).toUpper()+"

\n"; infoText+= " Name: "+bi.m_name+"

\n" +" Version: "+bi.m_version+" "+bi.m_bid+"

\n" +" Date: "+bi.m_date+"

\n" +" IBC: "+bi.m_ibc+"

\n" +" P/N: "+bi.m_pn+"

\n" +" Part Type: "+bi.m_partType+"

\n" +" Architecture: "+bi.m_pn+" - "+bi.m_archName+"

\n" +" Format: "+bi.m_fmtName+"

\n" +" Generator: "+bi.m_generator+"

\n" //+" Version: "+bi.m_bid+"

\n" +" Info: "+bi.m_usr+"

\n" +" Host: "+bi.m_host+"

\n" +" Signature: "+bi.m_md5+"

\n"; fileToWrite.validConfig = false; } if (popup) QMessageBox::information(0, "File: "+bfi.sourcefile, infoText); return infoText; } void QgGrifoBeamUpForm::on_tbFileInfo_clicked() { ShowFileInfo(ui->leFile->text()); } void QgGrifoBeamUpForm::programWithProfile(bool checked) { /*QString address = QString("0x%1-0x%2").arg(profile.user_address_start_area, 0, 16).arg(profile.user_address_stop_area, 0, 16); QString srio = QString("%1@%2:%3").arg(profile.slotAddress).arg(profile.ip).arg(profile.port); int spi = int(profile.spiport); _dbHistory->addNewFile(profile.FileToSend, db_error_no_error, profile.fName, db_status_started, address, srio, spi);*/ if (ui->cbSimulate->checkState()==Qt::Checked) { //è simulazione con dati di test if (checked) programmer->start(1, ui->sbSectorSize->value(), ui->sbBase->value()); else programmer->start(0, ui->sbSectorSize->value(), ui->sbBase->value()); } else { //non è simulazione programmer->start(profile); } } void QgGrifoBeamUpForm:: on_btnStart_clicked(bool checked) { //indivisuare il profilo da usare per le operazione di programmazione if (!getProfile(ui->sbSectorSize->value(),ui->sbBase->value())) { //profile not valid to program return; } profile.writeRamp = (ui->cbWriteRamp->checkState()==Qt::Checked); profile.verifyFinal = (ui->cbVerifyAll->checkState()==Qt::Checked); profile.verifySector = (ui->cbVerifySector->checkState()==Qt::Checked); if (fileToWrite.validConfig) { // spi port primary 0 profile.spiport = primarySpiPort; profile.FileToSend = fileToWrite.primaryFile; profile.FileToSend2 = fileToWrite.secondaryFile; profile.write2Flash = true; QString address = QString("0x%1 - 0x%2").arg(profile.user_address_start_area, 0, 16). arg(profile.user_address_stop_area, 0, 16); QString msg = QString(STR_START_WORK).arg(fileToWrite.targetFlash).arg("primary").arg(address); addToLog(msg); /*//"... on %1 - spi port: %2 - address: %3." programWithProfile(checked); // spi port secondary 1 profile.spiport = secondarySpiPort; profile.FileToSend = fileToWrite.secondaryFile;*/ address = QString("0x%1 - 0x%2").arg(profile.user_address_start_area, 0, 16). arg(profile.user_address_stop_area, 0, 16); msg = QString(STR_START_WORK).arg(fileToWrite.targetFlash).arg("secondary").arg(address); addToLog(msg); programWithProfile(checked); } else { profile.FileToSend = ui->leFile->text(); profile.FileToSend2 = ""; profile.write2Flash = false; QString msg = ""; QString address = QString("0x%1 - 0x%2").arg(profile.user_address_start_area, 0, 16). arg(profile.user_address_stop_area, 0, 16); //controllo se si tratta di fpga dell'rfif if (!profile.isFpgaRFIF) { //Se non lo è allora devo selezionare il canale spi dove installare QInputDialog qDialogSpiPort ; QStringList items; items << QString("Primary"); items << QString("Secondary"); qDialogSpiPort.setComboBoxItems(items); qDialogSpiPort.setWindowTitle("SPI"); qDialogSpiPort.setLabelText("Select spi-port: "); if (qDialogSpiPort.exec()) { QString value = qDialogSpiPort.textValue(); if (value=="Primary") { profile.spiport = primarySpiPort; msg = QString(STR_START_WORK).arg(fileToWrite.targetFlash).arg("primary").arg(address); } else { profile.spiport = secondarySpiPort; msg = QString(STR_START_WORK).arg(fileToWrite.targetFlash).arg("secondary").arg(address); } } else { startEnabled(true); ui->btnWrite->setText("START"); ui->btnWrite->setStyleSheet("QPushButton { background-color: green; color:white; }\n" "QPushButton:enabled { background-color: rgb(0,200,0); color:white; }\n"); return; } } else //se si tratta della fpga dell'rfif allora devo configurare il profilo di download in altra maniera { //Se non lo è allora devo selezionare il canale spi dove installare QInputDialog qDialogSpiPort ; QStringList items; items << QString("GOLDEN"); items << QString("UPDATE"); qDialogSpiPort.setComboBoxItems(items); qDialogSpiPort.setWindowTitle(""); qDialogSpiPort.setLabelText("Select which part of RFIF fpga: "); if (qDialogSpiPort.exec()) { QString value = qDialogSpiPort.textValue(); if (value=="GOLDEN") { profile.spiport = primarySpiPort; address = QString("0x%1 - 0x%2").arg(profile.golden_address_start_area, 0, 16). arg(profile.golden_address_stop_area, 0, 16); msg = QString(STR_START_WORK).arg(fileToWrite.targetFlash).arg("GOLDEN").arg(address); } else { profile.spiport = secondarySpiPort; address = QString("0x%1 - 0x%2").arg(profile.user_address_start_area, 0, 16). arg(profile.user_address_stop_area, 0, 16); msg = QString(STR_START_WORK).arg(fileToWrite.targetFlash).arg("UPDATE").arg(address); } } else { startEnabled(true); ui->btnWrite->setText("START"); ui->btnWrite->setStyleSheet("QPushButton { background-color: green; color:white; }\n" "QPushButton:enabled { background-color: rgb(0,200,0); color:white; }\n"); return; } //profile.spiport = primarySpiPort; //msg = QString(STR_START_WORK).arg(fileToWrite.targetFlash).arg("NC").arg(address); } addToLog(msg); programWithProfile(checked); } } void QgGrifoBeamUpForm::statusUpdated(int sts, int progress, const QString& msg) { if (sts==s_erase || sts==s_write || sts==s_read) { ui->lbOperation->setText(QString("%1").arg(msg)); } else { addToLog(msg,sts); } if (progress>0) ui->progressBar->setValue(progress); } void QgGrifoBeamUpForm::on_btnStart_clicked() { } void QgGrifoBeamUpForm::on_btnReset_clicked() { //indivisuare il profilo da usare per le operazione di programmazione if (!getProfile(ui->sbSectorSize->value(),ui->sbBase->value())) { //profile not valid to program return; } profile.FileToSend = ui->leFile->text(); programmer->reset(profile); } void QgGrifoBeamUpForm::on_btnErase_clicked() { programmer->erase(1, ui->sbSectorSize->value(), ui->sbBase->value()); } void QgGrifoBeamUpForm::on_btnFlashID_clicked() { //indivisuare il profilo da usare per le operazione di programmazione if (!getProfile(ui->sbSectorSize->value(),ui->sbBase->value())) { //profile not valid to program return; } profile.FileToSend = ui->leFile->text(); programmer->readFlashID(profile); } void QgGrifoBeamUpForm::on_btnGetStatus_clicked() { //indivisuare il profilo da usare per le operazione di programmazione if (!getProfile(ui->sbSectorSize->value(),ui->sbBase->value())) { //profile not valid to program return; } profile.FileToSend = ui->leFile->text(); programmer->readStatusSPI(profile); } void QgGrifoBeamUpForm::on_btnFinish_clicked() { //indivisuare il profilo da usare per le operazione di programmazione if (!getProfile(ui->sbSectorSize->value(),ui->sbBase->value())) { //profile not valid to program return; } profile.FileToSend = ui->leFile->text(); programmer->terminate(profile); } void QgGrifoBeamUpForm::on_cbSimulate_clicked(bool checked) { programmer->setSimulate(checked); } void QgGrifoBeamUpForm::on_tbGo_clicked() { } void QgGrifoBeamUpForm::clearTargets() { memset(&targets, 0, sizeof targets); } //*********************************************************************** // update Grifo Download Site // Input parameters: checked = true if I also have to view the golden area of the flash // false if I have to display only the user area of the flash // Returns: //*********************************************************************** void QgGrifoBeamUpForm::updateGrifoDownloadSite(Qt::CheckState checked) { //clear targets struct clearTargets(); //clear treewidget for targets entitiesForm->clear(); //for every targets read from configuration files for (int i = 0; icountTarget(); i++) { //TgtMatch tgt = tgtMatchSet.db[i]; targetItem tgt = flashTargets->getTarget(i); if ((checked==Qt::Checked)) //|| //(checked==Qt::Unchecked && tgt.firmware_area!=flash_firmware_area_golden)) { MyDebug.logMsg(type_log_info, origin_msg_generic, QString("%1 %2 %3 %4").arg(tgt.name).arg(tgt.slotAddress).arg(tgt.description).arg(tgt.filePrefix)); {//Site QgGrifoDownloadSite* s=&targets.sites[targets.valid]; memset(&s->site, 0, sizeof s->site); bsk_download_site_t* site=&s->site; strncpy(site->address, tgt.slotAddress.toLatin1(), sizeof site->address); s->tgtFlash=&tgt; s->site.media_address=QHostAddress(flashTargets->getDefIp()).toIPv4Address(); s->site.media_port=flashTargets->getDefPort(); strncpy(s->site.name, tgt.name.toLatin1().constData(), sizeof s->site.name); ++targets.valid; entitiesForm->addSite(s); } } } } void QgGrifoBeamUpForm::on_cb_GoldenFlash_stateChanged() { updateGrifoDownloadSite(ui->cb_GoldenFlash->checkState()); } //*********************************************************************** // Show target info // Input parameters: // popup = display the dialog box // Returns: the complete string of target information //*********************************************************************** QString QgGrifoBeamUpForm::ShowTargetInfo(bool popup) { QString fName = entitiesForm->getFirstSelectedTarget(); const targetItem* tgt=flashTargets->getFromName(fName); if (!tgt) return QString(""); QString infoText= "Target: "+fName+"

\n" +"   Description: "+QString("%1").arg(tgt->description)+"

\n" +"   Name: "+QString("%1").arg(tgt->name)+"

\n" +"   Arch: "+QString("%1").arg(tgt->arch)+"

\n" +"   Slot Address: "+QString("%1").arg(tgt->slotAddress)+"

\n" +"   IP:PORT: "+QString("%1").arg(flashTargets->getDefIp())+":"+QString("%1").arg(flashTargets->getDefPort())+"

\n" +"

\n" +" FLASH:

\n"; if (tgt->model.type==flash_type_xcku040) { infoText+= " ->  Type: XCKU040

\n"; } else if(tgt->model.type==flash_type_xcku060) { infoText+= " ->  Type: XCKU060

\n"; } else { infoText+= " ->  Type: XC7A200

\n"; } if (tgt->model.byte3_4==bytes3address) { infoText+= " ->  Address: 3 bytes address

\n"; } else { infoText+= " ->  Address: 4 bytes address

\n"; } infoText+= " ->  GOLDEN Start-Stop address: "+QString("%1").arg(tgt->model.goldenAddressStartArea)+"-"+QString("%1").arg(tgt->model.goldenAddressStopArea)+"

\n"; infoText+= " ->  USER Start-Stop address: "+QString("%1").arg(tgt->model.userAddressStartArea)+"-"+QString("%1").arg(tgt->model.userAddressStopArea)+"

\n"; if (popup) QMessageBox::information(0, "Target: "+fName, infoText); return infoText; } void QgGrifoBeamUpForm::on_btnGetTargetInfo_clicked() { ShowTargetInfo(true); } //*********************************************************************** // Set profile, read information form selected fpga // Input parameters: // Returns: //*********************************************************************** bool QgGrifoBeamUpForm::getProfile(unsigned int sectorSize, unsigned int baseOffset) { QString fName = entitiesForm->getFirstSelectedTarget(); const targetItem *tgt = flashTargets->getFromName(fName); if (!tgt) { return false; } profile.fName = fName; bool bStatus= false; profile.user_address_start_area = QString(tgt->model.userAddressStartArea).toUInt(&bStatus, 16); if (!bStatus) { return false; } profile.user_address_stop_area = QString(tgt->model.userAddressStopArea).toUInt(&bStatus, 16); if (!bStatus) { return false; } profile.golden_address_start_area = QString(tgt->model.goldenAddressStartArea).toUInt(&bStatus, 16); if (!bStatus) { return false; } profile.golden_address_stop_area = QString(tgt->model.goldenAddressStopArea).toUInt(&bStatus, 16); if (!bStatus) { return false; } profile.BaseAddress = QString(tgt->model.userAddressStartArea).toUInt(&bStatus, 16); if (!bStatus) { return false; } profile.BaseOffset = baseOffset; profile.byteddress = (reg_moder_byteaddress_t)tgt->model.byte3_4; profile.ip = flashTargets->getDefIp(); profile.port = QString("%1").arg(flashTargets->getDefPort()); profile.SectorSize_KBytes = sectorSize; profile.slotAddress = tgt->slotAddress; //profile.spiport = tgt->spiPort; /*if (tgt->model->type==flash_type_xcku040) { //xcku040 profile.dimMbit = FLASH_128Mbit; } else { //xc7a200 and xcku060 profile.dimMbit = FLASH_256Mbit; }*/ profile.writeRamp = (ui->cbWriteRamp->checkState()==Qt::Checked); profile.verifyFinal = (ui->cbVerifyAll->checkState()==Qt::Checked); profile.verifySector = (ui->cbVerifySector->checkState()==Qt::Checked); fileToWrite.targetFlash = tgt->filePrefix; profile.isFpgaRFIF = false; if (tgt->model.idModel==AESA_RFIF_MODEL) profile.isFpgaRFIF = true; return true; } void QgGrifoBeamUpForm::on_cb_TargetAddress_clicked(bool checked) { programmer->setSRIOMemory(checked); } void QgGrifoBeamUpForm::on_btnGetValue_clicked() { QString address = ui->sbGetValue->text(); unsigned int len=256; char data[len]; uint32_t dataInt[256]; //legge mediante srio un valore presente in memoria all'indirizzo indicato QString remoteFile=QString("$SRIO:%1/%2+%3").arg(profile.slotAddress).arg(address, 0, 16).arg(len); MyDebug.logMsg(type_log_info, origin_msg_srio, QString("Command %1").arg(remoteFile)); try { Q_EMIT programmer->readRequest(remoteFile, dataInt, len); //programmer->waitRxEvent(); } catch (...) { MyDebug.logMsg(type_log_error, origin_msg_tftp, "not inizialized"); } sprintf (data, "0x%8.8lX", (long unsigned int)dataInt[0]); ui->lblGetValue->setText(data); } void QgGrifoBeamUpForm::on_btnMem_clicked() { ui->sbGetValue->setText(QString("0x%1").arg(BASE_ADDRESS_MEM,0,16)); } void QgGrifoBeamUpForm::on_btnFPGA_clicked() { ui->sbGetValue->setText(QString("0x%1").arg(BASE_ADDRESS_IF,0,16)); } void QgGrifoBeamUpForm::on_btnHistory_clicked() { _dbHistory->refreshList(); HistoryDBForm HistoryDBWindow; HistoryDBWindow.setWindowTitle("History DB"); HistoryDBWindow.setDB(_dbHistory); HistoryDBWindow.exec(); } void QgGrifoBeamUpForm::on_btnAddHistory_clicked() { //(QString _file, db_error_t _error, QString _where) QString fileName = ui->leFile->text(); db_error_t _error = db_error_t(ui->cbError->currentIndex()); db_status_t _status = db_status_t(ui->cbStatus->currentIndex()); QString fName = entitiesForm->getFirstSelectedTarget(); const targetItem* tgt=flashTargets->getFromName(fName); if (!tgt) return; QString address = QString("%1-%2").arg(tgt->model.userAddressStartArea).arg(tgt->model.userAddressStopArea); QString srio = QString("%1@%2:%3").arg(tgt->slotAddress).arg(flashTargets->getDefIp()).arg(flashTargets->getDefPort()); int spi = int(profile.spiport); _dbHistory->addNewFile(fileName, _error, fName, _status, address, srio, spi); } void QgGrifoBeamUpForm::on_tbRefresh_clicked() { } void QgGrifoBeamUpForm::on_tbHistory_clicked() { on_btnHistory_clicked(); } void QgGrifoBeamUpForm::on_tbFileSelect_clicked() { } void QgGrifoBeamUpForm::startEnabled(bool _status) { ui->tbRefresh->setEnabled(_status); ui->tbFileSelect->setEnabled(_status); ui->tbFileInfo->setEnabled(_status); ui->tbHistory->setEnabled(_status); entitiesForm->setEnabled(_status); } void QgGrifoBeamUpForm::on_btnWrite_clicked() { //check if connected if (!IS_TFTP_CONNECTED) { QMessageBox::warning(0, STR_TITLE_SERVER, STR_SERVER_IS_NOT_CONNECTED); return; } //check if one target is selected QString fName = entitiesForm->getFirstSelectedTarget(); if (fName=="") { QMessageBox::warning(0, STR_TITLE_SELECTION, STR_SELECTION_NOT_VALID); return; } //check if selected file exists QFileInfo finfo(ui->leFile->text()); if (!finfo.exists()) { QMessageBox::critical(0, "ERROR open file", "File

"+ui->leFile->text() +"

is not available."); return; } if (ui->btnWrite->text()=="START") { ui->btnWrite->setText("STOP"); startEnabled(false); on_btnStart_clicked(true); ui->btnWrite->setStyleSheet("QPushButton { background-color: red; color:white; }\n" "QPushButton:enabled { background-color: rgb(200,0,0); color:white; }\n"); } else { startEnabled(true); ui->btnWrite->setText("START"); ui->btnWrite->setStyleSheet("QPushButton { background-color: green; color:white; }\n" "QPushButton:enabled { background-color: rgb(0,200,0); color:white; }\n"); } } /******************************************************************** * extract info about fpga-flash to programme with this file * Input parameters: complete file zip path * Return: true if config is ok * false if config is not ok */ bool QgGrifoBeamUpForm::extractInfoFromZip(QString _fileName) { resetFileToWrite(); //check if tmp folder is already created if (QDir(TMP_FOLDER).exists()) { //delete tmp folder if (QDir(TMP_FOLDER).removeRecursively()) { MyDebug.logMsg(type_log_info, origin_msg_generic, "Tmp folder deleted."); } else { MyDebug.logMsg(type_log_error, origin_msg_generic, "Tmp folder is not deleted."); } } if (!QDir().mkdir(TMP_FOLDER)) { MyDebug.logMsg(type_log_error, origin_msg_history, QString("ERROR create tmp folder %1").arg(TMP_FOLDER)); return false; } //extract info from zip to tmp folder QZipReader zipfile(_fileName); if(zipfile.count()!=0) { for (int i = 0; icurrentCharFormat(); tf.setForeground(QBrush(newColor)); tf.setBackground(QBrush(newBckColor)); logtext->setCurrentCharFormat(tf); } void QgGrifoBeamUpForm::addToLog(QString _msg, unsigned int sts) { QString tick = QDateTime::currentDateTime().toString("hh:mm:ss.zzz"); switch (sts) { case s_init: case s_status: case s_read_id: case s_erase: case s_write: default: ui->leMsg->appendPlainText(QString("%1 - %2").arg(tick).arg(_msg)); break; case s_error: setColorLog(ui->leMsg, Qt::red, Qt::black); ui->leMsg->appendPlainText(QString("%1 - %2").arg(tick).arg(_msg)); setColorLog(ui->leMsg, Qt::black, Qt::white); break; case s_end: setColorLog(ui->leMsg, Qt::green,Qt::black); ui->leMsg->appendPlainText(QString("%1 - %2").arg(tick).arg(_msg)); setColorLog(ui->leMsg, Qt::black,Qt::white); break; case s_question: setColorLog(ui->leMsg, Qt::cyan,Qt::black); ui->leMsg->appendPlainText(QString("%1 - %2").arg(tick).arg(_msg)); setColorLog(ui->leMsg, Qt::black,Qt::white); break; case s_warning: setColorLog(ui->leMsg, Qt::yellow,Qt::black); ui->leMsg->appendPlainText(QString("%1 - %2").arg(tick).arg(_msg)); setColorLog(ui->leMsg, Qt::black,Qt::white); break; } } void QgGrifoBeamUpForm::setTargetOnScreen() { unsigned int numTargets = flashTargets->countTarget(); targetItem tgt; for (unsigned int i=0; igetTarget(i); MyDebug.logMsg(type_log_info, origin_msg_generic, QString("%1 %2 %3 %4").arg(tgt.g).arg(tgt.name).arg(tgt.slotAddress).arg(tgt.arch)); {//Site QgGrifoDownloadSite* s=&targets.sites[targets.valid]; memset(&s->site, 0, sizeof s->site); bsk_download_site_t* site=&s->site; strncpy(site->address, tgt.slotAddress.toLatin1(), sizeof site->address); s->tgtFlash = &tgt; s->site.media_address = QHostAddress(flashTargets->getDefIp()).toIPv4Address(); s->site.media_port = flashTargets->getDefPort(); strncpy(s->site.name, tgt.name.toLatin1().constData(), sizeof s->site.name); ++targets.valid; entitiesForm->addSite(s); }//Site } entitiesForm->setDefaultTarget(flashTargets->getDefTarget()); entitiesForm->setVisible(true); }