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.
703 lines
21 KiB
703 lines
21 KiB
//Author: Timothy Pearson <kb9vqf@pearsoncomputing.net>, (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 <cassert>
|
|
using namespace std;
|
|
|
|
#include <pwd.h>
|
|
|
|
#include <tdeapplication.h>
|
|
#include <tdelocale.h>
|
|
#include <kdebug.h>
|
|
#include <tdeconfig.h>
|
|
#include <tdemessagebox.h>
|
|
|
|
#include <tqlabel.h>
|
|
#include <tqtimer.h>
|
|
#include <tqlayout.h>
|
|
#include <kiconloader.h>
|
|
#include <kstdaction.h>
|
|
#include <kstatusbar.h>
|
|
#include <tdemdichildview.h>
|
|
#include <tdelistbox.h>
|
|
#include <tdeactionclasses.h>
|
|
#include <kedittoolbar.h>
|
|
#include <kkeydialog.h>
|
|
#include <libtdeldap.h>
|
|
|
|
#include "views/instrumentview.h"
|
|
#include "dialogs/selectserverdlg.h"
|
|
|
|
#define STATUSBAR_TIMEOUT_ID 5
|
|
|
|
RemoteMDI::RemoteMDI()
|
|
: KMdiMainFrm(0, "RemoteMDI", KMdi::ChildframeMode), m_children(0), m_rsvSvrSocket(NULL), connToServerConnecting(false), connToServerState(-1), connToServerTimeoutTimer(NULL)
|
|
{
|
|
setXMLFile("remotelabui.rc");
|
|
setIcon(SmallIcon("remote_laboratory_client"));
|
|
|
|
masterPollTimer = new TQTimer();
|
|
connect(masterPollTimer, SIGNAL(timeout()), this, SLOT(masterPoll()));
|
|
|
|
// Create some actions
|
|
KStdAction::close(this, SLOT(closeCurrent()), actionCollection());
|
|
KStdAction::quit(this, SLOT(close()), actionCollection());
|
|
|
|
TDEActionCollection *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 TDEAction(i18n("Connect to Server"), "connect_creating", TDEShortcut(), TQT_TQOBJECT(this), TQT_SLOT(connectToServer()), ac, "connect_server");
|
|
disconnect_action = new TDEAction(i18n("Disconnect from Server"), "connect_no", TDEShortcut(), TQT_TQOBJECT(this), TQT_SLOT(disconnectFromServer()), ac, "disconnect_server");
|
|
|
|
setMenuForSDIModeSysButtons(menuBar());
|
|
|
|
createGUI(0);
|
|
|
|
// Add Window menu
|
|
if ( !isFakingSDIApplication() ) {
|
|
menuBar()->insertItem(i18n("&Window"), windowMenu(), -1, 4);
|
|
}
|
|
// Hide task bar as no windows are currently active
|
|
hideViewTaskBar();
|
|
|
|
// 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&)), this, TQT_SLOT(updateStatusBarMainMessage(const TQString&) ));
|
|
connect(ac, TQT_SIGNAL(clearStatusText()), statusBar(), TQT_SLOT(clear()));
|
|
|
|
// Create the status bar
|
|
updateStatusBarMainMessage(i18n("No active instruments"));
|
|
KStatusBar* sb = statusBar();
|
|
if (sb) {
|
|
sb->insertItem(i18n("Unknown Time Remaining"), STATUSBAR_TIMEOUT_ID, 0, true);
|
|
}
|
|
|
|
processActions();
|
|
|
|
processLockouts();
|
|
|
|
showMaximized();
|
|
}
|
|
|
|
RemoteMDI::~RemoteMDI()
|
|
{
|
|
if (masterPollTimer) {
|
|
masterPollTimer->stop();
|
|
delete masterPollTimer;
|
|
}
|
|
|
|
while (m_pCurrentWindow) {
|
|
closeCurrent();
|
|
}
|
|
|
|
if (m_rsvSvrSocket) {
|
|
m_rsvSvrSocket->clearPendingData();
|
|
m_rsvSvrSocket->close();
|
|
delete m_rsvSvrSocket;
|
|
m_rsvSvrSocket = NULL;
|
|
}
|
|
}
|
|
|
|
void RemoteMDI::updateStatusBarMessage() {
|
|
TQString windowStatusBarMessage;
|
|
if (m_pCurrentWindow) {
|
|
windowStatusBarMessage = m_windowStatusBarMapping[TQT_TQOBJECT(m_pCurrentWindow)];
|
|
}
|
|
|
|
KStatusBar* sb = statusBar();
|
|
if (sb) {
|
|
sb->message(m_mainStatusBarMessage + ((windowStatusBarMessage != "")?" [" + i18n("Instrument") + ": " + windowStatusBarMessage + "]":""));
|
|
}
|
|
}
|
|
|
|
void RemoteMDI::updateStatusBarMainMessage(const TQString& message) {
|
|
m_mainStatusBarMessage = message;
|
|
updateStatusBarMessage();
|
|
}
|
|
|
|
void RemoteMDI::updateStatusBarWindowMessage(const TQString& message, const TQObject* window) {
|
|
const TQObject* windowObject = window;
|
|
if (!windowObject) {
|
|
windowObject = sender();
|
|
}
|
|
|
|
if (windowObject) {
|
|
m_windowStatusBarMapping[windowObject] = message;
|
|
}
|
|
|
|
updateStatusBarMessage();
|
|
}
|
|
|
|
void RemoteMDI::resizeEvent(TQResizeEvent *e) {
|
|
KMdiMainFrm::resizeEvent(e);
|
|
setSysButtonsAtMenuPosition();
|
|
}
|
|
|
|
void RemoteMDI::processActions() {
|
|
// Add dynamic actions
|
|
TDEActionCollection *const ac = actionCollection();
|
|
|
|
TDEAction* action;
|
|
ServiceType st;
|
|
for (ServiceList::Iterator it(m_activeStation.services.begin()); it != m_activeStation.services.end(); ++it) {
|
|
st = *it;
|
|
action = new TDEAction(i18n("Launch")+" "+st.name, st.clientLibrary, TDEShortcut(), TQT_TQOBJECT(this), TQT_SLOT(startModule()), ac, st.clientLibrary.ascii());
|
|
m_instrumentActionList.append(action);
|
|
}
|
|
plugActionList("instrumentMenu_actionlist", m_instrumentActionList);
|
|
plugActionList("instrumentToolBar_actionlist", m_instrumentActionList);
|
|
}
|
|
|
|
void RemoteMDI::startModule() {
|
|
const TDEAction* sendingAction = dynamic_cast<const TDEAction*>(sender());
|
|
if (sendingAction) {
|
|
bool serviceFound = false;
|
|
ServiceType st;
|
|
for (ServiceList::Iterator it(m_activeStation.services.begin()); it != m_activeStation.services.end(); ++it) {
|
|
st = *it;
|
|
if (st.clientLibrary == sendingAction->name()) {
|
|
serviceFound = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!serviceFound) {
|
|
KMessageBox::error(this, i18n("<qt>The active laboratory workspace does not support the requested service</qt>"), i18n("Service Unavailable"));
|
|
return;
|
|
}
|
|
|
|
RemoteLab::InstrumentView* view = new RemoteLab::InstrumentView(st.clientLibrary, st.name, (mdiMode() == KMdi::ToplevelMode) ? 0 : this);
|
|
view->setName(st.clientLibrary.ascii());
|
|
connect(view, SIGNAL(statusMessageSet(const TQString&)), this, SLOT(updateStatusBarWindowMessage(const TQString&)));
|
|
if (st.singleInstance) {
|
|
const_cast<TDEAction*>(sendingAction)->setEnabled(false);
|
|
}
|
|
openNewWindow(view);
|
|
showViewTaskBar();
|
|
if (m_serverHost != "") {
|
|
view->connectServer(m_serverHost);
|
|
}
|
|
}
|
|
}
|
|
|
|
int RemoteMDI::getNewTicket() {
|
|
int ret = -1;
|
|
|
|
LDAPCredentials credentials;
|
|
KerberosTicketInfoList ticketList = LDAPManager::getKerberosTicketList();
|
|
if (ticketList.count() > 0) {
|
|
TQStringList princParts = TQStringList::split("@", ticketList[0].cachePrincipal);
|
|
credentials.username = princParts[0];
|
|
credentials.realm = princParts[1];
|
|
}
|
|
else {
|
|
struct passwd* pwd = getpwuid(geteuid());
|
|
if (pwd) {
|
|
credentials.username = TQString(pwd->pw_name);
|
|
}
|
|
}
|
|
int result = LDAPManager::getKerberosPassword(credentials, i18n("Please provide Kerberos credentials"), false, this);
|
|
if (result == KDialog::Accepted) {
|
|
TQString errorstring;
|
|
TQString service;
|
|
if (LDAPManager::obtainKerberosTicket(credentials, service, &errorstring) != 0) {
|
|
KMessageBox::error(this, i18n("<qt>Failed to obtain ticket<p>%1</qt>").arg(errorstring), i18n("Failed to obtain Kerberos ticket"));
|
|
}
|
|
else {
|
|
ret = 0;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void RemoteMDI::finishConnectingToServer() {
|
|
if (!m_rsvSvrSocket) {
|
|
connToServerState = -1;
|
|
connToServerConnecting = false;
|
|
processLockouts();
|
|
return;
|
|
}
|
|
|
|
if (connToServerConnecting) {
|
|
switch(connToServerState) {
|
|
case 0:
|
|
if (!connToServerTimeoutTimer) {
|
|
connToServerTimeoutTimer = new TQTimer;
|
|
connToServerTimeoutTimer->start(5000, TRUE);
|
|
}
|
|
if ((m_rsvSvrSocket->state() == TQSocket::Connecting) || (m_rsvSvrSocket->state() == TQSocket::HostLookup)) {
|
|
if (!connToServerTimeoutTimer->isActive()) {
|
|
connToServerState = -3;
|
|
connToServerConnecting = false;
|
|
disconnectFromServer();
|
|
KMessageBox::error(this, i18n("<qt>Unable to establish connection to remote server</qt>"), i18n("Connection Failed"));
|
|
return;
|
|
}
|
|
}
|
|
else {
|
|
if (m_rsvSvrSocket->state() == TQSocket::Connected) {
|
|
printf("[DEBUG] Initial connection established...\n\r"); fflush(stdout);
|
|
m_rsvSvrSocket->setDataTimeout(5000);
|
|
m_rsvSvrSocket->setUsingKerberos(true);
|
|
delete connToServerTimeoutTimer;
|
|
connToServerTimeoutTimer= NULL;
|
|
connToServerState = 1;
|
|
}
|
|
else {
|
|
connToServerState = -1;
|
|
connToServerConnecting = false;
|
|
disconnectFromServer();
|
|
KMessageBox::error(this, i18n("<qt>Unable to establish connection to remote server</qt>"), i18n("Connection Failed"));
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
case 1:
|
|
if (m_rsvSvrSocket->kerberosStatus() == TDEKerberosClientSocket::KerberosInitializing) {
|
|
// Do nothing
|
|
}
|
|
else {
|
|
if (m_rsvSvrSocket->kerberosStatus() != TDEKerberosClientSocket::KerberosInUse) {
|
|
connToServerState = -1;
|
|
connToServerConnecting = false;
|
|
disconnectFromServer();
|
|
|
|
// Try to get a valid ticket
|
|
if (getNewTicket() == 0) {
|
|
// Retry connection if no obvious errors were detected
|
|
TQTimer::singleShot(0, this, SLOT(connectToServer()));
|
|
return;
|
|
}
|
|
else {
|
|
KMessageBox::error(this, i18n("<qt>Unable to establish Kerberos protocol with remote server<p>Please verify that you currently hold a valid Kerberos ticket</qt>"), i18n("Connection Failed"));
|
|
return;
|
|
}
|
|
}
|
|
else {
|
|
connect(m_rsvSvrSocket, SIGNAL(readyRead()), m_rsvSvrSocket, SLOT(processPendingData()));
|
|
m_rsvSvrSocket->processPendingData();
|
|
connToServerState = 2;
|
|
}
|
|
}
|
|
break;
|
|
case 2:
|
|
// Connection established!
|
|
// Read magic number and proto version from server
|
|
TQDataStream* ds = new TQDataStream(m_rsvSvrSocket);
|
|
ds->setPrintableData(true);
|
|
while (!m_rsvSvrSocket->canReadFrame()) {
|
|
tqApp->processEvents();
|
|
if (!m_rsvSvrSocket) {
|
|
return;
|
|
}
|
|
}
|
|
TQ_UINT32 magicnum;
|
|
TQ_UINT32 protover;
|
|
*ds >> magicnum;
|
|
*ds >> protover;
|
|
m_rsvSvrSocket->clearFrameTail();
|
|
printf("[DEBUG] Got magic number %d and protocol version %d\n\r", magicnum, protover); fflush(stdout);
|
|
if ((magicnum == MAGIC_NUMBER) && (protover == PROTOCOL_VERSION)) {
|
|
// Request server name
|
|
TQString serverName;
|
|
*ds << TQString("NAME");
|
|
m_rsvSvrSocket->writeEndOfFrame();
|
|
while (!m_rsvSvrSocket->canReadFrame()) {
|
|
tqApp->processEvents();
|
|
if (!m_rsvSvrSocket) {
|
|
return;
|
|
}
|
|
}
|
|
*ds >> serverName;
|
|
m_rsvSvrSocket->clearFrameTail();
|
|
|
|
// Set caption if a valid server name was received
|
|
if ((serverName != "") && (serverName != "ERRINVCMD")) {
|
|
setCaption(TQString("%1 - %2").arg(serverName).arg(kapp->caption()));
|
|
}
|
|
|
|
delete ds;
|
|
disconnect_action->setEnabled(true);
|
|
promptForStationType();
|
|
}
|
|
else {
|
|
delete ds;
|
|
disconnectFromServer();
|
|
KMessageBox::error(this, i18n("<qt>The remote server is not compatible with this client</qt>"), i18n("Connection Failed"));
|
|
}
|
|
connToServerState = 3;
|
|
connToServerConnecting = false;
|
|
masterPollTimer->start(0, TRUE);
|
|
processLockouts();
|
|
break;
|
|
}
|
|
|
|
TQTimer::singleShot(0, this, SLOT(finishConnectingToServer()));
|
|
}
|
|
}
|
|
|
|
void RemoteMDI::masterPoll() {
|
|
// Query current termination timestamp
|
|
if (m_rsvSvrSocket) {
|
|
if ((m_rsvSvrSocket->state() == TQSocket::Connected) && (!connToServerConnecting)) {
|
|
TQDataStream ds(m_rsvSvrSocket);
|
|
ds.setPrintableData(true);
|
|
TQ_ULLONG terminationStamp;
|
|
long long currentStamp;
|
|
ds << TQString("TSTP");
|
|
m_rsvSvrSocket->writeEndOfFrame();
|
|
while (!m_rsvSvrSocket->canReadFrame()) {
|
|
tqApp->processEvents();
|
|
if (!m_rsvSvrSocket) {
|
|
masterPollTimer->start(1000, TRUE);
|
|
return;
|
|
}
|
|
}
|
|
ds >> terminationStamp;
|
|
m_rsvSvrSocket->clearFrameTail();
|
|
currentStamp = TQDateTime::currentDateTime().toTime_t();
|
|
|
|
KStatusBar* sb = statusBar();
|
|
if (sb) {
|
|
if (terminationStamp == 0) {
|
|
sb->changeItem(i18n("Unlimited Time Remaining"), STATUSBAR_TIMEOUT_ID);
|
|
}
|
|
else {
|
|
long long difference = terminationStamp - currentStamp;
|
|
int seconds = 0;
|
|
int minutes = 0;
|
|
int hours = 0;
|
|
int days = 0;
|
|
if (difference >= 0) {
|
|
days = (difference / 86400);
|
|
difference = difference - (days * 86400);
|
|
hours = (difference / 3600);
|
|
difference = difference - (hours * 3600);
|
|
minutes = (difference / 60);
|
|
difference = difference - (minutes * 60);
|
|
seconds = difference;
|
|
}
|
|
TQString differenceString;
|
|
if (days > 0) {
|
|
differenceString.append(i18n("%1 day(s), ").arg(days));
|
|
}
|
|
if ((days > 0) || (hours > 0)) {
|
|
differenceString.append(i18n("%1 hours(s), ").arg(hours));
|
|
}
|
|
if ((days > 0) || (hours > 0) || (minutes > 0)) {
|
|
differenceString.append(i18n("%1 minutes(s), ").arg(minutes));
|
|
}
|
|
differenceString.append(i18n("%1 seconds(s)").arg(seconds));
|
|
sb->changeItem(i18n("%1 Remaining").arg(differenceString), STATUSBAR_TIMEOUT_ID);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
masterPollTimer->start(1000, TRUE);
|
|
}
|
|
|
|
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()));
|
|
connect(m_rsvSvrSocket, TQT_SIGNAL(statusMessageUpdated(const TQString&)), this, TQT_SLOT(updateStatusBarMainMessage(const TQString&) ));
|
|
}
|
|
m_rsvSvrSocket->setServiceName("ulab");
|
|
TQStringList disallowedMechList;
|
|
disallowedMechList.append("GSS-SPNEGO");
|
|
m_rsvSvrSocket->setDisallowedMechanisms(disallowedMechList);
|
|
if (m_serverHost != "") {
|
|
m_rsvSvrSocket->setServerFQDN(m_serverHost);
|
|
m_rsvSvrSocket->connectToHost(m_serverHost, 4004);
|
|
|
|
// Finish connecting when appropriate
|
|
connToServerState = 0;
|
|
connToServerConnecting = true;
|
|
TQTimer::singleShot(0, this, SLOT(finishConnectingToServer()));
|
|
}
|
|
}
|
|
|
|
void RemoteMDI::promptForStationType() {
|
|
if (!m_rsvSvrSocket) {
|
|
return;
|
|
}
|
|
if (m_rsvSvrSocket->state() != TQSocket::Connected) {
|
|
return;
|
|
}
|
|
|
|
TQDataStream ds(m_rsvSvrSocket);
|
|
ds.setPrintableData(true);
|
|
|
|
// Request list of laboratory stations
|
|
StationList slist;
|
|
ds << TQString("LIST");
|
|
m_rsvSvrSocket->writeEndOfFrame();
|
|
while (!m_rsvSvrSocket->canReadFrame()) {
|
|
tqApp->processEvents();
|
|
if (!m_rsvSvrSocket) {
|
|
return;
|
|
}
|
|
}
|
|
ds >> slist;
|
|
m_rsvSvrSocket->clearFrameTail();
|
|
|
|
SelectServerDialog select(this, 0, slist);
|
|
const int ret = select.exec();
|
|
if (ret == KDialog::Accepted) {
|
|
TQString result;
|
|
ds << TQString("BIND");
|
|
m_rsvSvrSocket->writeEndOfFrame();
|
|
ds << select.m_selectedStation;
|
|
m_rsvSvrSocket->writeEndOfFrame();
|
|
while (!m_rsvSvrSocket->canReadFrame()) {
|
|
tqApp->processEvents();
|
|
if (!m_rsvSvrSocket) {
|
|
return;
|
|
}
|
|
}
|
|
ds >> result;
|
|
m_rsvSvrSocket->clearFrameTail();
|
|
if (result == "OK") {
|
|
// Success!
|
|
m_activeStation = select.m_selectedStation;
|
|
processActions();
|
|
}
|
|
else if (result == "ERRUNAVAL") {
|
|
KMessageBox::error(this, i18n("<qt>No stations of the specified type are currently available<p>Please try again later</qt>"), i18n("Insufficient Laboratory Resources"));
|
|
disconnectFromServer();
|
|
}
|
|
else if (result == "ERRPREVCN") {
|
|
KMessageBox::error(this, i18n("<qt>You are already connected to a laboratory station<p>Please disconnect and try again</qt>"), i18n("Multiple Connections Detected"));
|
|
disconnectFromServer();
|
|
}
|
|
else {
|
|
KMessageBox::error(this, i18n("<qt>Unknown server error<p>Please reconnect and try again</qt>"), i18n("Internal Error"));
|
|
disconnectFromServer();
|
|
}
|
|
}
|
|
else {
|
|
disconnectFromServer();
|
|
}
|
|
}
|
|
|
|
void RemoteMDI::disconnectFromServer() {
|
|
connect_action->setEnabled(false);
|
|
disconnect_action->setEnabled(false);
|
|
|
|
m_instrumentActionList.clear();
|
|
unplugActionList("instrumentMenu_actionlist");
|
|
unplugActionList("instrumentToolBar_actionlist");
|
|
|
|
// Close all windows
|
|
closeAllViews();
|
|
|
|
if (m_rsvSvrSocket) {
|
|
m_rsvSvrSocket->clearPendingData();
|
|
m_rsvSvrSocket->close();
|
|
delete m_rsvSvrSocket;
|
|
m_rsvSvrSocket = NULL;
|
|
}
|
|
|
|
connect_action->setEnabled(true);
|
|
processLockouts();
|
|
}
|
|
|
|
void RemoteMDI::connectionClosedHandler() {
|
|
disconnectFromServer();
|
|
KMessageBox::error(this, i18n("<qt>The remote server has closed the connection</qt>"), i18n("Connection Terminated"));
|
|
}
|
|
|
|
void RemoteMDI::processLockouts() {
|
|
bool connected = false;
|
|
if (m_rsvSvrSocket) {
|
|
connected = ((m_rsvSvrSocket->state() == TQSocket::Connected) && (connToServerConnecting == false) && (connToServerState > 0));
|
|
}
|
|
|
|
connect_action->setEnabled(!connected);
|
|
disconnect_action->setEnabled(connected);
|
|
|
|
for (TQPtrList<TDEAction>::Iterator it(m_instrumentActionList.begin()); it != m_instrumentActionList.end(); ++it) {
|
|
(*it)->setEnabled(connected);
|
|
}
|
|
|
|
if (!connected) {
|
|
KStatusBar* sb = statusBar();
|
|
if (sb) {
|
|
sb->changeItem(i18n("Unknown Time Remaining"), STATUSBAR_TIMEOUT_ID);
|
|
}
|
|
}
|
|
}
|
|
|
|
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;
|
|
connectToServer();
|
|
}
|
|
|
|
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<RemoteLab::InstrumentView*>(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) {
|
|
RemoteLab::InstrumentView* view = dynamic_cast<RemoteLab::InstrumentView*>(current);
|
|
|
|
// Plug/unplug menus
|
|
if (view) {
|
|
unplugActionList("selectedInstrument_actionlist");
|
|
plugActionList("selectedInstrument_actionlist", view->menuActionList());
|
|
}
|
|
|
|
// Update status bar and list box
|
|
updateStatusBarMainMessage(i18n("Instrument %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
|
|
updateStatusBarWindowMessage(TQString::null, TQT_TQOBJECT(window));
|
|
updateStatusBarMainMessage(i18n("Instrument %1 removed").arg(window->tabCaption()));
|
|
|
|
// Unplug menus
|
|
unplugActionList("selectedInstrument_actionlist");
|
|
|
|
// 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);
|
|
|
|
// Unplug menus
|
|
unplugActionList("selectedInstrument_actionlist");
|
|
|
|
// Notify the status bar of the removal of the window
|
|
updateStatusBarWindowMessage(TQString::null, TQT_TQOBJECT(w));
|
|
updateStatusBarMainMessage(i18n("Instrument %1 removed").arg(w->tabCaption()));
|
|
|
|
// Re-enable associated action
|
|
RemoteLab::InstrumentView* view = dynamic_cast<RemoteLab::InstrumentView*>(w);
|
|
if (view) {
|
|
TQString libraryName = view->name();
|
|
for (TQPtrList<TDEAction>::Iterator it(m_instrumentActionList.begin()); it != m_instrumentActionList.end(); ++it) {
|
|
if ((*it)->name() == libraryName) {
|
|
(*it)->setEnabled(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Remove status bar text
|
|
m_windowStatusBarMapping.remove(TQT_TQOBJECT(w));
|
|
|
|
// 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<KMdiChildView*> *it = createIterator();
|
|
while (it->currentItem()) {
|
|
KMdiChildView *c = dynamic_cast<KMdiChildView*>(it->currentItem());
|
|
if (c) {
|
|
RemoteLab::InstrumentView* iview = dynamic_cast<RemoteLab::InstrumentView*>(c);
|
|
if (iview) {
|
|
iview->closeConnections();
|
|
}
|
|
}
|
|
it->next();
|
|
}
|
|
deleteIterator(it);
|
|
|
|
// Save current MDI settings (window positions, etc.)
|
|
// FIXME
|
|
TDEConfig *c = kapp->config();
|
|
|
|
c->sync();
|
|
|
|
// Allow this window to close
|
|
return true;
|
|
}
|
|
|
|
#include "remotemdi.moc"
|
|
|