Beispiel #1
0
QString Folder::aliasGui() const
{
    if (remotePath().length() > 0 && remotePath() != QLatin1String("/")) {
        QString a = QFile(remotePath()).fileName();
        if (a.startsWith('/')) {
            a = a.remove(0, 1);
        }
        return a;
    } else {
        return Theme::instance()->appNameGUI();
    }
}
Beispiel #2
0
/**
* ChangeFilePermissions
*
*/
bool CFtpManager::ChangeFilePermissions(CConnection * con, CFileContainer & file, CString & permissions, CWaitDialog & waitDialog)
{
	bool result = false;
	if(!m_ftpClient.IsConnected())
	{
		int retcode = 11;
		retcode = m_ftpClient.FTPConnect(con->host, con->user, con->password, _T(""));
		if(retcode == UTE_SUCCESS)
		{
			
		}
	}
	m_ftpClient.SetFireWallMode(TRUE);

	//CString localStorePath;
	//GetLocalStorePath(con, localStorePath);
	//CString localPath(localStorePath + filePath + fileName);
	//localPath.Replace('/', '\\');

	CString remotePath(file.path + file.name);
	//CString renameToPath(file.path + new.name);

	int r = m_ftpClient.ChmodFile( remotePath, permissions );
	if(r == UTE_SUCCESS)
	{
		result = true;
	}

	if(r == UTE_NO_RESPONSE) {TRACE0(" Error: UTE_NO_RESPONSE \n");}
	//if(r == UTE_RNFR_NA) {TRACE0(" Error: UTE_RNFR_NA \n");}
	//if(r == UTE_RNTO_NA) {TRACE0(" Error: UTE_RNTO_NA \n");}
	
	return result;
}
Beispiel #3
0
/**
* CreateFolder
*
*/
bool CFtpManager::CreateFolder(CConnection * con, CString & path, CString & folder)
{
	bool result = false;
	
	CString remotePath(path + folder);

	if(!m_ftpClient.IsConnected())
	{
		int retcode = 11;
		retcode = m_ftpClient.FTPConnect(con->host, con->user, con->password, _T(""));
		if(retcode == UTE_SUCCESS)
		{
			
		}
	}
	m_ftpClient.SetFireWallMode(TRUE);
	int r = m_ftpClient.MkDir(remotePath);
	if(r == UTE_SUCCESS)
	{
		result = true;
	}
	// Allready exists = 10
	if(r == 10){
		result = true;
	}

	return result;
}
Beispiel #4
0
/**
* RenameFile
*
* Description: 
*/
bool CFtpManager::RenameFile(CConnection * con, CString & filePath, CString & fileName, CString & newName)
{
	bool result = false;
	if(!m_ftpClient.IsConnected())
	{
		int retcode = 11;
		retcode = m_ftpClient.FTPConnect(con->host, con->user, con->password, _T(""));
		if(retcode == UTE_SUCCESS)
		{
			
		}
	}
	m_ftpClient.SetFireWallMode(TRUE);

	//CString localStorePath;
	//GetLocalStorePath(con, localStorePath);
	//CString localPath(localStorePath + filePath + fileName);
	//localPath.Replace('/', '\\');

	CString remotePath(filePath + fileName);
	CString renameToPath(filePath + newName);

	int r = m_ftpClient.RenameFile(remotePath, renameToPath);
	if(r == UTE_SUCCESS)
	{
		result = true;
	}

	if(r == UTE_NO_RESPONSE) {TRACE0(" Error: UTE_NO_RESPONSE \n");}
	if(r == UTE_RNFR_NA) {TRACE0(" Error: UTE_RNFR_NA \n");}
	if(r == UTE_RNTO_NA) {TRACE0(" Error: UTE_RNTO_NA \n");}
	
	return result;
}
/* install packages defined in packageList from local path to sensor*/
bool SensorUpdater::installPackagesFromPath(const VersionList& packageList,
                                            const std::string& localPath)
{
  if (!is_ssh_initialized_) {
    std::cout << "sensor updater is not connected to any sensor\n";
    return false;
  }
  for (size_t i = 0; i < packageList.size(); i++) {
    std::cout << "Installing " << packageList[i].package_name << " ...  ";

    // download
    std::string pkg_filename = localPath + packageList[i].package_name + std::string(".deb");
    std::string pkg_remote_filename = remotePath() + packageList[i].package_name + std::string(".deb");

    // transfer file to sensor
    bool ret = pSsh_->sendFile(pkg_filename, pkg_remote_filename);
    if (!ret) {
      std::cout << "failed.\n";
      std::cout << "[ERROR]: Could not upload file to sensor!\n";
      exit(1);
    }

    // install
    ret = sensorInstallDebFile(pkg_remote_filename);

    if (!ret) {
      std::cout << "failed.\n";
      std::cout << "[ERROR]: Could not install debfile on sensor " << pkg_filename << "\n";
      exit(1);
    }
    std::cout << "done.\n";
  }
  std::cout << std::endl;
  return true;
}
Beispiel #6
0
void Folder::slotRunEtagJob()
{
    qDebug() << "* Trying to check" << alias() << "for changes via ETag check. (time since last sync:" << (_timeSinceLastSyncDone.elapsed() / 1000) << "s)";

    Q_ASSERT(_accountState );

    AccountPtr account = _accountState->account();

    if (!_requestEtagJob.isNull()) {
        qDebug() << Q_FUNC_INFO << alias() << "has ETag job queued, not trying to sync";
        return;
    }

    if (_definition.paused || !_accountState->isConnected()) {
        qDebug() << "Not syncing.  :"  << alias() << _definition.paused << AccountState::stateString(_accountState->state());
        return;
    }

    bool forceSyncIntervalExpired =
            quint64(_timeSinceLastSyncDone.elapsed()) > ConfigFile().forceSyncInterval();
    bool syncAgainAfterFail = _consecutiveFailingSyncs > 0 && _consecutiveFailingSyncs < 3;

    // There are several conditions under which we trigger a full-discovery sync:
    // * When a suitably long time has passed since the last sync finished
    // * When the last sync failed (only a couple of times)
    // * When the last sync requested another sync to be done (only a couple of times)
    //
    // Note that the etag check (see below) and the file watcher may also trigger
    // syncs.
    if (forceSyncIntervalExpired
            || _forceSyncOnPollTimeout
            || syncAgainAfterFail) {

        if (forceSyncIntervalExpired) {
            qDebug() << "** Force Sync, because it has been " << _timeSinceLastSyncDone.elapsed() << "ms "
                     << "since the last sync";
        }
        if (_forceSyncOnPollTimeout) {
            qDebug() << "** Force Sync, because it was requested";
        }
        if (syncAgainAfterFail) {
            qDebug() << "** Force Sync, because the last"
                     << _consecutiveFailingSyncs << "syncs failed, last status:"
                     << _syncResult.statusString();
        }
        _forceSyncOnPollTimeout = false;
        emit scheduleToSync(this);

    } else {
        // Do the ordinary etag check for the root folder and only schedule a real
        // sync if it's different.

        _requestEtagJob = new RequestEtagJob(account, remotePath(), this);
        // check if the etag is different
        QObject::connect(_requestEtagJob, SIGNAL(etagRetreived(QString)), this, SLOT(etagRetreived(QString)));
        FolderMan::instance()->slotScheduleETagJob(alias(), _requestEtagJob);
        // The _requestEtagJob is auto deleting itself on finish. Our guard pointer _requestEtagJob will then be null.
    }
}
/**
* SetPath()
* Set the current path of the remote device OBEX session.
*/
bool QBtObjectExchangeClientPrivate::SetPath (const QString & path)
{
	if (connectionHandle == BTSDK_INVALID_HANDLE)
	{
		emit p_ptr->error(QBtObjectExchangeClient::OBEXClientDisconnected);
		return false;
	}

	BTINT32 iErrorCode;
	//BTUINT8 editedFolderName[BTSDK_PATH_MAXLENGTH];
	//memset(editedFolderName, '\0', BTSDK_PATH_MAXLENGTH);

	/*editedFolderName[0] = '\\';

	if(path.size() > 0)
		memcpy(editedFolderName+1, 
				path.constData(), 
				(path.size() < BTSDK_PATH_MAXLENGTH) ? 
						path.size() : 
						BTSDK_PATH_MAXLENGTH);*/
	QString pathEdited = path;
	pathEdited.prepend("\\");

	// first try if file is in relative path form
	iErrorCode = Btsdk_FTPSetRmtDir(connectionHandle, (BTUINT8*)pathEdited.toUtf8().constData());

	if(iErrorCode != BTSDK_OK)
	{
		// then try as absolute path, going first to root path and then setting 
		// the path given as argument
		Btsdk_FTPSetRmtDir(connectionHandle, NULL);
		iErrorCode = Btsdk_FTPSetRmtDir(connectionHandle, (BTUINT8*)pathEdited.toUtf8().constData());
	}

	if(iErrorCode == BTSDK_OK)
	{
		QString remotePath(GetRemoteWorkingDirectory());
		emit p_ptr->remotePathSet(remotePath);
		return true;
	}
	else
	{
		emit p_ptr->error(QBtObjectExchangeClient::OBEXClientUnableToSetPath);
		return false;
	}
}
Beispiel #8
0
/**
* ReceiveFile
*
* Description: Starts a receive transfer in a new thread. If multiple 
*  file transfers are requested in the same operation the same waitDialog is used to track them.
*/
bool CFtpManager::ReceiveFile(CConnection * con, CFileContainer & file, CWaitDialog & waitDialog) 
{
	bool result = false;

	CString localStorePath;
	GetLocalStorePath(con, localStorePath);
	CString localPath(localStorePath + file.path + file.name);
	localPath.Replace('/', '\\');

	CString remotePath(file.path + file.name);

	CRealFtpClient * ftpClient = new CRealFtpClient();
	ftpClient->fileSize = file.size;
	ftpClient->m_waitDialog = &waitDialog;
	ftpClient->con = con;

	CFileTransfer * transfer = new CFileTransfer();
	transfer->sending = false;
	CConnection * conClone = new CConnection(con);
	transfer->connection = conClone;
	transfer->fileName = file.name;
	ftpClient->m_transfer = transfer;

	FTP_THREADPARAM * _param = new FTP_THREADPARAM;
	_param->c = this;
	_param->con = con;
	_param->localPath = localPath;
	_param->remotePath = remotePath;
	_param->ftpClient = ftpClient;
	_param->fileSize = file.size; 
	_param->waitDialog = &waitDialog;
	
	m_pReceiveFileThread = AfxBeginThread(CFtpManager::ReceiveFileWorker, _param); 
	if (m_pReceiveFileThread != NULL)
	{
		//TRACE(_T("AfxBeginThread: 0x%08lX\n"), m_pReceiveFileThread->m_nThreadID);
		result = true;
	}

	return result;
}
Beispiel #9
0
/**
* DeleteFile
*
* Description: Delete a file from the local system and remote FTP server.
*				TODO: multi file select
* Parameters: CFileContainer  contains identification for file to be removed
*
* Returns:    bool true if deleted, false if not deleted.
*/
bool CFtpManager::DeleteFile(CConnection * con, CFileContainer & file)
{
	bool result = false;
	
	CString localStorePath;
	GetLocalStorePath(con, localStorePath);
	CString localPath(localStorePath + file.path + file.name);
	localPath.Replace('/', '\\');

	CString remotePath(file.path + file.name);

	//TRACE2("localPath %s  remotePath %s  \n", localPath, remotePath);

	// Delete from FTP server
	if(!m_ftpClient.IsConnected())
	{
		int retcode = 11;
		retcode = m_ftpClient.FTPConnect(con->host, con->user, con->password, _T(""));
		if(retcode == UTE_SUCCESS)
		{
			
		}
	}
	m_ftpClient.SetFireWallMode(TRUE);
	int r = m_ftpClient.DeleteFileW(remotePath);
	if(r == UTE_SUCCESS)
	{
		result = true;
	}

	// Delete from local disk
	CFile::Remove(localPath);

	// Reload dir listing info from server
	GetFtpDirectory(con, file.path);

	return result;
}
QVariant FolderStatusModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    if (role == Qt::EditRole)
        return QVariant();

    switch(classify(index)) {
    case AddButton: {
        if (role == FolderStatusDelegate::AddButton) {
            return QVariant(true);
        } else if (role == Qt::ToolTipRole) {
            if (!_accountState->isConnected()) {
                return tr("You need to be connected to add a folder");
            } if (_folders.count() == 1) {
                auto remotePath = _folders.at(0)._folder->remotePath();
                if (remotePath.isEmpty() || remotePath == QLatin1String("/")) {
                    // Syncing the entire owncloud: disable the add folder button (#3438)
                    return tr("Adding folder is disabled because you are already syncing all your files. "
                            "If you want to sync multiple folders, please remove the currently "
                            "configured root folder.");
                }
            }
            return tr("Click this button to add a folder to synchronize.");
        }
        return QVariant();
    }
    case SubFolder:
    {
        const auto &x = static_cast<SubFolderInfo *>(index.internalPointer())->_subs[index.row()];
        switch (role) {
        case Qt::ToolTipRole:
        case Qt::DisplayRole:
            return tr("%1 (%2)").arg(x._name, Utility::octetsToString(x._size));
        case Qt::CheckStateRole:
            return x._checked;
        case Qt::DecorationRole:
            return QFileIconProvider().icon(QFileIconProvider::Folder);
        case Qt::ForegroundRole:
            if (x._isUndecided) {
                return QColor(Qt::red);
            }
            break;
        }
    }
        return QVariant();
    case FetchLabel:
    {
        const auto x = static_cast<SubFolderInfo *>(index.internalPointer());
        switch(role) {
            case Qt::DisplayRole:
                if (x->_hasError) {
                    return tr("Error while loading the list of folders from the server.");
                } else {
                    return tr("Fetching folder list from server...");
                }
                break;
            default: return QVariant();
        }
    }
    case RootFolder:
        break;
    }

    const SubFolderInfo & folderInfo = _folders.at(index.row());
    auto f = folderInfo._folder;
    if (!f)
        return QVariant();

    const SubFolderInfo::Progress & progress = folderInfo._progress;
    const bool accountConnected = _accountState->isConnected();

    switch (role) {
    case FolderStatusDelegate::FolderPathRole         : return  f->shortGuiPath();
    case FolderStatusDelegate::FolderSecondPathRole   : return  f->remotePath();
    case FolderStatusDelegate::HeaderRole             : return  f->aliasGui();
    case FolderStatusDelegate::FolderAliasRole        : return  f->alias();
    case FolderStatusDelegate::FolderSyncPaused       : return  f->syncPaused();
    case FolderStatusDelegate::FolderAccountConnected : return  accountConnected;
    case Qt::ToolTipRole:
        if ( accountConnected )
            return Theme::instance()->statusHeaderText(f->syncResult().status());
        else
            return tr("Signed out");
    case FolderStatusDelegate::FolderStatusIconRole:
        if ( accountConnected ) {
            auto theme = Theme::instance();
            auto status = f->syncResult().status();
            if( f->syncPaused() ) {
                return theme->folderDisabledIcon( );
            } else {
                if( status == SyncResult::SyncPrepare ) {
                    return theme->syncStateIcon(SyncResult::SyncRunning);
                } else if( status == SyncResult::Undefined ) {
                    return theme->syncStateIcon( SyncResult::SyncRunning);
                } else {
                    // keep the previous icon for the prepare phase.
                    if( status == SyncResult::Problem) {
                        return theme->syncStateIcon( SyncResult::Success);
                    } else {
                        return theme->syncStateIcon( status );
                    }
                }
            }
        } else {
            return Theme::instance()->folderOfflineIcon();
        }
    case FolderStatusDelegate::SyncProgressItemString:
        return progress._progressString;
    case FolderStatusDelegate::WarningCount:
        return progress._warningCount;
    case FolderStatusDelegate::SyncProgressOverallPercent:
        return progress._overallPercent;
    case FolderStatusDelegate::SyncProgressOverallString:
        return progress._overallSyncString;
    }
    return QVariant();
}
Beispiel #11
0
void Folder::startSync(const QStringList &pathList)
{
    Q_ASSERT(_accountState);

    Q_UNUSED(pathList)
    if (!_csync_ctx) {
        // no _csync_ctx yet,  initialize it.
        init();

        if (!_csync_ctx) {
            qDebug() << Q_FUNC_INFO << "init failed.";
            // the error should already be set
            QMetaObject::invokeMethod(this, "slotSyncFinished", Qt::QueuedConnection);
            return;
        }
    } else if (proxyDirty()) {
        setProxyDirty(false);
    }
    csync_set_log_level( Logger::instance()->isNoop() ? 0 : 11 );

    if (isBusy()) {
        qCritical() << "* ERROR csync is still running and new sync requested.";
        return;
    }
    _errors.clear();
    _csyncError = false;
    _csyncUnavail = false;

    _timeSinceLastSyncStart.restart();
    _syncResult.clearErrors();
    _syncResult.setStatus( SyncResult::SyncPrepare );
    _syncResult.setSyncFileItemVector(SyncFileItemVector());
    emit syncStateChange();

    qDebug() << "*** Start syncing " << alias() << " - client version"
             << qPrintable(Theme::instance()->version());

    if (! setIgnoredFiles())
    {
        slotSyncError(tr("Could not read system exclude file"));
        QMetaObject::invokeMethod(this, "slotSyncFinished", Qt::QueuedConnection);
        return;
    }

    // pass the setting if hidden files are to be ignored, will be read in csync_update
    _csync_ctx->ignore_hidden_files = _definition.ignoreHiddenFiles;

    _engine.reset(new SyncEngine( _accountState->account(), _csync_ctx, path(), remoteUrl().path(), remotePath(), &_journal));

    qRegisterMetaType<SyncFileItemVector>("SyncFileItemVector");
    qRegisterMetaType<SyncFileItem::Direction>("SyncFileItem::Direction");

    connect(_engine.data(), SIGNAL(rootEtag(QString)), this, SLOT(etagRetreivedFromSyncEngine(QString)));
    connect( _engine.data(), SIGNAL(treeWalkResult(const SyncFileItemVector&)),
              this, SLOT(slotThreadTreeWalkResult(const SyncFileItemVector&)), Qt::QueuedConnection);
    connect( _engine.data(), SIGNAL(aboutToPropagate(SyncFileItemVector&)),
              this, SLOT(slotAboutToPropagate(SyncFileItemVector&)));

    connect(_engine.data(), SIGNAL(started()),  SLOT(slotSyncStarted()), Qt::QueuedConnection);
    connect(_engine.data(), SIGNAL(finished(bool)), SLOT(slotSyncFinished(bool)), Qt::QueuedConnection);
    connect(_engine.data(), SIGNAL(csyncError(QString)), SLOT(slotSyncError(QString)), Qt::QueuedConnection);
    connect(_engine.data(), SIGNAL(csyncUnavailable()), SLOT(slotCsyncUnavailable()), Qt::QueuedConnection);

    //direct connection so the message box is blocking the sync.
    connect(_engine.data(), SIGNAL(aboutToRemoveAllFiles(SyncFileItem::Direction,bool*)),
                    SLOT(slotAboutToRemoveAllFiles(SyncFileItem::Direction,bool*)));
    connect(_engine.data(), SIGNAL(folderDiscovered(bool,QString)), this, SLOT(slotFolderDiscovered(bool,QString)));
    connect(_engine.data(), SIGNAL(transmissionProgress(ProgressInfo)), this, SLOT(slotTransmissionProgress(ProgressInfo)));
    connect(_engine.data(), SIGNAL(itemCompleted(const SyncFileItem &, const PropagatorJob &)),
            this, SLOT(slotItemCompleted(const SyncFileItem &, const PropagatorJob &)));
    connect(_engine.data(), SIGNAL(syncItemDiscovered(const SyncFileItem &)), this, SLOT(slotSyncItemDiscovered(const SyncFileItem &)));
    connect(_engine.data(), SIGNAL(newBigFolder(QString)), this, SLOT(slotNewBigFolderDiscovered(QString)));

    setDirtyNetworkLimits();

    ConfigFile cfgFile;
    auto newFolderLimit = cfgFile.newBigFolderSizeLimit();
    quint64 limit = newFolderLimit.first ? newFolderLimit.second * 1000 * 1000 : -1; // convert from MB to B
    _engine->setNewBigFolderSizeLimit(limit);

    QMetaObject::invokeMethod(_engine.data(), "startSync", Qt::QueuedConnection);

    // disable events until syncing is done
    // _watcher->setEventsEnabled(false);
    emit syncStarted();
}
Beispiel #12
0
QUrl Folder::remoteUrl() const
{
    Q_ASSERT(_accountState);
    return Account::concatUrlPath(_accountState->account()->davUrl(), remotePath());
}
Beispiel #13
0
void Folder::slotPollTimerTimeout()
{
    qDebug() << "* Polling" << alias() << "for changes. (time since last sync:" << (_timeSinceLastSync.elapsed() / 1000) << "s)";

    if (quint64(_timeSinceLastSync.elapsed()) > MirallConfigFile().forceSyncInterval() ||
            !(_syncResult.status() == SyncResult::Success ||_syncResult.status() == SyncResult::Problem)) {
        qDebug() << "** Force Sync now, state is " << _syncResult.statusString();
        emit scheduleToSync(alias());
    } else {
        RequestEtagJob* job = new RequestEtagJob(AccountManager::instance()->account(), remotePath(), this);
        // check if the etag is different
        QObject::connect(job, SIGNAL(etagRetreived(QString)), this, SLOT(etagRetreived(QString)));
        QObject::connect(job, SIGNAL(networkError(QNetworkReply*)), this, SLOT(slotNetworkUnavailable()));
        job->start();
    }
}
Beispiel #14
0
QVariant FolderStatusModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    if (role == Qt::EditRole)
        return QVariant();

    switch (classify(index)) {
    case AddButton: {
        if (role == FolderStatusDelegate::AddButton) {
            return QVariant(true);
        } else if (role == Qt::ToolTipRole) {
            if (!_accountState->isConnected()) {
                return tr("You need to be connected to add a folder");
            }
            return tr("Click this button to add a folder to synchronize.");
        }
        return QVariant();
    }
    case SubFolder: {
        const auto &x = static_cast<SubFolderInfo *>(index.internalPointer())->_subs[index.row()];
        switch (role) {
        case Qt::DisplayRole:
            //: Example text: "File.txt (23KB)"
            return x._size < 0 ? x._name : tr("%1 (%2)").arg(x._name, Utility::octetsToString(x._size));
        case Qt::ToolTipRole:
            return QString(QLatin1String("<qt>") + Utility::escape(x._size < 0 ? x._name : tr("%1 (%2)").arg(x._name, Utility::octetsToString(x._size))) + QLatin1String("</qt>"));
        case Qt::CheckStateRole:
            return x._checked;
        case Qt::DecorationRole:
            return QFileIconProvider().icon(x._isExternal ? QFileIconProvider::Network : QFileIconProvider::Folder);
        case Qt::ForegroundRole:
            if (x._isUndecided) {
                return QColor(Qt::red);
            }
            break;
        case FolderStatusDelegate::FolderPathRole: {
            auto f = x._folder;
            if (!f)
                return QVariant();
            return QVariant(f->path() + x._path);
        }
        }
    }
        return QVariant();
    case FetchLabel: {
        const auto x = static_cast<SubFolderInfo *>(index.internalPointer());
        switch (role) {
        case Qt::DisplayRole:
            if (x->_hasError) {
                return QVariant(tr("Error while loading the list of folders from the server.")
                    + QString("\n") + x->_lastErrorString);
            } else {
                return tr("Fetching folder list from server...");
            }
            break;
        default:
            return QVariant();
        }
    }
    case RootFolder:
        break;
    }

    const SubFolderInfo &folderInfo = _folders.at(index.row());
    auto f = folderInfo._folder;
    if (!f)
        return QVariant();

    const SubFolderInfo::Progress &progress = folderInfo._progress;
    const bool accountConnected = _accountState->isConnected();

    switch (role) {
    case FolderStatusDelegate::FolderPathRole:
        return f->shortGuiLocalPath();
    case FolderStatusDelegate::FolderSecondPathRole:
        return f->remotePath();
    case FolderStatusDelegate::FolderConflictMsg:
        return (f->syncResult().hasUnresolvedConflicts())
            ? QStringList(tr("There are unresolved conflicts. Click for details."))
            : QStringList();
    case FolderStatusDelegate::FolderErrorMsg:
        return f->syncResult().errorStrings();
    case FolderStatusDelegate::FolderInfoMsg:
        return f->useVirtualFiles()
            ? QStringList(tr("New files are being created as virtual files."))
            : QStringList();
    case FolderStatusDelegate::SyncRunning:
        return f->syncResult().status() == SyncResult::SyncRunning;
    case FolderStatusDelegate::HeaderRole:
        return f->shortGuiRemotePathOrAppName();
    case FolderStatusDelegate::FolderAliasRole:
        return f->alias();
    case FolderStatusDelegate::FolderSyncPaused:
        return f->syncPaused();
    case FolderStatusDelegate::FolderAccountConnected:
        return accountConnected;
    case Qt::ToolTipRole: {
        QString toolTip;
        if (!progress.isNull()) {
            return progress._progressString;
        }
        if (accountConnected)
            toolTip = Theme::instance()->statusHeaderText(f->syncResult().status());
        else
            toolTip = tr("Signed out");
        toolTip += "\n";
        toolTip += folderInfo._folder->path();
        return toolTip;
    }
    case FolderStatusDelegate::FolderStatusIconRole:
        if (accountConnected) {
            auto theme = Theme::instance();
            auto status = f->syncResult().status();
            if (f->syncPaused()) {
                return theme->folderDisabledIcon();
            } else {
                if (status == SyncResult::SyncPrepare) {
                    return theme->syncStateIcon(SyncResult::SyncRunning);
                } else if (status == SyncResult::Undefined) {
                    return theme->syncStateIcon(SyncResult::SyncRunning);
                } else {
                    // The "Problem" *result* just means some files weren't
                    // synced, so we show "Success" in these cases. But we
                    // do use the "Problem" *icon* for unresolved conflicts.
                    if (status == SyncResult::Success || status == SyncResult::Problem) {
                        if (f->syncResult().hasUnresolvedConflicts()) {
                            return theme->syncStateIcon(SyncResult::Problem);
                        } else {
                            return theme->syncStateIcon(SyncResult::Success);
                        }
                    } else {
                        return theme->syncStateIcon(status);
                    }
                }
            }
        } else {
            return Theme::instance()->folderOfflineIcon();
        }
    case FolderStatusDelegate::SyncProgressItemString:
        return progress._progressString;
    case FolderStatusDelegate::WarningCount:
        return progress._warningCount;
    case FolderStatusDelegate::SyncProgressOverallPercent:
        return progress._overallPercent;
    case FolderStatusDelegate::SyncProgressOverallString:
        return progress._overallSyncString;
    }
    return QVariant();
}