//Author: Timothy Pearson , (C) 2012 //Copyright: See COPYING file that comes with this distribution // TDE MDI interface based on a (passable) tutorial by Andrea Bergia et al. #include "remotemdi.h" #include using namespace std; #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "views/instrumentview.h" #include "dialogs/selectserverdlg.h" RemoteMDI::RemoteMDI() : KMdiMainFrm(0, "RemoteMDI", KMdi::ChildframeMode), m_children(0), m_rsvSvrSocket(NULL) { setXMLFile("remotelabui.rc"); // Create some actions KStdAction::close(this, SLOT(closeCurrent()), actionCollection()); KStdAction::quit(this, SLOT(close()), actionCollection()); KActionCollection *const ac = actionCollection(); setStandardToolBarMenuEnabled(true); KStdAction::quit(TQT_TQOBJECT(this), TQT_SLOT(close()), ac); KStdAction::configureToolbars(TQT_TQOBJECT(this), TQT_SLOT(configToolbars()), ac); KStdAction::keyBindings(TQT_TQOBJECT(this), TQT_SLOT(configKeys()), ac); connect_action = new KAction(i18n("Connect to Server"), "connect_creating", KShortcut(), TQT_TQOBJECT(this), TQT_SLOT(connectToServer()), ac, "connect_server"); disconnect_action = new KAction(i18n("Disconnect from Server"), "connect_no", KShortcut(), TQT_TQOBJECT(this), TQT_SLOT(disconnectFromServer()), ac, "disconnect_server"); inst_fpgaviewer_menu = new KAction(i18n("Launch Spectrum Analyzer"), "remote", KShortcut(), TQT_TQOBJECT(this), TQT_SLOT(startSpectrumAnalyzer()), ac, "spectrum_analyzer"); inst_sa_menu = new KAction(i18n("Launch FPGA Viewer"), "remote", KShortcut(), TQT_TQOBJECT(this), TQT_SLOT(startFPGAViewer()), ac, "fpga_viewer"); // Add Window menu if ( !isFakingSDIApplication() ) { menuBar()->insertItem(i18n("&Window"), windowMenu()); } createGUI( 0 ); // When we change view, change the status bar text connect(this, SIGNAL(viewActivated(KMdiChildView*)), this, SLOT(currentChanged(KMdiChildView*))); ac->setHighlightingEnabled(true); connect(ac, TQT_SIGNAL(actionStatusText(const TQString&)), statusBar(), TQT_SLOT(message(const TQString&) )); connect(ac, TQT_SIGNAL(clearStatusText()), statusBar(), TQT_SLOT(clear())); // Create the status bar statusBar()->message(i18n("No view!")); processLockouts(); } RemoteMDI::~RemoteMDI() { while (m_pCurrentWindow) { closeCurrent(); } if (m_rsvSvrSocket) { m_rsvSvrSocket->close(); while (m_rsvSvrSocket->state() == TQSocket::Closing) { tqApp->processEvents(); } } } void RemoteMDI::connectToServer() { if (m_rsvSvrSocket) { if (m_rsvSvrSocket->state() != TQSocket::Idle) { printf("[DEBUG] Not connecting because the socket is still in state %d\n\r", m_rsvSvrSocket->state()); fflush(stdout); return; } } connect_action->setEnabled(false); disconnect_action->setEnabled(true); // Connect to the central reservation/control server if (!m_rsvSvrSocket) { m_rsvSvrSocket = new TDEKerberosClientSocket(this); connect(m_rsvSvrSocket, SIGNAL(connectionClosed()), this, SLOT(connectionClosedHandler())); } m_rsvSvrSocket->setServiceName("remotefpga"); if (m_serverHost != "") { m_rsvSvrSocket->setServerFQDN(m_serverHost); m_rsvSvrSocket->connectToHost(m_serverHost, 4004); while ((m_rsvSvrSocket->state() == TQSocket::Connecting) || (m_rsvSvrSocket->state() == TQSocket::HostLookup)) { tqApp->processEvents(); } if (m_rsvSvrSocket->state() == TQSocket::Connected) { printf("[DEBUG] Initial connection established...\n\r"); fflush(stdout); if (m_rsvSvrSocket->setUsingKerberos(true) != 0) { disconnectFromServer(); KMessageBox::error(this, i18n("Unable to establish Kerberos protocol with remote server

Please verify that you currently hold a valid Kerberos ticket"), i18n("Connection Failed")); } else { // Connection established! // Read magic number and proto version from server TQDataStream* ds = new TQDataStream(m_rsvSvrSocket); TQ_UINT32 magicnum; TQ_UINT32 protover; *ds >> magicnum; *ds >> protover; printf("[DEBUG] Got magic number %d and protocol version %d\n\r", magicnum, protover); fflush(stdout); delete ds; if ((magicnum == MAGIC_NUMBER) && (protover == PROTOCOL_VERSION)) { disconnect_action->setEnabled(true); promptForStationType(); } else { disconnectFromServer(); KMessageBox::error(this, i18n("The remote server is not compatible with this client"), i18n("Connection Failed")); } } } else { disconnectFromServer(); KMessageBox::error(this, i18n("Unable to establish connection to remote server"), i18n("Connection Failed")); } } else { disconnectFromServer(); KMessageBox::error(this, i18n("The address of the remote server has not been specified"), i18n("Connection Failed")); } processLockouts(); } void RemoteMDI::promptForStationType() { if (!m_rsvSvrSocket) { return; } if (m_rsvSvrSocket->state() != TQSocket::Connected) { return; } TQDataStream ds(m_rsvSvrSocket); // Request list of laboratory stations StationList slist; ds << TQString("LIST"); ds >> slist; printf("[RAJA DEBUG 200.2] Got list of stations, count is %d\n\r", slist.count()); fflush(stdout); SelectServerDialog select(this, 0, slist); const int ret = select.exec(); if (ret == KDialog::Accepted) { TQString result; ds << TQString("BIND"); ds << select.m_selectedStation; ds >> result; printf("[RAJA DEBUG 100.0] '%s'\n\r", result.ascii()); fflush(stdout); if (result == "OK") { // Success, do nothing } else if (result == "ERRUNAVAL") { KMessageBox::error(this, i18n("No stations of the specified type are currently available

Please try again later"), i18n("Insufficient Laboratory Resources")); disconnectFromServer(); } else { KMessageBox::error(this, i18n("Unknown server error

Please reconnect and try again"), i18n("Internal Error")); disconnectFromServer(); } } else { disconnectFromServer(); } } void RemoteMDI::disconnectFromServer() { connect_action->setEnabled(false); disconnect_action->setEnabled(false); // Close all windows KMdiIterator *it = createIterator(); while (it->currentItem()) { KMdiChildView *c = dynamic_cast(it->currentItem()); if (c) { closeSpecifiedWindow(c); } it->next(); } deleteIterator(it); if (m_rsvSvrSocket) { m_rsvSvrSocket->clearPendingData(); m_rsvSvrSocket->close(); while (m_rsvSvrSocket->state() == TQSocket::Closing) { tqApp->processEvents(); } } connect_action->setEnabled(true); processLockouts(); } void RemoteMDI::connectionClosedHandler() { disconnectFromServer(); KMessageBox::error(this, i18n("The remote server has closed the connection"), i18n("Connection Terminated")); } void RemoteMDI::processLockouts() { bool connected = false; if (m_rsvSvrSocket) { connected = (m_rsvSvrSocket->state() == TQSocket::Connected); } printf("[RAJA DEBUG 600.0] connected: %d\n\r", connected); fflush(stdout); connect_action->setEnabled(!connected); disconnect_action->setEnabled(connected); inst_fpgaviewer_menu->setEnabled(connected); inst_sa_menu->setEnabled(connected); } void RemoteMDI::configToolbars() { KEditToolbar dialog(factory(), this); dialog.showButtonApply(false); if (dialog.exec()) { applyMainWindowSettings(kapp->config(), "window"); } } void RemoteMDI::configKeys() { KKeyDialog::configure(actionCollection(), this); } void RemoteMDI::setServerHost(TQString server) { m_serverHost = server; } void RemoteMDI::startSpectrumAnalyzer() { RemoteLab::InstrumentView* saview = new RemoteLab::InstrumentView("libremotelab_commanalyzer", i18n("Communications Analyzer"), (mdiMode() == KMdi::ToplevelMode) ? 0 : this); openNewWindow(saview); if (m_serverHost != "") { saview->connectServer(m_serverHost); } } void RemoteMDI::startFPGAViewer() { RemoteLab::InstrumentView* fpgaview = new RemoteLab::InstrumentView("libremotelab_fpgaviewer", i18n("FPGA Viewer"), (mdiMode() == KMdi::ToplevelMode) ? 0 : this); openNewWindow(fpgaview); if (m_serverHost != "") { fpgaview->connectServer(m_serverHost); } } void RemoteMDI::openNewWindow(KMdiChildView *view) { // Add a child view m_children++; // The child view will be our child only if we aren't in Toplevel mode if (!view) { view = new KMdiChildView(i18n("View %1").arg(m_children), (mdiMode() == KMdi::ToplevelMode) ? 0 : this); } (new TQHBoxLayout(view))->setAutoAdd( true ); // Add to the MDI and set as current if (mdiMode() == KMdi::ToplevelMode) { addWindow(view, KMdi::Detach); } else { addWindow(view); } currentChanged(view); // Handle termination connect(view, SIGNAL(childWindowCloseRequest(KMdiChildView*)), this, SLOT(childClosed(KMdiChildView*))); } void RemoteMDI::childWindowCloseRequest(KMdiChildView *pWnd) { RemoteLab::InstrumentView* iview = dynamic_cast(pWnd); if (iview) { // Give the child a chance to finish what it was doing and exit cleanly (i.e. without crashing!) iview->closeConnections(); iview->hide(); KMdiMainFrm::childWindowCloseRequest(pWnd); } } void RemoteMDI::currentChanged(KMdiChildView *current) { // Update status bar and list box statusBar()->message(i18n( "%1 activated").arg(current->tabCaption())); } void RemoteMDI::closeCurrent() { // If there's a current view, close it if (m_pCurrentWindow) { closeSpecifiedWindow(m_pCurrentWindow); } } void RemoteMDI::closeSpecifiedWindow(KMdiChildView *window) { if (window) { // Notify the status bar of the removal of the window statusBar()->message(i18n("%1 removed").arg(window->tabCaption())); // We could also call removeWindowFromMdi, but it doesn't delete the // pointer. This way, we're sure that the view will get deleted. closeWindow(window); // Synchronize combo box if (m_pCurrentWindow) { currentChanged(m_pCurrentWindow); } } } void RemoteMDI::childClosed(KMdiChildView * w) { assert(w); // Set as active w->activate(); assert(w == m_pCurrentWindow); // Notify the status bar of the removal of the window statusBar()->message(i18n("%1 removed").arg(w->tabCaption())); // Remove the view from MDI, BUT DO NOT DELETE IT! It is automatically deleted by TQt since it was closed. removeWindowFromMdi(w); } bool RemoteMDI::queryClose() { // Close all open connections KMdiIterator *it = createIterator(); while (it->currentItem()) { KMdiChildView *c = dynamic_cast(it->currentItem()); if (c) { RemoteLab::InstrumentView* iview = dynamic_cast(c); if (iview) { iview->closeConnections(); } } it->next(); } deleteIterator(it); // Save current MDI settings (window positions, etc.) KConfig *c = kapp->config(); // RAJA FIXME c->sync(); // Allow this window to close return true; } #include "remotemdi.moc"