mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-23 13:35:58 +03:00
ActivityWidget: Do a proper asynchronous model to display the activity.
This commit is contained in:
parent
3b8e1dcd89
commit
4895683bab
2 changed files with 131 additions and 66 deletions
|
@ -52,11 +52,12 @@ QString ActivityList::accountName() const
|
|||
ActivityListModel::ActivityListModel(QWidget *parent)
|
||||
:QAbstractListModel(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QVariant ActivityListModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
Activity a;
|
||||
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
|
@ -65,10 +66,14 @@ QVariant ActivityListModel::data(const QModelIndex &index, int role) const
|
|||
|
||||
switch (role) {
|
||||
case Qt::ToolTipRole:
|
||||
return QVariant();
|
||||
case Qt::DisplayRole:
|
||||
return tr("%1 (%2)").arg("IM an item");
|
||||
a = _finalList.at(index.row());
|
||||
return tr("Account %1 at %2: %3").arg(a._accName).arg(a._dateTime.toString(Qt::SystemLocaleShortDate)).arg(a._subject);
|
||||
break;
|
||||
case Qt::DecorationRole:
|
||||
return QFileIconProvider().icon(QFileIconProvider::Folder);
|
||||
// return QFileIconProvider().icon(QFileIconProvider::Folder);
|
||||
return QVariant();
|
||||
break;
|
||||
}
|
||||
return QVariant();
|
||||
|
@ -77,19 +82,106 @@ QVariant ActivityListModel::data(const QModelIndex &index, int role) const
|
|||
|
||||
int ActivityListModel::rowCount(const QModelIndex&) const
|
||||
{
|
||||
int cnt = 0;
|
||||
foreach(ActivityList al, _activityLists) {
|
||||
cnt += al.count();
|
||||
}
|
||||
return cnt;
|
||||
return _finalList.count();
|
||||
}
|
||||
|
||||
void ActivityListModel::addActivities( const ActivityList& activities )
|
||||
// current strategy: Fetch 100 items per Account
|
||||
bool ActivityListModel::canFetchMore(const QModelIndex& ) const
|
||||
{
|
||||
bool found = false;
|
||||
if( _activityLists.count() == 0 ) return true;
|
||||
|
||||
// build up a time list here.
|
||||
QMap<AccountStatePtr, ActivityList>::const_iterator i = _activityLists.begin();
|
||||
while (i != _activityLists.end()) {
|
||||
if( i.value().count() == 0 &&
|
||||
! _currentlyFetching.contains(i.key())) {
|
||||
return true;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ActivityListModel::startFetchJob(AccountStatePtr s)
|
||||
{
|
||||
JsonApiJob *job = new JsonApiJob(s->account(), QLatin1String("ocs/v1.php/cloud/activity"), this);
|
||||
QObject::connect(job, SIGNAL(jsonRecieved(QVariantMap)), this, SLOT(slotActivitiesReceived(QVariantMap)));
|
||||
job->setProperty("AccountStatePtr", QVariant::fromValue<AccountStatePtr>(s));
|
||||
_currentlyFetching.insert(s);
|
||||
job->start();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ActivityListModel::slotActivitiesReceived(const QVariantMap& json)
|
||||
{
|
||||
auto activities = json.value("ocs").toMap().value("data").toList();
|
||||
qDebug() << "*** activities" << activities;
|
||||
|
||||
ActivityList list;
|
||||
AccountStatePtr ai = qvariant_cast<AccountStatePtr>(sender()->property("AccountStatePtr"));
|
||||
_currentlyFetching.remove(ai);
|
||||
list.setAccountName( ai->account()->displayName());
|
||||
foreach( auto activ, activities ) {
|
||||
auto json = activ.toMap();
|
||||
|
||||
Activity a;
|
||||
a._accName = ai->account()->displayName();
|
||||
a._id = json.value("id").toLongLong();
|
||||
a._subject = json.value("subject").toString();
|
||||
a._message = json.value("message").toString();
|
||||
a._file = json.value("file").toString();
|
||||
a._link = json.value("link").toUrl();
|
||||
a._dateTime = json.value("date").toDateTime();
|
||||
list.append(a);
|
||||
}
|
||||
|
||||
_activityLists[ai] = list;
|
||||
|
||||
// if all activity lists were received, assemble the whole list
|
||||
bool allAreHere = true;
|
||||
foreach( ActivityList list, _activityLists.values() ) {
|
||||
if( list.count() == 0 ) {
|
||||
allAreHere = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( allAreHere ) {
|
||||
combineActivityLists();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ActivityListModel::combineActivityLists()
|
||||
{
|
||||
ActivityList resultList;
|
||||
|
||||
foreach( ActivityList list, _activityLists.values() ) {
|
||||
resultList.append(list);
|
||||
}
|
||||
|
||||
std::sort( resultList.begin(), resultList.end() );
|
||||
|
||||
beginInsertRows(QModelIndex(), 0, resultList.count()-1);
|
||||
_finalList = resultList;
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void ActivityListModel::fetchMore(const QModelIndex &)
|
||||
{
|
||||
QList<AccountStatePtr> accounts = AccountManager::instance()->accounts();
|
||||
|
||||
foreach (AccountStatePtr asp, accounts) {
|
||||
|
||||
// if the account is not yet managed, add an empty list.
|
||||
if( !_activityLists.contains(asp) ) {
|
||||
_activityLists[asp] = ActivityList();
|
||||
}
|
||||
ActivityList activities = _activityLists[asp];
|
||||
if( activities.count() == 0 ) {
|
||||
startFetchJob(asp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================================================================== */
|
||||
|
@ -112,54 +204,8 @@ ActivityWidget::ActivityWidget(QWidget *parent) :
|
|||
_copyBtn->setToolTip( tr("Copy the activity list to the clipboard."));
|
||||
_copyBtn->setEnabled(false);
|
||||
connect(_copyBtn, SIGNAL(clicked()), SLOT(copyToClipboard()));
|
||||
|
||||
connect( &_timer, SIGNAL(timeout()), this, SLOT(slotRefresh()));
|
||||
|
||||
_timer.start(10000);
|
||||
}
|
||||
|
||||
void ActivityWidget::slotRefresh()
|
||||
{
|
||||
foreach (auto ai , AccountManager::instance()->accounts()) {
|
||||
if( ai->isConnected() ) {
|
||||
slotAddAccount(ai);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ActivityWidget::slotAddAccount( AccountStatePtr s )
|
||||
{
|
||||
if( s && s->state() == AccountState::Connected ) {
|
||||
// start a new fetch job for this account
|
||||
|
||||
JsonApiJob *job = new JsonApiJob(s->account(), QLatin1String("ocs/v1.php/cloud/activity"), this);
|
||||
QObject::connect(job, SIGNAL(jsonRecieved(QVariantMap)), this, SLOT(slotActivitiesReceived(QVariantMap)));
|
||||
job->setProperty("AccountStatePtr", QVariant::fromValue<AccountStatePtr>(s));
|
||||
job->start();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void ActivityWidget::slotActivitiesReceived(const QVariantMap& json)
|
||||
{
|
||||
auto activities = json.value("ocs").toMap().value("data").toList();
|
||||
qDebug() << "*** activities" << activities;
|
||||
|
||||
ActivityList list;
|
||||
AccountStatePtr ai = qvariant_cast<AccountStatePtr>(sender()->property("AccountStatePtr"));
|
||||
|
||||
list.setAccountName( ai->account()->displayName());
|
||||
foreach( auto activ, activities ) {
|
||||
Activity a;
|
||||
a._id = activ.toMap().value("id").toLongLong();
|
||||
a._subject = activ.toMap().value("subject").toString();
|
||||
list.append(a);
|
||||
}
|
||||
|
||||
_model->addActivities(list);
|
||||
}
|
||||
|
||||
|
||||
ActivityWidget::~ActivityWidget()
|
||||
{
|
||||
delete _ui;
|
||||
|
|
|
@ -50,6 +50,17 @@ public:
|
|||
QString _file;
|
||||
QUrl _link;
|
||||
QDateTime _dateTime;
|
||||
QString _accName;
|
||||
|
||||
/**
|
||||
* @brief Sort operator to sort the list youngest first.
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
bool operator<( const Activity& val ) const {
|
||||
return _dateTime.toMSecsSinceEpoch() > val._dateTime.toMSecsSinceEpoch();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class ActivityList:public QList<Activity>
|
||||
|
@ -63,6 +74,8 @@ private:
|
|||
QString _accountName;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class ActivityListModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -72,10 +85,19 @@ public:
|
|||
QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE;
|
||||
|
||||
void addActivities( const ActivityList& activities );
|
||||
private:
|
||||
bool canFetchMore(const QModelIndex& ) const;
|
||||
void fetchMore(const QModelIndex&);
|
||||
|
||||
QMap<QString, ActivityList> _activityLists;
|
||||
private slots:
|
||||
void slotActivitiesReceived(const QVariantMap& json);
|
||||
|
||||
private:
|
||||
void startFetchJob(AccountStatePtr s);
|
||||
void combineActivityLists();
|
||||
|
||||
QMap<AccountStatePtr, ActivityList> _activityLists;
|
||||
ActivityList _finalList;
|
||||
QSet<AccountStatePtr> _currentlyFetching;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -90,16 +112,14 @@ public:
|
|||
~ActivityWidget();
|
||||
QSize sizeHint() const { return ownCloudGui::settingsDialogSize(); }
|
||||
|
||||
// FIXME: Move the tab widget to its own widget that is used in settingsdialog.
|
||||
QTabWidget *tabWidget() { return _ui->_tabWidget; }
|
||||
|
||||
public slots:
|
||||
void slotAddAccount( AccountStatePtr s );
|
||||
void slotOpenFile();
|
||||
|
||||
protected slots:
|
||||
void copyToClipboard();
|
||||
void slotRefresh();
|
||||
|
||||
private slots:
|
||||
void slotActivitiesReceived(const QVariantMap& json);
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -110,7 +130,6 @@ private:
|
|||
QString timeString(QDateTime dt, QLocale::FormatType format) const;
|
||||
Ui::ActivityWidget *_ui;
|
||||
QPushButton *_copyBtn;
|
||||
QTimer _timer;
|
||||
|
||||
ActivityListModel *_model;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue