/* Copyright (C) 2004-2009 Alexander Neundorf This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "qcppdialogimpl.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //Added by qt3to4: #include #include #include #include #include #include #include using namespace std; #include #include #include #include #include #include #include #include #include void millisleep(int ms) { if (ms>0) { struct timeval tv; tv.tv_sec=0; tv.tv_usec=ms*1000; select(0, 0, 0, 0, &tv); } } QCPPDialogImpl::QCPPDialogImpl(QWidget* parent) :QWidget(parent) ,m_isConnected(false) ,m_fd(-1) ,m_cmdBufIndex(0) ,m_notifier(0) ,m_sz(0) ,m_progress(0) ,m_progressStepSize(1000) ,m_fileDlg(0) ,m_outputTimer(this) ,m_keyRepeatTimer(this) ,m_keyCode(0) ,m_hexBytes(0) ,m_previousChar('\0') { QCoreApplication::setOrganizationName("CuteCom"); // QCoreApplication::setOrganizationDomain("mysoft.com"); QCoreApplication::setApplicationName("CuteCom"); this->setupUi(this); fillBaudCb(); connect(m_connectPb, SIGNAL(clicked()), this, SLOT(connectTTY())); connect(m_closePb, SIGNAL(clicked()), this, SLOT(disconnectTTY())); connect(m_clearOutputPb, SIGNAL(clicked()), this, SLOT(clearOutput())); // connect(m_clearInputPb, SIGNAL(clicked()), m_oldCmdsLb, SLOT(clear())); connect(m_cmdLe, SIGNAL(returnPressed()), this, SLOT(execCmd())); connect(m_sendPb, SIGNAL(clicked()), this, SLOT(sendFile())); connect(m_aboutPb, SIGNAL(clicked()), this, SLOT(showAboutMsg())); connect(m_quitPb, SIGNAL(clicked()), this, SLOT(close())); connect(m_oldCmdsLb, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(oldCmdClicked(QListWidgetItem*))); connect(m_oldCmdsLb, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(execCmd())); connect(m_hexOutputCb, SIGNAL(toggled(bool)), this, SLOT(hexOutputClicked(bool))); connect(m_connectPb, SIGNAL(clicked()), this, SLOT(saveSettings())); connect(m_deviceCb, SIGNAL(activated(int)), this, SLOT(saveSettings())); connect(m_baudCb, SIGNAL(activated(int)), this, SLOT(saveSettings())); connect(m_dataBitsCb, SIGNAL(activated(int)), this, SLOT(saveSettings())); connect(m_parityCb, SIGNAL(activated(int)), this, SLOT(saveSettings())); connect(m_stopCb, SIGNAL(activated(int)), this, SLOT(saveSettings())); connect(m_protoPb, SIGNAL(activated(int)), this, SLOT(saveSettings())); connect(m_softwareCb, SIGNAL(clicked()), this, SLOT(saveSettings())); connect(m_hardwareCb, SIGNAL(clicked()), this, SLOT(saveSettings())); connect(m_readCb, SIGNAL(clicked()), this, SLOT(saveSettings())); connect(m_writeCb, SIGNAL(clicked()), this, SLOT(saveSettings())); connect(m_applyCb, SIGNAL(clicked()), this, SLOT(saveSettings())); connect(m_hexOutputCb, SIGNAL(clicked()), this, SLOT(saveSettings())); connect(m_inputModeCb, SIGNAL(activated(int)), this, SLOT(saveSettings())); connect(m_charDelaySb, SIGNAL(valueChanged(int)), this, SLOT(saveSettings())); connect(m_logAppendCb, SIGNAL(activated(int)), this, SLOT(saveSettings())); connect(m_applyCb, SIGNAL(toggled(bool)), this, SLOT(enableSettingWidgets(bool))); connect(m_logFileFileDialog, SIGNAL(clicked()), this, SLOT(chooseLogFile())); connect(&m_outputTimer, SIGNAL(timeout()), this, SLOT(doOutput())); connect(&m_keyRepeatTimer, SIGNAL(timeout()), this, SLOT(sendKey())); connect(m_enableLoggingCb, SIGNAL(toggled(bool)), this, SLOT(enableLogging(bool))); // connect(m_enableLoggingCb, SIGNAL(toggled(bool)), this, SLOT(enableLogging(bool))); m_outputView->setWordWrapMode(QTextOption::WrapAnywhere); m_outputView->document()->setMaximumBlockCount(500); // TODO ? m_outputView->setWordWrap(Q3TextEdit::WidgetWidth); /* QAccel* accel=new QAccel(this); accel->insertItem(CTRL+Key_C, 3); accel->insertItem(CTRL+Key_Q, 17); accel->insertItem(CTRL+Key_S, 19); connect(accel, SIGNAL(activated(int)), this, SLOT(sendByte(int)));*/ m_outputTimerStart.start(); readSettings(); disconnectTTY(); m_cmdLe->installEventFilter(this); } void QCPPDialogImpl::fillBaudCb() { #ifdef B0 m_baudCb->addItem("0"); #endif #ifdef B50 m_baudCb->addItem("50"); #endif #ifdef B75 m_baudCb->addItem("75"); #endif #ifdef B110 m_baudCb->addItem("110"); #endif #ifdef B134 m_baudCb->addItem("134"); #endif #ifdef B150 m_baudCb->addItem("150"); #endif #ifdef B200 m_baudCb->addItem("200"); #endif #ifdef B300 m_baudCb->addItem("300"); #endif #ifdef B600 m_baudCb->addItem("600"); #endif #ifdef B1200 m_baudCb->addItem("1200"); #endif #ifdef B1800 m_baudCb->addItem("1800"); #endif #ifdef B2400 m_baudCb->addItem("2400"); #endif #ifdef B4800 m_baudCb->addItem("4800"); #endif #ifdef B7200 m_baudCb->addItem("7200"); #endif #ifdef B9600 m_baudCb->addItem("9600"); #endif #ifdef B14400 m_baudCb->addItem("14400"); #endif #ifdef B19200 m_baudCb->addItem("19200"); #endif #ifdef B28800 m_baudCb->addItem("28800"); #endif #ifdef B38400 m_baudCb->addItem("38400"); #endif #ifdef B57600 m_baudCb->addItem("57600"); #endif #ifdef B76800 m_baudCb->addItem("76800"); #endif // this one is the default (without special reason) m_baudCb->addItem("115200"); m_baudCb->setCurrentIndex(m_baudCb->count()-1); #ifdef B128000 m_baudCb->addItem("128000"); #endif #ifdef B230400 m_baudCb->addItem("230400"); #endif #ifdef B460800 m_baudCb->addItem("460800"); #endif #ifdef B576000 m_baudCb->addItem("576000"); #endif #ifdef B921600 m_baudCb->addItem("921600"); #endif } void QCPPDialogImpl::resizeEvent(QResizeEvent *e) { QWidget::resizeEvent(e); saveSettings(); } void QCPPDialogImpl::saveSettings() { QSettings settings; settings.setValue("/cutecom/HardwareHandshake", m_hardwareCb->isChecked()); settings.setValue("/cutecom/SoftwareHandshake", m_softwareCb->isChecked()); settings.setValue("/cutecom/OpenForReading", m_readCb->isChecked()); settings.setValue("/cutecom/OpenForWriting", m_writeCb->isChecked()); settings.setValue("/cutecom/DontApplySettings", !m_applyCb->isChecked()); settings.setValue("/cutecom/Device", m_deviceCb->currentText()); settings.setValue("/cutecom/Baud", m_baudCb->currentItem()); settings.setValue("/cutecom/Databits", m_dataBitsCb->currentItem()); settings.setValue("/cutecom/Parity", m_parityCb->currentItem()); settings.setValue("/cutecom/Stopbits", m_stopCb->currentItem()); settings.setValue("/cutecom/Protocol", m_protoPb->currentItem()); settings.setValue("/cutecom/width", width()); settings.setValue("/cutecom/height", height()); settings.setValue("/cutecom/LineMode", m_inputModeCb->currentItem()); settings.setValue("/cutecom/HexOutput", m_hexOutputCb->isChecked()); settings.setValue("/cutecom/CharDelay", m_charDelaySb->value()); settings.setValue("/cutecom/SendFileDialogStartDir", m_sendFileDialogStartDir); settings.setValue("/cutecom/LogFileName", m_logFileLe->text()); settings.setValue("/cutecom/AppendToLogFile", m_logAppendCb->currentItem()); QString currentDevice=m_deviceCb->currentText(); settings.setValue("/cutecom/CurrentDevice", currentDevice); bool currentDeviceIsInList=false; QStringList devices; for (int i=0; icount(); i++) { QString s=m_deviceCb->itemText(i); devices<count(); if (historyCount>50) { historyCount=50; } QStringList saveHist; for (unsigned int i=m_oldCmdsLb->count()-historyCount; icount(); i++) { saveHist << m_oldCmdsLb->item(i)->text(); } settings.setValue("/cutecom/History", saveHist); } void QCPPDialogImpl::readSettings() { QSettings settings; m_hardwareCb->setChecked(settings.value("/cutecom/HardwareHandshake", false).toBool()); m_softwareCb->setChecked(settings.value("/cutecom/SoftwareHandshake", false).toBool()); m_readCb->setChecked(settings.value("/cutecom/OpenForReading", true).toBool()); m_writeCb->setChecked(settings.value("/cutecom/OpenForWriting", true).toBool()); m_applyCb->setChecked(!settings.value("/cutecom/DontApplySettings", false).toBool()); enableSettingWidgets(m_applyCb->isChecked()); int defaultBaud = settings.value("/cutecom/Baud", -1).toInt(); if (defaultBaud != -1) { m_baudCb->setCurrentIndex(defaultBaud); } m_dataBitsCb->setCurrentIndex(settings.value("/cutecom/Databits", 3).toInt()); m_parityCb->setCurrentIndex(settings.value("/cutecom/Parity", 0).toInt()); m_stopCb->setCurrentIndex(settings.value("/cutecom/Stopbits", 0).toInt()); m_protoPb->setCurrentIndex(settings.value("/cutecom/Protocol", 0).toInt()); m_inputModeCb->setCurrentIndex(settings.value("/cutecom/LineMode", 0).toInt()); m_hexOutputCb->setChecked(settings.value("/cutecom/HexOutput", false).toBool()); m_charDelaySb->setValue(settings.value("/cutecom/CharDelay", 1).toInt()); m_sendFileDialogStartDir=settings.value("/cutecom/SendFileDialogStartDir", QDir::homePath()).toString(); m_logFileLe->setText(settings.value("/cutecom/LogFileName", QDir::homePath()+"/cutecom.log").toString()); m_logAppendCb->setCurrentIndex(settings.value("/cutecom/AppendToLogFile", 0).toInt()); int x=settings.value("/cutecom/width", -1).toInt(); int y=settings.value("/cutecom/height", -1).toInt(); if ((x>100) && (y>100)) { resize(x,y); } bool entryFound = settings.contains("/cutecom/AllDevices"); QStringList devices=settings.value("/cutecom/AllDevices").toStringList(); if (!entryFound) { devices<<"/dev/ttyS0"<<"/dev/ttyS1"<<"/dev/ttyS2"<<"/dev/ttyS3"; } m_deviceCb->insertItems(0, devices); int indexOfCurrentDevice = devices.indexOf(settings.value("/cutecom/CurrentDevice", "/dev/ttyS0").toString()); // fprintf(stderr, "currentDEev: -%s - index: %d\n", settings.value("/cutecom/CurrentDevice", "/dev/ttyS0").toString().toLatin1().constData(), indexOfCurrentDevice); if (indexOfCurrentDevice!=-1) { m_deviceCb->setCurrentIndex(indexOfCurrentDevice); } QStringList history=settings.value("/cutecom/History").toStringList(); if (!history.empty()) { m_oldCmdsLb->addItems(history); m_oldCmdsLb->setCurrentRow(m_oldCmdsLb->count()-1); m_oldCmdsLb->scrollToItem(m_oldCmdsLb->currentItem()); m_oldCmdsLb->clearSelection(); } } void QCPPDialogImpl::showAboutMsg() { QMessageBox::about(this, tr("About CuteCom"), tr("This is CuteCom 0.22.0
(c)2004-2009 Alexander Neundorf, <neundorf@kde.org>
Licensed under the GNU GPL v2")); } void QCPPDialogImpl::sendFile() { if (m_fileDlg==0) { m_fileDlg=new QFileDialog(); m_fileDlg->setDirectory(m_sendFileDialogStartDir); m_fileDlg->setFileMode(QFileDialog::ExistingFile); } QString filename; if ( m_fileDlg->exec() == QDialog::Accepted ) { QStringList fn = m_fileDlg->selectedFiles(); if(!fn.isEmpty()) { filename = fn[0]; } m_sendFileDialogStartDir=m_fileDlg->directory().absolutePath(); saveSettings(); } else { return; } unsigned int charDelay=m_charDelaySb->value(); if (m_protoPb->currentText()=="Script") { QFile file(filename); if (!file.open(QIODevice::ReadOnly)) { QMessageBox::information(this, tr("Opening file failed"), tr("Could not open file %1").arg(filename)); return; } QTextStream stream(&file); while (!stream.atEnd()) { QString nextLine=stream.readLine(); nextLine=nextLine.left((unsigned int)nextLine.indexOf('#')); if (nextLine.isEmpty()) { continue; } if (!sendString(nextLine)) { QMessageBox::information(this, tr("Comm error"), tr("Sending failed")); return; } millisleep(charDelay*3); } } else if (m_protoPb->currentText()=="Plain") { QFile file(filename); if (!file.open(QIODevice::ReadOnly)) { QMessageBox::information(this, tr("Opening file failed"), tr("Could not open file %1").arg(filename)); return; } QByteArray data=file.readAll(); delete m_progress; m_progress=new QProgressDialog(tr("Sending file..."), tr("Cancel"), 0, 100, this); m_progress->setMinimumDuration(100); unsigned int step=data.size()/100; if (step<1) { step=1; } for (int i=0; isetValue(i/step); qApp->processEvents(); } sendByte(data.data()[i], charDelay); if ((data.data()[i]=='\n') || (data.data()[i]=='\r')) //wait twice as long after bytes which might be line ends (helps some uCs) { millisleep(charDelay); } // if (!sendByte(data.data()[i])) if (0) { QMessageBox::information(this, tr("Comm error"), tr("Sending failed (%1/%2").arg(i).arg(data.count())); break; } if ( m_progress->wasCanceled() ) { break; } } delete m_progress; m_progress=0; } else if ((m_protoPb->currentText()=="XModem") || (m_protoPb->currentText()=="YModem") || (m_protoPb->currentText()=="ZModem") || (m_protoPb->currentText()=="1kXModem")) { // QProcess sx(this); disconnectTTYRestore(false); m_sz=new Q3Process(this); m_sz->addArgument("sh"); m_sz->addArgument("-c"); // QString tmp=QString("sx -vv \"")+filename+"\" < "+m_deviceCb->currentText()+" > "+m_deviceCb->currentText(); QString tmp=QString("sz "); if (m_protoPb->currentText()=="XModem") { tmp+="--xmodem "; } else if (m_protoPb->currentText()=="YModem") { tmp+="--ymodem "; } else if (m_protoPb->currentText()=="ZModem") { tmp+="--zmodem "; } else if (m_protoPb->currentText()=="1kXModem") { tmp+="--xmodem --1k "; } tmp=tmp+"-vv \""+filename+"\" < "+m_deviceCb->currentText()+" > "+m_deviceCb->currentText(); m_sz->addArgument(tmp); m_sz->setCommunication(Q3Process::Stderr); connect(m_sz, SIGNAL(readyReadStderr()), this, SLOT(readFromStderr())); /* m_sz->addArgument("sx"); m_sz->addArgument("-vv"); m_sz->addArgument(filename); m_sz->setCommunication(QProcess::Stdin|QProcess::Stdout|QProcess::Stderr); connect(m_sz, SIGNAL(readyReadStdout()), this, SLOT(readFromStdout())); connect(m_sz, SIGNAL(readyReadStderr()), this, SLOT(readFromStderr()));*/ connect(m_sz, SIGNAL(processExited()), this, SLOT(sendDone())); if (!m_sz->start()) { QMessageBox::information(this, tr("Comm error"), tr("Could not start sx")); delete m_sz; m_sz=0; connectTTY(); return; } m_progress=new QProgressDialog(tr("Sending file via xmodem..."), tr("Cancel"), 0, 100, this); connect(m_progress, SIGNAL(cancelled()), this, SLOT(killSz())); m_progress->setMinimumDuration(100); QFileInfo fi(filename); m_progressStepSize=fi.size()/1024/100; if (m_progressStepSize<1) { m_progressStepSize=1; } // cerr<<"while(isRunning)"<setValue(0); while (m_sz->isRunning()) { qApp->processEvents(); millisleep(10); } // cerr<<"----------------- sx done"<currentText())); } } void QCPPDialogImpl::killSz() { if (m_sz==0) { return; } m_sz->tryTerminate(); } void QCPPDialogImpl::readFromStdout() { QByteArray ba=m_sz->readStdout(); // cerr<<"readFromStdout() "<0) { int bytesWritten=::write(m_fd, src, (bytesToWrite>CUTECOMM_BUFSIZE?CUTECOMM_BUFSIZE:bytesToWrite)); if (bytesWritten<0) { // cerr<<"readFromStdout() error "<readStderr(); // cerr<<"readFromStderr() "<-1) { QString captured=regex.cap(1); // cerr<<"captured kb: -"<setValue(p); } } } // else // cerr<<"--------"<type()==QEvent::KeyPress)) { if (ke->state()==Qt::NoModifier) { if (ke->key()==Qt::Key_Up) { prevCmd(); return true; } else if (ke->key()==Qt::Key_Down) { nextCmd(); return true; } } else if (ke->modifiers()==Qt::ControlModifier) { if (ke->key()==Qt::Key_C) { // std::cerr<<"c"; m_keyCode=3; sendByte(m_keyCode, 0); m_keyRepeatTimer.setSingleShot(false); m_keyRepeatTimer.start(0); return true; } else if (ke->key()==Qt::Key_Q) { // std::cerr<<"#"; m_keyCode=17; sendByte(m_keyCode, 0); return true; } else if (ke->key()==Qt::Key_S) { m_keyCode=19; sendByte(m_keyCode, 0); return true; } } } else if ((watched==m_cmdLe) && (e->type()==QEvent::KeyRelease)) { m_keyRepeatTimer.stop(); } return false; } void QCPPDialogImpl::sendKey() { // std::cerr<<"-"; sendByte(m_keyCode, 0); } void QCPPDialogImpl::oldCmdClicked(QListWidgetItem* item) { if (item==0) { return; } int index=m_oldCmdsLb->row(item); m_cmdLe->setText(item->text()); m_cmdBufIndex=m_oldCmdsLb->count()-index; m_cmdLe->setFocus(); } void QCPPDialogImpl::prevCmd() { if (m_oldCmdsLb->count()<=m_cmdBufIndex) { return; } // std::cerr<<"prevCmd() count: "<count()<<" bufIndex: "<< m_cmdBufIndex++; QListWidgetItem* item=m_oldCmdsLb->item(m_oldCmdsLb->count()-m_cmdBufIndex); if (item!=0) { m_oldCmdsLb->setCurrentItem(item); m_cmdLe->setText(item->text()); } // std::cerr<<"prev() count: "<count()<<" bufIndex: "<clear(); m_oldCmdsLb->setCurrentItem(0); // TODO ? m_oldCmdsLb->setCurrentIndex(0); } else { QListWidgetItem* it=m_oldCmdsLb->item(m_oldCmdsLb->count()-m_cmdBufIndex); m_oldCmdsLb->setCurrentItem(it); m_cmdLe->setText(it->text()); } // std::cerr<<"next() count: "<count()<<" bufIndex: "<text().trimmed(); m_cmdLe->clear(); if (!cmd.isEmpty()) { if ((m_oldCmdsLb->count()<1) || (m_oldCmdsLb->item(m_oldCmdsLb->count()-1)->text()!=cmd)) { m_oldCmdsLb->addItem(cmd); m_oldCmdsLb->setCurrentRow(m_oldCmdsLb->count()-1); if (m_oldCmdsLb->count()>50) { #if QT_VERSION >= 0x040300 m_oldCmdsLb->removeItemWidget(m_oldCmdsLb->item(0)); #else /* QT_VERSION >= 0x030000 */ m_oldCmdsLb->setItemWidget(m_oldCmdsLb->item(0), 0); #endif /* QT_VERSION >= 0x030000 */ } saveSettings(); } } m_oldCmdsLb->clearSelection(); if (m_fd==-1) { return; } sendString(cmd); /* std::cerr<<"paras: "<paragraphs()<paragraphs()>1100) { m_outputView->setUpdatesEnabled(false); m_outputView->setSelection(0, 0, 100, 0); m_outputView->removeSelectedText(); m_outputView->scrollToBottom(); m_outputView->append("abc\n"); m_outputView->setUpdatesEnabled(true); } else*/ /* m_outputView->setCursorPosition(m_outputView->paragraphs()-1, 0); static int i=0; i++; QString s=QString::number(i); s=" -"+s+"-\n "; m_outputView->insert(s);*/ /* m_outputView->insert("abc"); m_outputView->insert("def"); m_outputView->insert("ghi\n"); m_outputView->update();*/ } bool QCPPDialogImpl::sendString(const QString& s) { unsigned int lineMode=m_inputModeCb->currentIndex(); unsigned int charDelay=m_charDelaySb->value(); if (lineMode==4) // hex { QString hex=s; hex.remove(QRegExp("\\s")); if ((hex.startsWith("0x")) || (hex.startsWith("0X"))) { hex=hex.mid(2); } if (hex.length()%2 != 0) { hex="0"+hex; } for (int i=0; icurrentText(); int baudrate=m_baudCb->currentText().toInt(); int dataBits=m_dataBitsCb->currentText().toInt(); QString parity=m_parityCb->currentText(); QString stop=m_stopCb->currentText(); bool softwareHandshake=m_softwareCb->isChecked(); bool hardwareHandshake=m_hardwareCb->isChecked(); int flags=0; if (m_readCb->isChecked() && m_writeCb->isChecked()) { flags=O_RDWR; } else if (!m_readCb->isChecked() && m_writeCb->isChecked()) { flags=O_WRONLY; } else if (m_readCb->isChecked() && !m_writeCb->isChecked()) { flags=O_RDONLY; } else { QMessageBox::information(this, tr("Error"), tr("Opening the device neither for reading nor writing doesn't seem to make much sense ;-)")); return; } m_fd=open(dev.toLatin1(), flags | O_NDELAY); if (m_fd<0) { std::cerr<<"opening failed"<isChecked()) { int n = fcntl(m_fd, F_GETFL, 0); fcntl(m_fd, F_SETFL, n & ~O_NDELAY); if (tcgetattr(m_fd, &m_oldtio)!=0) { std::cerr<<"tcgetattr() 2 failed"<setEnabled(false); m_deviceCb->setEnabled(false); enableSettingWidgets(false); m_applyCb->setEnabled(false); m_readCb->setEnabled(false); m_writeCb->setEnabled(false); m_isConnected=true; if (m_readCb->isChecked()) { m_notifier=new QSocketNotifier(m_fd, QSocketNotifier::Read, this); connect(m_notifier, SIGNAL(activated(int)), this, SLOT(readData(int))); } m_oldCmdsLb->setEnabled(true); m_cmdLe->setEnabled(true); m_sendPb->setEnabled(true); m_protoPb->setEnabled(true); m_closePb->setEnabled(true); m_cmdLe->setFocus(); m_previousChar = '\0'; m_hexBytes=0; } void QCPPDialogImpl::enableSettingWidgets(bool enable) { m_baudCb->setEnabled(enable); m_dataBitsCb->setEnabled(enable); m_parityCb->setEnabled(enable); m_stopCb->setEnabled(enable); m_softwareCb->setEnabled(enable); m_hardwareCb->setEnabled(enable); } void QCPPDialogImpl::disconnectTTY() { disconnectTTYRestore(m_applyCb->isChecked()); } void QCPPDialogImpl::disconnectTTYRestore(bool restoreSettings) { m_outputTimer.stop(); m_outputBuffer=""; // std::cerr<<"closing "<setEnabled(true); m_deviceCb->setEnabled(true); if (m_applyCb->isChecked()) { enableSettingWidgets(true); } m_applyCb->setEnabled(true); m_readCb->setEnabled(true); m_writeCb->setEnabled(true); m_oldCmdsLb->setEnabled(false); m_cmdLe->setEnabled(false); m_sendPb->setEnabled(false); m_protoPb->setEnabled(false); m_closePb->setEnabled(false); m_connectPb->setFocus(); m_isConnected=false; delete m_notifier; m_notifier=0; } /** This function features some code from minicom 2.0.0, src/sysdep1.c */ void QCPPDialogImpl::setNewOptions(int baudrate, int databits, const QString& parity, const QString& stop, bool softwareHandshake, bool hardwareHandshake) { struct termios newtio; // memset(&newtio, 0, sizeof(newtio)); if (tcgetattr(m_fd, &newtio)!=0) { std::cerr<<"tcgetattr() 3 failed"<writeToStdin(ba); return; } if (m_logFile.isOpen()) { m_logFile.write(m_buf, bytesRead); } QString text; char buf[16]; for (int i=0; iisChecked()) { if ((m_hexBytes % 16) == 0) { snprintf(buf, 16, "%08x: ", m_hexBytes); text+=buf; } unsigned int b=*c; snprintf(buf, 16, "%02x ", b & 0xff); text+=buf; m_hexBytes++; if ((m_hexBytes % 16)==0) { text+="\n"; } else if ((m_hexBytes % 8)==0) { text+=" "; } } else { // also print a newline for \r, and print only one newline for \r\n if ((isprint(*c)) || (*c=='\n') || (*c=='\r')) { if (*c=='\r') { text+='\n'; } else if (*c=='\n') { if (m_previousChar != '\r') { text+='\n'; } } else { text+=(*c); } m_previousChar = *c; } else { unsigned int b=*c; snprintf(buf, 16, "\\0x%02x", b & 0xff); text+=buf; } } c++; } addOutput(text); } void QCPPDialogImpl::addOutput(const QString& text) { m_outputBuffer+=text; if (!m_outputTimer.isActive()) { doOutput(); m_outputTimerStart.restart(); m_outputTimer.setSingleShot(true); m_outputTimer.start(50); } else { if ((m_outputTimerStart.elapsed()>400) || ((m_outputTimerStart.elapsed()>200) && (m_outputBuffer.length()<100))) { doOutput(); m_outputTimerStart.restart(); } m_outputTimer.setSingleShot(true); m_outputTimer.start(50); } } void QCPPDialogImpl::doOutput() { if (m_outputBuffer.isEmpty()) { return; } m_outputView->append(m_outputBuffer); m_outputBuffer.clear(); } void QCPPDialogImpl::hexOutputClicked(bool /* on */) { addOutput("\n"); m_hexBytes=0; } void QCPPDialogImpl::clearOutput() { m_outputView->clear(); m_hexBytes=0; } void QCPPDialogImpl::enableLogging(bool on) { if (m_logFile.isOpen()==on) { return; } if (on) { m_logFile.setFileName(m_logFileLe->text()); QIODevice::OpenMode mode=QIODevice::ReadWrite; if (m_logAppendCb->currentIndex()==0) { mode=mode | QIODevice::Truncate; } else { mode=mode | QIODevice::Append; } if (!m_logFile.open(mode)) { QMessageBox::information(this, tr("Opening file failed"), tr("Could not open file %1 for writing").arg(m_logFileLe->text())); m_enableLoggingCb->setChecked(false); } else { m_logAppendCb->setEnabled(false); m_logFileLe->setEnabled(false); m_logFileFileDialog->setEnabled(false); saveSettings(); } } else { m_logFile.close(); m_logAppendCb->setEnabled(true); m_logFileLe->setEnabled(true); m_logFileFileDialog->setEnabled(true); } } void QCPPDialogImpl::chooseLogFile() { QString logFile=QFileDialog::getSaveFileName(this, tr("Save log file ..."), m_logFileLe->text()); if (!logFile.isEmpty()) { m_logFileLe->setText(logFile); } }