You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
357 lines
9.8 KiB
357 lines
9.8 KiB
//Author: Timothy Pearson <kb9vqf@pearsoncomputing.net>, (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 <cassert>
|
|
using namespace std;
|
|
|
|
#include <kapplication.h>
|
|
#include <klocale.h>
|
|
#include <kdebug.h>
|
|
#include <kconfig.h>
|
|
|
|
#include <tqlabel.h>
|
|
#include <tqtimer.h>
|
|
#include <tqlayout.h>
|
|
#include <kiconloader.h>
|
|
#include <kstdaction.h>
|
|
#include <kstatusbar.h>
|
|
#include <kmdichildview.h>
|
|
#include <klistbox.h>
|
|
#include <kactionclasses.h>
|
|
#include <kedittoolbar.h>
|
|
#include <kkeydialog.h>
|
|
|
|
#include "views/instrumentview.h"
|
|
|
|
RemoteMDI::RemoteMDI()
|
|
: KMdiMainFrm(0, "RemoteMDI", KMdi::ChildframeMode), m_children(NULL), 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"), "remote", NULL, TQT_TQOBJECT(this), TQT_SLOT(connectToServer()), ac, "connect_server");
|
|
disconnect_action = new KAction(i18n("Disconnect from Server"), "remote", NULL, TQT_TQOBJECT(this), TQT_SLOT(disconnectFromServer()), ac, "disconnect_server");
|
|
inst_sa_menu = new KAction(i18n("Launch Spectrum Analyzer"), "remote", NULL, 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();
|
|
}
|
|
delete m_rsvSvrSocket;
|
|
}
|
|
}
|
|
|
|
void RemoteMDI::connectToServer() {
|
|
if (m_rsvSvrSocket) {
|
|
return;
|
|
}
|
|
|
|
connect_action->setEnabled(false);
|
|
disconnect_action->setEnabled(false);
|
|
|
|
// Connect to the central reservation/control server
|
|
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();
|
|
}
|
|
else {
|
|
// Connection established!
|
|
disconnect_action->setEnabled(true);
|
|
|
|
// Read the next line from the server
|
|
TQString str = m_rsvSvrSocket->readLine();
|
|
printf("[RAJA DEBUG 200.0] Got %s\n\r", str.ascii()); fflush(stdout);
|
|
}
|
|
}
|
|
else {
|
|
printf("[ERROR] Initial connection failed (state %d)\n\r", m_rsvSvrSocket->state()); fflush(stdout);
|
|
disconnectFromServer();
|
|
}
|
|
}
|
|
|
|
processLockouts();
|
|
}
|
|
|
|
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();
|
|
}
|
|
delete m_rsvSvrSocket;
|
|
m_rsvSvrSocket = 0;
|
|
}
|
|
|
|
connect_action->setEnabled(true);
|
|
processLockouts();
|
|
}
|
|
|
|
void RemoteMDI::connectionClosedHandler() {
|
|
disconnectFromServer();
|
|
}
|
|
|
|
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);
|
|
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<RemoteLab::InstrumentView*>(pWnd);
|
|
if (iview) {
|
|
iview->closeConnections();
|
|
iview->hide();
|
|
// Give the child a chance to finish what it was doing
|
|
// FIXME HACK
|
|
// There is no nice way to shut down the instrument parts it seems...
|
|
// Debug why they crash when this delay is set to zero!
|
|
m_closelist.append(pWnd);
|
|
TQTimer::singleShot(100, this, SLOT(processCloseList()));
|
|
}
|
|
}
|
|
|
|
void RemoteMDI::processCloseList() {
|
|
if (m_closelist.begin() != m_closelist.end()) {
|
|
KMdiMainFrm::childWindowCloseRequest(*m_closelist.begin());
|
|
}
|
|
}
|
|
|
|
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<RemoteLab::InstrumentView*>(*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"
|
|
|