//Author: Timothy Pearson , (C) 2012 //Copyright: See COPYING file that comes with this distribution // TDE MDI interface based on excellent 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_sa_menu = new KAction(i18n("Launch Spectrum Analyzer"), "remote", KShortcut(), TQT_TQOBJECT(this), TQT_SLOT(startSpectrumAnalyzer()), ac, "spectrum_analyzer"); // 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!")); // Create the list of the opened windows m_listBox = new KListBox(this); m_listBox->setCaption(i18n("Opened windows")); addToolWindow(m_listBox, KDockWidget::DockLeft, getMainDockWidget()); connect(m_listBox, SIGNAL(executed(TQListBoxItem *)), this, SLOT(listBoxExecuted(TQListBoxItem*))); connect(m_listBox, SIGNAL(rightButtonClicked(TQListBoxItem*, const TQPoint&)), this, SLOT(listBoxRightClicked(TQListBoxItem*))); 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) { return; } } connect_action->setEnabled(false); disconnect_action->setEnabled(false); // 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); if (m_rsvSvrSocket) { 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_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::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 the item to the window list m_window.append(view); m_listBox->insertItem(view->tabCaption()); // 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())); TQListBoxItem *item = m_listBox->findItem(current->tabCaption()); assert(item); m_listBox->setCurrentItem(item); } void RemoteMDI::closeCurrent() { // If there's a current view, close it if ( m_pCurrentWindow != 0 ) { // Notify the status bar of the removal of the window statusBar()->message(i18n("%1 removed").arg(m_pCurrentWindow->tabCaption())); // Remove from the window list m_window.remove(m_window.find(m_pCurrentWindow)); // Remove from the list box TQListBoxItem *item = m_listBox->findItem(m_pCurrentWindow->tabCaption()); assert( item ); delete item; // We could also call removeWindowFromMdi, but it doesn't delete the // pointer. This way, we're sure that the view will get deleted. closeWindow(m_pCurrentWindow); } // Synchronize combo box if (m_pCurrentWindow) { currentChanged(m_pCurrentWindow); } } void RemoteMDI::listBoxExecuted(TQListBoxItem *item) { // Get the current item's text TQString text = item->text(); // Active the corresponding tab for (TQValueList< KMdiChildView *>::iterator it = m_window.begin(); it != m_window.end(); ++it ) { // Get the view KMdiChildView *view = *it; assert(view); // Is the view we need to show? if (view->caption() == text) { view->activate(); break; } } } void RemoteMDI::listBoxRightClicked(TQListBoxItem *item) { // Get the current item's text TQString text = item->text(); // Bring up a menu for the corresponding window // RAJA FIXME for (TQValueList< KMdiChildView *>::iterator it = m_window.begin(); it != m_window.end(); ++it ) { // Get the view KMdiChildView *view = *it; assert(view); // Is the view we need to show? if (view->caption() == text) { view->activate(); break; } } } 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 from the window list m_window.remove(m_window.find(w)); // Remove from the list box TQListBoxItem *item = m_listBox->findItem( w->tabCaption() ); assert(item); delete item; // 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 for (TQValueList< KMdiChildView *>::iterator it = m_window.begin(); it != m_window.end(); ++it ) { RemoteLab::InstrumentView* iview = dynamic_cast(*it); if (iview) { iview->closeConnections(); } } // 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"