mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-23 13:35:58 +03:00
Allow to interrupt running sync task, incl. some cleanups.
This commit is contained in:
parent
f96fa3dbeb
commit
9c4613e5d2
18 changed files with 211 additions and 75 deletions
|
@ -452,23 +452,43 @@ void Application::slotInfoFolder( const QString& alias )
|
|||
|
||||
SyncResult folderResult = _folderMan->syncResult( alias );
|
||||
|
||||
QString folderMessage = tr( "Last sync was succesful." );
|
||||
bool enabled = true;
|
||||
Folder *f = _folderMan->folder( alias );
|
||||
if( f && ! f->syncEnabled() ) {
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
QString folderMessage;
|
||||
|
||||
SyncResult::Status syncStatus = folderResult.status();
|
||||
if ( syncStatus == SyncResult::Error ) {
|
||||
folderMessage = tr( "<b>Syncing Error</b><br/>" );
|
||||
} else if ( syncStatus == SyncResult::SetupError ) {
|
||||
folderMessage = tr( "<b>Setup Error</b><br/>" );
|
||||
} else if ( syncStatus == SyncResult::Disabled ) {
|
||||
folderMessage = tr( "<b>Disabled Folder</b><br/>" ).arg( folderResult.errorString() );
|
||||
} else if ( syncStatus == SyncResult::Undefined ) {
|
||||
folderMessage = tr( "<b>Undefined state</b><br/>" );
|
||||
switch( syncStatus ) {
|
||||
case SyncResult::Undefined:
|
||||
folderMessage = tr( "Undefined Folder State" );
|
||||
break;
|
||||
case SyncResult::NotYetStarted:
|
||||
folderMessage = tr( "The folder waits to start syncing." );
|
||||
break;
|
||||
case SyncResult::SyncRunning:
|
||||
folderMessage = tr("Sync is running.");
|
||||
break;
|
||||
case SyncResult::Success:
|
||||
folderMessage = tr("Last Sync was successful.");
|
||||
break;
|
||||
case SyncResult::Error:
|
||||
folderMessage = tr( "Syncing Error." );
|
||||
break;
|
||||
case SyncResult::SetupError:
|
||||
folderMessage = tr( "Setup Error." );
|
||||
break;
|
||||
default:
|
||||
folderMessage = tr( "Undefined Error State." );
|
||||
}
|
||||
folderMessage = QLatin1String("<b>") + folderMessage + QLatin1String("</b><br/>");
|
||||
|
||||
QMessageBox infoBox( QMessageBox::Information, tr( "Folder information" ), alias, QMessageBox::Ok );
|
||||
QStringList li = folderResult.errorStrings();
|
||||
foreach( const QString l, li ) {
|
||||
folderMessage += "<p>" + l +"</p>";
|
||||
folderMessage += QString("<p>%1</p>").arg( l );
|
||||
}
|
||||
|
||||
infoBox.setText( folderMessage );
|
||||
|
@ -507,7 +527,22 @@ void Application::slotEnableFolder(const QString& alias, const bool enable)
|
|||
qDebug() << "Application: enable folder with alias " << alias;
|
||||
|
||||
_folderMan->slotEnableFolder( alias, enable );
|
||||
_statusDialog->slotUpdateFolderState( _folderMan->folder(alias));
|
||||
|
||||
// this sets the folder status to disabled but does not interrupt it.
|
||||
Folder *f = _folderMan->folder( alias );
|
||||
if( f && !enable ) {
|
||||
// check if a sync is still running and if so, ask if we should terminate.
|
||||
if( f->isBusy() ) { // its still running
|
||||
QMessageBox::StandardButton b = QMessageBox::question( 0, tr("Sync Running"),
|
||||
tr("The syncing operation is running.<br/>Do you want to terminate it?"),
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes );
|
||||
if( b == QMessageBox::Yes ) {
|
||||
_folderMan->terminateSyncProcess( alias );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_statusDialog->slotUpdateFolderState( f );
|
||||
}
|
||||
|
||||
void Application::slotConfigure()
|
||||
|
@ -544,43 +579,44 @@ void Application::computeOverallSyncStatus()
|
|||
SyncResult folderResult = syncedFolder->syncResult();
|
||||
SyncResult::Status syncStatus = folderResult.status();
|
||||
|
||||
if( ! folderResult.localRunOnly() ) { // skip local runs, use the last message.
|
||||
if ( syncStatus == SyncResult::Success ) {
|
||||
folderMessage = tr( "Folder %1: Ok." ).arg( syncedFolder->alias() );
|
||||
} else if ( syncStatus == SyncResult::Error ) {
|
||||
if( ! folderResult.localRunOnly() && syncedFolder->syncEnabled() ) { // skip local runs, use the last message.
|
||||
switch( syncStatus ) {
|
||||
case SyncResult::Undefined:
|
||||
if ( overallResult.status() != SyncResult::Error ) {
|
||||
overallResult = SyncResult::Error;
|
||||
}
|
||||
folderMessage = tr( "Undefined State." );
|
||||
break;
|
||||
case SyncResult::NotYetStarted:
|
||||
folderMessage = tr( "Waits to start syncing." );
|
||||
break;
|
||||
case SyncResult::SyncRunning:
|
||||
folderMessage = tr( "Sync is running." );
|
||||
break;
|
||||
case SyncResult::Success:
|
||||
folderMessage = tr( "Last Sync was successful." );
|
||||
break;
|
||||
case SyncResult::Error:
|
||||
overallResult = SyncResult::Error;
|
||||
folderMessage = tr( "Folder %1: %2" ).arg( syncedFolder->alias(), folderResult.errorString() );
|
||||
} else if ( syncStatus == SyncResult::SetupError ) {
|
||||
folderMessage = tr( "Syncing Error." );
|
||||
break;
|
||||
case SyncResult::SetupError:
|
||||
if ( overallResult.status() != SyncResult::Error ) {
|
||||
overallResult = SyncResult::SetupError;
|
||||
}
|
||||
folderMessage = tr( "Folder %1: setup error" ).arg( syncedFolder->alias() );
|
||||
} else if ( syncStatus == SyncResult::Disabled ) {
|
||||
if ( overallResult.status() != SyncResult::SetupError
|
||||
&& overallResult.status() != SyncResult::Error ) {
|
||||
overallResult = SyncResult::Disabled;
|
||||
}
|
||||
folderMessage = tr( "Folder %1: %2" ).arg( syncedFolder->alias(), folderResult.errorString() );
|
||||
} else if ( syncStatus == SyncResult::Undefined ) {
|
||||
if ( overallResult.status() == SyncResult::Success ) {
|
||||
overallResult = SyncResult::Undefined;
|
||||
}
|
||||
folderMessage = tr( "Folder %1: undefined state" ).arg( syncedFolder->alias() );
|
||||
folderMessage = tr( "Setup Error." );
|
||||
break;
|
||||
default:
|
||||
folderMessage = tr( "Undefined Error State." );
|
||||
}
|
||||
}
|
||||
_overallStatusStrings[syncedFolder] = folderMessage;
|
||||
_overallStatusStrings[syncedFolder] = QString("Folder %1: %2").arg(syncedFolder->alias()).arg(folderMessage);
|
||||
}
|
||||
|
||||
// create the tray blob message
|
||||
QStringList allStatusStrings = _overallStatusStrings.values();
|
||||
trayMessage = allStatusStrings.join("\n");
|
||||
|
||||
#if 0
|
||||
if( _statusDialog->isVisible() ) {
|
||||
_statusDialog->slotUpdateFolderState( syncedFolder );
|
||||
}
|
||||
#endif
|
||||
|
||||
QIcon statusIcon = _theme->syncStateIcon( overallResult.status(), 22 );
|
||||
|
||||
if( overallResult.status() == SyncResult::Success ) {
|
||||
|
|
|
@ -43,7 +43,7 @@ CSyncFolder::~CSyncFolder()
|
|||
|
||||
bool CSyncFolder::isBusy() const
|
||||
{
|
||||
return false;
|
||||
return (_csync && _csync->isRunning() );
|
||||
}
|
||||
|
||||
void CSyncFolder::startSync(const QStringList &pathList)
|
||||
|
@ -64,6 +64,13 @@ void CSyncFolder::startSync(const QStringList &pathList)
|
|||
_csync->start();
|
||||
}
|
||||
|
||||
void CSyncFolder::slotTerminateSync()
|
||||
{
|
||||
if( _csync ) {
|
||||
_csync->terminate();
|
||||
}
|
||||
}
|
||||
|
||||
void CSyncFolder::slotCSyncStarted()
|
||||
{
|
||||
qDebug() << " * csync thread started";
|
||||
|
|
|
@ -36,6 +36,10 @@ public:
|
|||
virtual ~CSyncFolder();
|
||||
virtual void startSync(const QStringList &pathList);
|
||||
virtual bool isBusy() const;
|
||||
|
||||
public slots:
|
||||
void slotTerminateSync();
|
||||
|
||||
protected slots:
|
||||
void slotCSyncStarted();
|
||||
void slotCSyncFinished();
|
||||
|
|
|
@ -30,6 +30,8 @@ namespace Mirall {
|
|||
/* static variables to hold the credentials */
|
||||
QString CSyncThread::_user;
|
||||
QString CSyncThread::_passwd;
|
||||
QString CSyncThread::_csyncConfigDir; // to be able to remove the lock file.
|
||||
|
||||
QMutex CSyncThread::_mutex;
|
||||
|
||||
int CSyncThread::checkPermissions( TREE_WALK_FILE* file, void *data )
|
||||
|
@ -145,6 +147,7 @@ void CSyncThread::run()
|
|||
}
|
||||
// FIXME: Check if we really need this stringcopy!
|
||||
wStats->sourcePath = qstrdup( _source.toLocal8Bit().constData() );
|
||||
_csyncConfigDir = QString::fromLocal8Bit( csync_get_config_dir( csync ));
|
||||
_mutex.unlock();
|
||||
|
||||
qDebug() << "## CSync Thread local only: " << _localCheckOnly;
|
||||
|
@ -280,6 +283,11 @@ void CSyncThread::setUserPwd( const QString& user, const QString& passwd )
|
|||
_mutex.unlock();
|
||||
}
|
||||
|
||||
QString CSyncThread::csyncConfigDir()
|
||||
{
|
||||
return _csyncConfigDir;
|
||||
}
|
||||
|
||||
int CSyncThread::getauth(const char *prompt,
|
||||
char *buf,
|
||||
size_t len,
|
||||
|
|
|
@ -64,6 +64,7 @@ public:
|
|||
|
||||
static void setUserPwd( const QString&, const QString& );
|
||||
static int checkPermissions( TREE_WALK_FILE* file, void *data);
|
||||
static QString csyncConfigDir();
|
||||
|
||||
signals:
|
||||
void treeWalkResult(WalkStats*);
|
||||
|
@ -81,6 +82,7 @@ private:
|
|||
static QMutex _mutex;
|
||||
static QString _user;
|
||||
static QString _passwd;
|
||||
static QString _csyncConfigDir;
|
||||
|
||||
QString _source;
|
||||
QString _target;
|
||||
|
|
|
@ -113,8 +113,7 @@ void Folder::setSyncEnabled( bool doit )
|
|||
_syncResult.clearErrors();
|
||||
evaluateSync( QStringList() );
|
||||
} else {
|
||||
// disabled.
|
||||
_syncResult.setStatus( SyncResult::Disabled );
|
||||
// disable folder. Done through the _enabled-flag set above
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -130,12 +130,21 @@ public:
|
|||
QString backend() const;
|
||||
|
||||
QIcon icon( int size ) const;
|
||||
QTimer *_pollTimer;
|
||||
QTimer *_pollTimer;
|
||||
|
||||
public slots:
|
||||
void slotSyncFinished(const SyncResult &);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void slotChanged(const QStringList &pathList = QStringList() );
|
||||
|
||||
/**
|
||||
* terminate the current sync run
|
||||
*/
|
||||
virtual void slotTerminateSync() = 0;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The minimum amounts of seconds to wait before
|
||||
|
|
|
@ -211,7 +211,19 @@ void FolderMan::slotEnableFolder( const QString& alias, bool enable )
|
|||
}
|
||||
|
||||
Folder *f = _folderMap[alias];
|
||||
f->setSyncEnabled(enable);
|
||||
if( f ) {
|
||||
f->setSyncEnabled(enable);
|
||||
}
|
||||
}
|
||||
|
||||
// this really terminates, ie. no questions, no prisoners.
|
||||
// csync still remains in a stable state, regardless of that.
|
||||
void FolderMan::terminateSyncProcess( const QString& alias )
|
||||
{
|
||||
Folder *f = _folderMap[alias];
|
||||
if( f ) {
|
||||
f->slotTerminateSync();
|
||||
}
|
||||
}
|
||||
|
||||
Folder *FolderMan::folder( const QString& alias )
|
||||
|
@ -269,6 +281,7 @@ void FolderMan::slotScheduleFolderSync()
|
|||
return;
|
||||
}
|
||||
|
||||
qDebug() << "XX slotScheduleFolderSync: folderQueue size: " << _scheduleQueue.count();
|
||||
if( ! _scheduleQueue.isEmpty() ) {
|
||||
const QString alias = _scheduleQueue.takeFirst();
|
||||
if( _folderMap.contains( alias ) ) {
|
||||
|
@ -299,7 +312,7 @@ void FolderMan::slotFolderSyncFinished( const SyncResult& )
|
|||
removeFolder( _currentSyncFolder );
|
||||
_folderToDelete = false;
|
||||
}
|
||||
_currentSyncFolder = QString();
|
||||
_currentSyncFolder.clear();
|
||||
QTimer::singleShot(200, this, SLOT(slotScheduleFolderSync()));
|
||||
}
|
||||
|
||||
|
|
|
@ -84,6 +84,8 @@ public slots:
|
|||
|
||||
void slotReparseConfiguration();
|
||||
|
||||
void terminateSyncProcess( const QString& );
|
||||
|
||||
private slots:
|
||||
// slot to add a folder to the syncing queue
|
||||
void slotScheduleSync( const QString & );
|
||||
|
|
|
@ -177,7 +177,7 @@ QString MirallConfigFile::ownCloudUrl( const QString& connection, bool webdav )
|
|||
if( webdav ) url.append( "files/webdav.php/" );
|
||||
}
|
||||
|
||||
qDebug() << "Returning configured owncloud url: " << url;
|
||||
// qDebug() << "Returning configured owncloud url: " << url;
|
||||
|
||||
return url;
|
||||
}
|
||||
|
@ -191,7 +191,7 @@ QString MirallConfigFile::ownCloudUser( const QString& connection ) const
|
|||
settings.beginGroup( con );
|
||||
|
||||
QString user = settings.value( "user" ).toString();
|
||||
qDebug() << "Returning configured owncloud user: " << user;
|
||||
// qDebug() << "Returning configured owncloud user: " << user;
|
||||
|
||||
return user;
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ void ownCloudFolder::slotPollTimerRemoteCheck()
|
|||
|
||||
bool ownCloudFolder::isBusy() const
|
||||
{
|
||||
return false;
|
||||
return ( _csync && _csync->isRunning() );
|
||||
}
|
||||
|
||||
QString ownCloudFolder::secondPath() const
|
||||
|
@ -85,7 +85,7 @@ QString ownCloudFolder::secondPath() const
|
|||
QString re(_secondPath);
|
||||
MirallConfigFile cfg;
|
||||
const QString ocUrl = cfg.ownCloudUrl(QString(), true);
|
||||
qDebug() << "**** " << ocUrl << " <-> " << re;
|
||||
// qDebug() << "**** " << ocUrl << " <-> " << re;
|
||||
if( re.startsWith( ocUrl ) ) {
|
||||
re.remove( ocUrl );
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ void ownCloudFolder::startSync(const QStringList &pathList)
|
|||
qCritical() << "* ERROR csync is still running and new sync requested.";
|
||||
return;
|
||||
}
|
||||
delete _csync;
|
||||
delete _csync;
|
||||
_errors.clear();
|
||||
_csyncError = false;
|
||||
|
||||
|
@ -201,15 +201,19 @@ void ownCloudFolder::slotCSyncTerminated()
|
|||
{
|
||||
// do not ask csync here for reasons.
|
||||
_syncResult.setStatus( SyncResult::Error );
|
||||
_errors.append( tr("The CSync thread terminated unexpectedly.") );
|
||||
_errors.append( tr("The CSync thread terminated.") );
|
||||
_syncResult.setErrorStrings(_errors);
|
||||
|
||||
emit syncFinished( _syncResult );
|
||||
_csyncError = true;
|
||||
qDebug() << "-> CSync Terminated!";
|
||||
// emit syncFinished( _syncResult );
|
||||
}
|
||||
|
||||
void ownCloudFolder::slotCSyncFinished()
|
||||
{
|
||||
qDebug() << "-> CSync Finished slot with error " << _csyncError;
|
||||
|
||||
if (_csyncError) {
|
||||
|
||||
_syncResult.setStatus(SyncResult::Error);
|
||||
|
||||
qDebug() << " ** error Strings: " << _errors;
|
||||
|
@ -224,5 +228,27 @@ void ownCloudFolder::slotCSyncFinished()
|
|||
emit syncFinished( _syncResult );
|
||||
}
|
||||
|
||||
void ownCloudFolder::slotTerminateSync()
|
||||
{
|
||||
qDebug() << "folder " << alias() << " Terminating!";
|
||||
QString configDir = _csync->csyncConfigDir();
|
||||
qDebug() << "csync's Config Dir: " << configDir;
|
||||
|
||||
if( _csync ) {
|
||||
_csync->terminate();
|
||||
_csync->wait();
|
||||
delete _csync;
|
||||
_csync = 0;
|
||||
}
|
||||
|
||||
if( ! configDir.isEmpty() ) {
|
||||
QFile file( configDir + QLatin1String("/lock"));
|
||||
if( file.exists() ) {
|
||||
qDebug() << "After termination, lock file exists and gets removed.";
|
||||
file.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // ns
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ public:
|
|||
|
||||
public slots:
|
||||
void startSync();
|
||||
void slotTerminateSync();
|
||||
|
||||
private slots:
|
||||
void slotCSyncStarted();
|
||||
|
|
|
@ -307,13 +307,15 @@ void StatusDialog::folderToModelItem( QStandardItem *item, Folder *f )
|
|||
|
||||
SyncResult res = f->syncResult();
|
||||
SyncResult::Status status = res.status();
|
||||
qDebug() << "Folder state is now " << status;
|
||||
|
||||
QString errors = res.errorStrings().join("<br/>");
|
||||
|
||||
item->setData( _theme->statusHeaderText( status ), Qt::ToolTipRole );
|
||||
|
||||
item->setData( _theme->syncStateIcon( status, 48 ), FolderViewDelegate::FolderStatusIcon );
|
||||
if( f->syncEnabled() ) {
|
||||
item->setData( _theme->syncStateIcon( status, 48 ), FolderViewDelegate::FolderStatusIcon );
|
||||
} else {
|
||||
item->setData( _theme->folderDisabledIcon(), FolderViewDelegate::FolderStatusIcon );
|
||||
}
|
||||
item->setData( _theme->statusHeaderText( status ), FolderViewDelegate::FolderStatus );
|
||||
item->setData( errors, FolderViewDelegate::FolderErrorMsg );
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@ public:
|
|||
SyncRunning,
|
||||
Success,
|
||||
Error,
|
||||
Disabled,
|
||||
SetupError
|
||||
};
|
||||
|
||||
|
|
|
@ -47,43 +47,61 @@ QIcon Theme::syncStateIcon( SyncResult::Status status, int ) const
|
|||
// FIXME: Mind the size!
|
||||
QString statusIcon;
|
||||
|
||||
qDebug() << "Status: " << status;
|
||||
|
||||
if( status == SyncResult::NotYetStarted ) {
|
||||
statusIcon = "task-ongoing";
|
||||
} else if( status == SyncResult::SyncRunning ) {
|
||||
statusIcon = "view-refresh";
|
||||
} else if( status == SyncResult::Success ) {
|
||||
statusIcon = "dialog-ok";
|
||||
} else if( status == SyncResult::Error ) {
|
||||
switch( status ) {
|
||||
case SyncResult::Undefined:
|
||||
statusIcon = "dialog-close";
|
||||
} else if( status == SyncResult::Disabled ) {
|
||||
break;
|
||||
case SyncResult::NotYetStarted:
|
||||
statusIcon = "task-ongoing";
|
||||
break;
|
||||
case SyncResult::SyncRunning:
|
||||
statusIcon = "view-refresh";
|
||||
break;
|
||||
case SyncResult::Success:
|
||||
statusIcon = "dialog-ok";
|
||||
break;
|
||||
case SyncResult::Error:
|
||||
statusIcon = "dialog-close";
|
||||
break;
|
||||
case SyncResult::SetupError:
|
||||
statusIcon = "dialog-cancel";
|
||||
} else if( status == SyncResult::SetupError ) {
|
||||
statusIcon = "dialog-cancel";
|
||||
} else {
|
||||
break;
|
||||
default:
|
||||
statusIcon = "dialog-close";
|
||||
}
|
||||
return QIcon::fromTheme( statusIcon, QIcon( QString( ":/mirall/resources/%1").arg(statusIcon) ) );
|
||||
}
|
||||
|
||||
QIcon Theme::folderDisabledIcon() const
|
||||
{
|
||||
// Fixme: Do we really want the dialog-canel from theme here?
|
||||
return QIcon::fromTheme( "dialog-cancel", QIcon( QString( ":/mirall/resources/dialog-cancel")) );
|
||||
}
|
||||
|
||||
QString Theme::statusHeaderText( SyncResult::Status status ) const
|
||||
{
|
||||
QString resultStr;
|
||||
|
||||
if( status == SyncResult::NotYetStarted ) {
|
||||
switch( status ) {
|
||||
case SyncResult::Undefined:
|
||||
resultStr = tr("Status undefined");
|
||||
break;
|
||||
case SyncResult::NotYetStarted:
|
||||
resultStr = tr("Waiting to start sync");
|
||||
} else if( status == SyncResult::SyncRunning ) {
|
||||
break;
|
||||
case SyncResult::SyncRunning:
|
||||
resultStr = tr("Sync is running");
|
||||
} else if( status == SyncResult::Success ) {
|
||||
break;
|
||||
case SyncResult::Success:
|
||||
resultStr = tr("Sync Success");
|
||||
} else if( status == SyncResult::Error ) {
|
||||
break;
|
||||
case SyncResult::Error:
|
||||
resultStr = tr("Sync Error - Click info button for details.");
|
||||
} else if( status == SyncResult::Disabled ) {
|
||||
resultStr = tr("Sync Disabled");
|
||||
} else if( status == SyncResult::SetupError ) {
|
||||
break;
|
||||
case SyncResult::SetupError:
|
||||
resultStr = tr( "Setup Error" );
|
||||
} else {
|
||||
break;
|
||||
default:
|
||||
resultStr = tr("Status undefined");
|
||||
}
|
||||
return resultStr;
|
||||
|
|
|
@ -42,6 +42,7 @@ public:
|
|||
*/
|
||||
virtual QIcon folderIcon( const QString&, int ) const;
|
||||
virtual QIcon syncStateIcon( SyncResult::Status, int ) const;
|
||||
virtual QIcon folderDisabledIcon() const;
|
||||
virtual QString statusHeaderText( SyncResult::Status ) const;
|
||||
virtual QPixmap splashScreen() const = 0;
|
||||
virtual QIcon applicationIcon() const;
|
||||
|
|
|
@ -89,6 +89,12 @@ void UnisonFolder::startSync(const QStringList &pathList)
|
|||
_unison->start(program, args);
|
||||
}
|
||||
|
||||
void UnisonFolder::slotTerminateSync()
|
||||
{
|
||||
if( _unison )
|
||||
_unison->terminate();
|
||||
}
|
||||
|
||||
void UnisonFolder::slotStarted()
|
||||
{
|
||||
qDebug() << " * Unison process started ( PID " << _unison->pid() << ")";
|
||||
|
|
|
@ -38,6 +38,9 @@ public:
|
|||
|
||||
virtual bool isBusy() const;
|
||||
|
||||
public slots:
|
||||
void slotTerminateSync();
|
||||
|
||||
protected slots:
|
||||
void slotReadyReadStandardOutput();
|
||||
void slotReadyReadStandardError();
|
||||
|
|
Loading…
Reference in a new issue