1e1e0b0c48
This is done for all top level windows - ports, stats, logs At startup, the local portgroup would automatically become current with the result that the welcome page would not be visible. Not sure why but an explicit setFocus of ports window seems to avoid it.
637 lines
20 KiB
C++
637 lines
20 KiB
C++
/*
|
|
Copyright (C) 2010 Srivats P.
|
|
|
|
This file is part of "Ostinato"
|
|
|
|
This 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 3 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, see <http://www.gnu.org/licenses/>
|
|
*/
|
|
|
|
#include "mainwindow.h"
|
|
|
|
#if 0
|
|
#include "dbgthread.h"
|
|
#endif
|
|
|
|
#include "clipboardhelper.h"
|
|
#include "jumpurl.h"
|
|
#include "logsmodel.h"
|
|
#include "logswindow.h"
|
|
#include "params.h"
|
|
#include "portgrouplist.h"
|
|
#include "portstatswindow.h"
|
|
#include "portswindow.h"
|
|
#include "preferences.h"
|
|
#include "sessionfileformat.h"
|
|
#include "settings.h"
|
|
#include "ui_about.h"
|
|
#include "updater.h"
|
|
|
|
#include "fileformat.pb.h"
|
|
|
|
#include <QDate>
|
|
#include <QDesktopServices>
|
|
#include <QDockWidget>
|
|
#include <QFileDialog>
|
|
#include <QMessageBox>
|
|
#include <QProcess>
|
|
#include <QProgressDialog>
|
|
#include <QTimer>
|
|
#include <QUrl>
|
|
|
|
#ifdef Q_OS_WIN32
|
|
#define WIN32_NO_STATUS
|
|
#include <windows.h>
|
|
#undef WIN32_NO_STATUS
|
|
#include <ntstatus.h>
|
|
#endif
|
|
|
|
extern const char* version;
|
|
extern const char* revision;
|
|
|
|
PortGroupList *pgl;
|
|
LogsModel *appLogs;
|
|
ClipboardHelper *clipboardHelper;
|
|
|
|
MainWindow::MainWindow(QWidget *parent)
|
|
: QMainWindow (parent)
|
|
{
|
|
Updater *updater = new Updater();
|
|
|
|
if (appParams.optLocalDrone()) {
|
|
QString serverApp = QCoreApplication::applicationDirPath();
|
|
#ifdef Q_OS_MAC
|
|
// applicationDirPath() does not return bundle,
|
|
// but executable inside bundle
|
|
serverApp.replace("Ostinato.app", "drone.app");
|
|
#endif
|
|
#ifdef Q_OS_WIN32
|
|
serverApp.append("/drone.exe");
|
|
#else
|
|
serverApp.append("/drone");
|
|
#endif
|
|
|
|
qDebug("staring local server - %s", qPrintable(serverApp));
|
|
localServer_ = new QProcess(this);
|
|
connect(localServer_, SIGNAL(finished(int, QProcess::ExitStatus)),
|
|
SLOT(onLocalServerFinished(int, QProcess::ExitStatus)));
|
|
connect(localServer_, SIGNAL(error(QProcess::ProcessError)),
|
|
SLOT(onLocalServerError(QProcess::ProcessError)));
|
|
localServer_->setProcessChannelMode(QProcess::ForwardedChannels);
|
|
localServer_->start(serverApp, QStringList());
|
|
QTimer::singleShot(5000, this, SLOT(stopLocalServerMonitor()));
|
|
}
|
|
else
|
|
localServer_ = NULL;
|
|
|
|
pgl = new PortGroupList;
|
|
appLogs = new LogsModel(this);
|
|
clipboardHelper = new ClipboardHelper(this);
|
|
|
|
portsWindow = new PortsWindow(pgl, this);
|
|
statsWindow = new PortStatsWindow(pgl, this);
|
|
|
|
portsDock = new QDockWidget(tr("Ports and Streams"), this);
|
|
portsDock->setObjectName("portsDock");
|
|
portsDock->setFeatures(
|
|
portsDock->features() & ~QDockWidget::DockWidgetClosable);
|
|
|
|
statsDock = new QDockWidget(tr("Port Statistics"), this);
|
|
statsDock->setObjectName("statsDock");
|
|
statsDock->setFeatures(
|
|
statsDock->features() & ~QDockWidget::DockWidgetClosable);
|
|
|
|
logsDock_ = new QDockWidget(tr("Logs"), this);
|
|
logsDock_->setObjectName("logsDock");
|
|
logsDock_->setFeatures(
|
|
logsDock_->features() & ~QDockWidget::DockWidgetClosable);
|
|
logsWindow_ = new LogsWindow(appLogs, logsDock_);
|
|
|
|
setupUi(this);
|
|
|
|
menuFile->insertActions(menuFile->actions().at(3), portsWindow->actions());
|
|
menuEdit->addActions(clipboardHelper->actions());
|
|
|
|
statsDock->setWidget(statsWindow);
|
|
addDockWidget(Qt::BottomDockWidgetArea, statsDock);
|
|
logsDock_->setWidget(logsWindow_);
|
|
addDockWidget(Qt::BottomDockWidgetArea, logsDock_);
|
|
tabifyDockWidget(statsDock, logsDock_);
|
|
statsDock->show();
|
|
statsDock->raise();
|
|
|
|
portsDock->setWidget(portsWindow);
|
|
addDockWidget(Qt::TopDockWidgetArea, portsDock);
|
|
|
|
#if QT_VERSION >= 0x050600
|
|
// Set top and bottom docks to equal height
|
|
resizeDocks({portsDock, statsDock}, {height()/2, height()/2}, Qt::Vertical);
|
|
#endif
|
|
|
|
portsWindow->setFocus();
|
|
|
|
// Save the default window geometry and layout ...
|
|
defaultGeometry_ = geometry();
|
|
defaultLayout_ = saveState(0);
|
|
|
|
// ... before restoring the last used settings
|
|
QRect geom = appSettings->value(kApplicationWindowGeometryKey).toRect();
|
|
if (!geom.isNull())
|
|
setGeometry(geom);
|
|
QByteArray layout = appSettings->value(kApplicationWindowLayout)
|
|
.toByteArray();
|
|
if (layout.size())
|
|
restoreState(layout, 0);
|
|
|
|
connect(actionFileExit, SIGNAL(triggered()), this, SLOT(close()));
|
|
connect(actionAboutQt, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
|
|
|
|
connect(actionViewShowMyReservedPortsOnly, SIGNAL(toggled(bool)),
|
|
portsWindow, SLOT(showMyReservedPortsOnly(bool)));
|
|
connect(actionViewShowMyReservedPortsOnly, SIGNAL(toggled(bool)),
|
|
statsWindow, SLOT(showMyReservedPortsOnly(bool)));
|
|
|
|
connect(updater, SIGNAL(newVersionAvailable(QString)),
|
|
this, SLOT(onNewVersion(QString)));
|
|
updater->checkForNewVersion();
|
|
|
|
// Add the "Local" Port Group
|
|
if (appParams.optLocalDrone()) {
|
|
PortGroup *pg = new PortGroup;
|
|
pgl->addPortGroup(*pg);
|
|
}
|
|
|
|
if (appParams.argumentCount()) {
|
|
QString fileName = appParams.argument(0);
|
|
if (QFile::exists(fileName))
|
|
openSession(fileName);
|
|
else
|
|
QMessageBox::information(NULL, qApp->applicationName(),
|
|
QString("File not found: " + fileName));
|
|
}
|
|
|
|
#if 0
|
|
{
|
|
DbgThread *dbg = new DbgThread(pgl);
|
|
dbg->start();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
MainWindow::~MainWindow()
|
|
{
|
|
stopLocalServerMonitor();
|
|
if (localServer_) {
|
|
#ifdef Q_OS_WIN32
|
|
//! \todo - find a way to terminate cleanly
|
|
localServer_->kill();
|
|
#else
|
|
localServer_->terminate();
|
|
#endif
|
|
}
|
|
|
|
delete pgl;
|
|
|
|
// We don't want to save state for Stream Stats Docks - so delete them
|
|
QList<QDockWidget*> streamStatsDocks
|
|
= findChildren<QDockWidget*>("streamStatsDock");
|
|
foreach(QDockWidget *dock, streamStatsDocks)
|
|
delete dock;
|
|
Q_ASSERT(findChildren<QDockWidget*>("streamStatsDock").size() == 0);
|
|
|
|
QByteArray layout = saveState(0);
|
|
appSettings->setValue(kApplicationWindowLayout, layout);
|
|
appSettings->setValue(kApplicationWindowGeometryKey, geometry());
|
|
|
|
if (localServer_) {
|
|
localServer_->waitForFinished();
|
|
delete localServer_;
|
|
}
|
|
}
|
|
|
|
void MainWindow::openSession(QString fileName)
|
|
{
|
|
qDebug("Open Session Action (%s)", qPrintable(fileName));
|
|
|
|
static QString dirName;
|
|
QStringList fileTypes = SessionFileFormat::supportedFileTypes(
|
|
SessionFileFormat::kOpenFile);
|
|
QString fileType;
|
|
QString errorStr;
|
|
bool ret;
|
|
|
|
if (!fileName.isEmpty())
|
|
goto _skip_prompt;
|
|
|
|
if (portsWindow->portGroupCount()) {
|
|
if (QMessageBox::question(this,
|
|
tr("Open Session"),
|
|
tr("Existing session will be lost. Proceed?"),
|
|
QMessageBox::Yes | QMessageBox::No,
|
|
QMessageBox::No) == QMessageBox::No)
|
|
goto _exit;
|
|
}
|
|
|
|
if (fileTypes.size())
|
|
fileType = fileTypes.at(0);
|
|
|
|
fileName = QFileDialog::getOpenFileName(this, tr("Open Session"),
|
|
dirName, fileTypes.join(";;"), &fileType);
|
|
if (fileName.isEmpty())
|
|
goto _exit;
|
|
|
|
_skip_prompt:
|
|
ret = openSession(fileName, errorStr);
|
|
if (!ret || !errorStr.isEmpty()) {
|
|
QMessageBox msgBox(this);
|
|
QStringList str = errorStr.split("\n\n\n\n");
|
|
|
|
msgBox.setIcon(ret ? QMessageBox::Warning : QMessageBox::Critical);
|
|
msgBox.setWindowTitle(qApp->applicationName());
|
|
msgBox.setText(str.at(0));
|
|
if (str.size() > 1)
|
|
msgBox.setDetailedText(str.at(1));
|
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
|
|
|
msgBox.exec();
|
|
}
|
|
dirName = QFileInfo(fileName).absolutePath();
|
|
|
|
_exit:
|
|
return;
|
|
}
|
|
|
|
void MainWindow::on_actionOpenSession_triggered()
|
|
{
|
|
openSession();
|
|
}
|
|
|
|
void MainWindow::on_actionSaveSession_triggered()
|
|
{
|
|
qDebug("Save Session Action");
|
|
|
|
static QString fileName;
|
|
QStringList fileTypes = SessionFileFormat::supportedFileTypes(
|
|
SessionFileFormat::kSaveFile);
|
|
QString fileType;
|
|
QString errorStr;
|
|
QFileDialog::Options options;
|
|
|
|
if (portsWindow->reservedPortCount()) {
|
|
QString myself = appSettings->value(kUserKey, kUserDefaultValue)
|
|
.toString();
|
|
if (QMessageBox::question(this,
|
|
tr("Save Session"),
|
|
QString("Some ports are reserved!\n\nOnly ports reserved by %1 will be saved. Proceed?").arg(myself),
|
|
QMessageBox::Yes | QMessageBox::No,
|
|
QMessageBox::No) == QMessageBox::No)
|
|
goto _exit;
|
|
}
|
|
|
|
// On Mac OS with Native Dialog, getSaveFileName() ignores fileType.
|
|
// Although currently there's only one supported file type, we may
|
|
// have more in the future
|
|
#if defined(Q_OS_MAC)
|
|
options |= QFileDialog::DontUseNativeDialog;
|
|
#endif
|
|
|
|
if (fileTypes.size())
|
|
fileType = fileTypes.at(0);
|
|
|
|
_retry:
|
|
fileName = QFileDialog::getSaveFileName(this, tr("Save Session"),
|
|
fileName, fileTypes.join(";;"), &fileType, options);
|
|
if (fileName.isEmpty())
|
|
goto _exit;
|
|
|
|
if (QFileInfo(fileName).suffix().isEmpty()) {
|
|
QString fileExt = fileType.section(QRegExp("[\\*\\)]"), 1, 1);
|
|
qDebug("Adding extension '%s' to '%s'",
|
|
qPrintable(fileExt), qPrintable(fileName));
|
|
fileName.append(fileExt);
|
|
if (QFileInfo(fileName).exists()) {
|
|
if (QMessageBox::warning(this, tr("Overwrite File?"),
|
|
QString("The file \"%1\" already exists.\n\n"
|
|
"Do you wish to overwrite it?")
|
|
.arg(QFileInfo(fileName).fileName()),
|
|
QMessageBox::Yes|QMessageBox::No,
|
|
QMessageBox::No) != QMessageBox::Yes)
|
|
goto _retry;
|
|
}
|
|
}
|
|
|
|
if (!saveSession(fileName, fileType, errorStr))
|
|
QMessageBox::critical(this, qApp->applicationName(), errorStr);
|
|
else if (!errorStr.isEmpty())
|
|
QMessageBox::warning(this, qApp->applicationName(), errorStr);
|
|
|
|
fileName = QFileInfo(fileName).absolutePath();
|
|
_exit:
|
|
return;
|
|
}
|
|
|
|
void MainWindow::on_actionPreferences_triggered()
|
|
{
|
|
Preferences *preferences = new Preferences();
|
|
|
|
preferences->exec();
|
|
|
|
delete preferences;
|
|
}
|
|
|
|
void MainWindow::on_actionViewRestoreDefaults_triggered()
|
|
{
|
|
// Use the saved default geometry/layout, however keep the
|
|
// window location same
|
|
defaultGeometry_.moveTo(geometry().topLeft());
|
|
setGeometry(defaultGeometry_);
|
|
restoreState(defaultLayout_, 0);
|
|
|
|
// Add streamStats as tabs
|
|
QList<QDockWidget*> streamStatsDocks
|
|
= findChildren<QDockWidget*>("streamStatsDock");
|
|
foreach(QDockWidget *dock, streamStatsDocks) {
|
|
dock->setFloating(false);
|
|
tabifyDockWidget(statsDock, dock);
|
|
}
|
|
statsDock->show();
|
|
statsDock->raise();
|
|
|
|
actionViewShowMyReservedPortsOnly->setChecked(false);
|
|
|
|
portsWindow->clearCurrentSelection();
|
|
statsWindow->clearCurrentSelection();
|
|
logsWindow_->clearCurrentSelection();
|
|
}
|
|
|
|
void MainWindow::on_actionHelpOnline_triggered()
|
|
{
|
|
QDesktopServices::openUrl(QUrl(jumpUrl("help", "app", "menu")));
|
|
}
|
|
|
|
void MainWindow::on_actionDonate_triggered()
|
|
{
|
|
QDesktopServices::openUrl(QUrl(jumpUrl("donate", "app", "menu")));
|
|
}
|
|
|
|
void MainWindow::on_actionCheckForUpdates_triggered()
|
|
{
|
|
Updater *updater = new Updater();
|
|
connect(updater, SIGNAL(latestVersion(QString)),
|
|
this, SLOT(onLatestVersion(QString)));
|
|
updater->checkForNewVersion();
|
|
}
|
|
|
|
void MainWindow::on_actionHelpAbout_triggered()
|
|
{
|
|
QDialog *aboutDialog = new QDialog;
|
|
|
|
Ui::About about;
|
|
about.setupUi(aboutDialog);
|
|
about.versionLabel->setText(
|
|
QString("Version: %1 Revision: %2").arg(version).arg(revision));
|
|
|
|
aboutDialog->exec();
|
|
|
|
delete aboutDialog;
|
|
}
|
|
|
|
void MainWindow::stopLocalServerMonitor()
|
|
{
|
|
// We are only interested in startup errors
|
|
disconnect(localServer_, SIGNAL(error(QProcess::ProcessError)),
|
|
this, SLOT(onLocalServerError(QProcess::ProcessError)));
|
|
disconnect(localServer_, SIGNAL(finished(int, QProcess::ExitStatus)),
|
|
this, SLOT(onLocalServerFinished(int, QProcess::ExitStatus)));
|
|
}
|
|
|
|
void MainWindow::onLocalServerFinished(int exitCode,
|
|
QProcess::ExitStatus /*exitStatus*/)
|
|
{
|
|
if (exitCode)
|
|
reportLocalServerError();
|
|
}
|
|
|
|
void MainWindow::onLocalServerError(QProcess::ProcessError /*error*/)
|
|
{
|
|
reportLocalServerError();
|
|
}
|
|
|
|
void MainWindow::reportLocalServerError()
|
|
{
|
|
QMessageBox msgBox(this);
|
|
msgBox.setIcon(QMessageBox::Warning);
|
|
msgBox.setTextFormat(Qt::RichText);
|
|
msgBox.setStyleSheet("messagebox-text-interaction-flags: 5"); // mouse copy
|
|
QString errorStr = tr("<p>Failed to start the local drone agent - "
|
|
"error 0x%1, exit status 0x%2 exit code 0x%3.</p>")
|
|
.arg(localServer_->error(), 0, 16)
|
|
.arg(localServer_->exitStatus(), 0, 16)
|
|
.arg(localServer_->exitCode(), 0, 16);
|
|
if (localServer_->error() == QProcess::FailedToStart)
|
|
errorStr.append(tr("<p>The drone program does not exist at %1 or you "
|
|
"don't have sufficient permissions to execute it."
|
|
"</p>")
|
|
.arg(QCoreApplication::applicationDirPath()));
|
|
if (localServer_->exitCode() == 1)
|
|
errorStr.append(tr("<p>The drone program was not able to bind to "
|
|
"TCP port 7878 - maybe a drone process is already "
|
|
"running?</p>"));
|
|
#ifdef Q_OS_WIN32
|
|
if (localServer_->exitCode() == STATUS_DLL_NOT_FOUND)
|
|
errorStr.append(tr("<p>This is most likely because Packet.dll "
|
|
"was not found - make sure you have "
|
|
"<a href='%1'>WinPcap"
|
|
"</a> installed.</p>")
|
|
.arg(jumpUrl("winpcap")));
|
|
#endif
|
|
msgBox.setText(errorStr);
|
|
msgBox.setInformativeText(tr("Try running drone directly."));
|
|
msgBox.exec();
|
|
|
|
QMessageBox::information(this, QString(),
|
|
tr("<p>If you have remote drone agents running, you can still add "
|
|
"and connect to them.</p>"
|
|
"<p>If you don't want to start the local drone agent at startup, "
|
|
"provide the <b>-c</b> option to Ostinato on the command line.</p>"
|
|
"<p>Learn about Ostinato's <a href='%1'>Controller-Agent "
|
|
"architecture</a></p>").arg(jumpUrl("arch")));
|
|
}
|
|
|
|
void MainWindow::onNewVersion(QString newVersion)
|
|
{
|
|
QDate today = QDate::currentDate();
|
|
QDate lastChecked = QDate::fromString(
|
|
appSettings->value(kLastUpdateCheck).toString(),
|
|
Qt::ISODate);
|
|
if (lastChecked.daysTo(today) >= 5) {
|
|
QMessageBox::information(this, tr("Update check"),
|
|
tr("<p><b>Ostinato version %1 is now available</b> (you have %2). "
|
|
"See <a href='%3'>change log</a>.</p>"
|
|
"<p>Visit <a href='%4'>ostinato.org</a> to download.</p>")
|
|
.arg(newVersion)
|
|
.arg(version)
|
|
.arg(jumpUrl("changelog", "app", "status", "update"))
|
|
.arg(jumpUrl("download", "app", "status", "update")));
|
|
}
|
|
else {
|
|
QLabel *msg = new QLabel(tr("New Ostinato version %1 available. Visit "
|
|
"<a href='%2'>ostinato.org</a> to download")
|
|
.arg(newVersion)
|
|
.arg(jumpUrl("download", "app", "status", "update")));
|
|
msg->setOpenExternalLinks(true);
|
|
statusBar()->addPermanentWidget(msg);
|
|
}
|
|
|
|
appSettings->setValue(kLastUpdateCheck, today.toString(Qt::ISODate));
|
|
sender()->deleteLater();
|
|
}
|
|
|
|
void MainWindow::onLatestVersion(QString latestVersion)
|
|
{
|
|
if (version != latestVersion) {
|
|
QMessageBox::information(this, tr("Update check"),
|
|
tr("<p><b>Ostinato version %1 is now available</b> (you have %2). "
|
|
"See <a href='%3'>change log</a>.</p>"
|
|
"<p>Visit <a href='%4'>ostinato.org</a> to download.</p>")
|
|
.arg(latestVersion)
|
|
.arg(version)
|
|
.arg(jumpUrl("changelog", "app", "status", "update"))
|
|
.arg(jumpUrl("download", "app", "status", "update")));
|
|
}
|
|
else {
|
|
QMessageBox::information(this, tr("Update check"),
|
|
tr("You are already running the latest Ostinato version - %1")
|
|
.arg(version));
|
|
}
|
|
|
|
sender()->deleteLater();
|
|
}
|
|
|
|
//! Returns true on success (or user cancel) and false on failure
|
|
bool MainWindow::openSession(QString fileName, QString &error)
|
|
{
|
|
bool ret = false;
|
|
QDialog *optDialog;
|
|
QProgressDialog progress("Opening Session", "Cancel", 0, 0, this);
|
|
OstProto::SessionContent session;
|
|
SessionFileFormat *fmt = SessionFileFormat::fileFormatFromFile(fileName);
|
|
|
|
if (fmt == NULL) {
|
|
error = tr("Unknown session file format");
|
|
goto _fail;
|
|
}
|
|
|
|
if ((optDialog = fmt->openOptionsDialog()))
|
|
{
|
|
int ret;
|
|
optDialog->setParent(this, Qt::Dialog);
|
|
ret = optDialog->exec();
|
|
optDialog->setParent(0, Qt::Dialog);
|
|
if (ret == QDialog::Rejected)
|
|
goto _user_opt_cancel;
|
|
}
|
|
|
|
progress.setAutoReset(false);
|
|
progress.setAutoClose(false);
|
|
progress.setMinimumDuration(0);
|
|
progress.show();
|
|
|
|
setDisabled(true);
|
|
progress.setEnabled(true); // to override the mainWindow disable
|
|
|
|
connect(fmt, SIGNAL(status(QString)),&progress,SLOT(setLabelText(QString)));
|
|
connect(fmt, SIGNAL(target(int)), &progress, SLOT(setMaximum(int)));
|
|
connect(fmt, SIGNAL(progress(int)), &progress, SLOT(setValue(int)));
|
|
connect(&progress, SIGNAL(canceled()), fmt, SLOT(cancel()));
|
|
|
|
fmt->openAsync(fileName, session, error);
|
|
qDebug("after open async");
|
|
|
|
while (!fmt->isFinished())
|
|
qApp->processEvents();
|
|
qDebug("wait over for async operation");
|
|
|
|
if (!fmt->result())
|
|
goto _fail;
|
|
|
|
// process any remaining events posted from the thread
|
|
for (int i = 0; i < 10; i++)
|
|
qApp->processEvents();
|
|
|
|
// XXX: user can't cancel operation from here on!
|
|
progress.close();
|
|
|
|
portsWindow->openSession(&session, error);
|
|
|
|
_user_opt_cancel:
|
|
ret = true;
|
|
|
|
_fail:
|
|
progress.close();
|
|
setEnabled(true);
|
|
return ret;
|
|
}
|
|
|
|
bool MainWindow::saveSession(QString fileName, QString fileType, QString &error)
|
|
{
|
|
bool ret = false;
|
|
QProgressDialog progress("Saving Session", "Cancel", 0, 0, this);
|
|
SessionFileFormat *fmt = SessionFileFormat::fileFormatFromType(fileType);
|
|
OstProto::SessionContent session;
|
|
|
|
if (fmt == NULL)
|
|
goto _fail;
|
|
|
|
progress.setAutoReset(false);
|
|
progress.setAutoClose(false);
|
|
progress.setMinimumDuration(0);
|
|
progress.show();
|
|
|
|
setDisabled(true);
|
|
progress.setEnabled(true); // to override the mainWindow disable
|
|
|
|
// Fill in session
|
|
ret = portsWindow->saveSession(&session, error, &progress);
|
|
if (!ret)
|
|
goto _user_cancel;
|
|
|
|
connect(fmt, SIGNAL(status(QString)),&progress,SLOT(setLabelText(QString)));
|
|
connect(fmt, SIGNAL(target(int)), &progress, SLOT(setMaximum(int)));
|
|
connect(fmt, SIGNAL(progress(int)), &progress, SLOT(setValue(int)));
|
|
connect(&progress, SIGNAL(canceled()), fmt, SLOT(cancel()));
|
|
|
|
fmt->saveAsync(session, fileName, error);
|
|
qDebug("after save async");
|
|
|
|
while (!fmt->isFinished())
|
|
qApp->processEvents();
|
|
qDebug("wait over for async operation");
|
|
|
|
ret = fmt->result();
|
|
goto _exit;
|
|
|
|
_user_cancel:
|
|
goto _exit;
|
|
|
|
_fail:
|
|
error = QString("Unsupported File Type - %1").arg(fileType);
|
|
goto _exit;
|
|
|
|
_exit:
|
|
progress.close();
|
|
setEnabled(true);
|
|
return ret;
|
|
}
|
|
|