Browse Source

Merges errors and protocols into notifications/activities.

- Errors will always be on top, then Notifications comes next and then Activities for last.
- Adds 2 new types of Activity: NotificationType and ErrorType.
- ActivityListModel and ActivityWidget stores AccountState to connect user and widget.

Signed-off-by: Camila San <hello@camila.codes>
Camila San 7 years ago
parent
commit
a9cd3b3a6d

+ 2 - 0
client.qrc

@@ -24,6 +24,8 @@
         <file>resources/delete.png</file>
         <file>resources/close.svg</file>
         <file>resources/bell.svg</file>
+        <file>resources/link.svg</file>
+        <file>resources/files.svg</file>
     </qresource>
     <qresource prefix="/"/>
 </RCC>

+ 1 - 0
resources/files.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1"><path d="M1.457 1.997c-.25 0-.46.21-.46.46v11.08c0 .26.202.46.46.46h13.08c.258 0 .46-.2.46-.46V4.46c0-.25-.21-.463-.46-.463h-6.54l-2-2z" /></svg>

File diff suppressed because it is too large
+ 0 - 0
resources/link.svg


+ 3 - 1
src/gui/activitydata.h

@@ -49,7 +49,8 @@ public:
 
     enum Type {
         ActivityType,
-        NotificationType
+        NotificationType,
+        ErrorType
     };
 
     Type _type;
@@ -60,6 +61,7 @@ public:
     QUrl _link;
     QDateTime _dateTime;
     QString _accName;
+    int _status;
 
     QVector<ActivityLink> _links;
     /**

+ 40 - 2
src/gui/activityitemdelegate.cpp

@@ -159,6 +159,43 @@ void ActivityItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
         primaryButton.features |= QStyleOptionButton::DefaultButton;
         primaryButton.state |= QStyle::State_Raised;
 
+        // save info to be able to filter mouse clicks
+        _buttonHeight = buttonSize;
+        _spaceBetweenButtons = leftMargin;
+        _primaryButtonWidth = primaryButton.rect.size().width();
+        _secondaryButtonWidth = secondaryButton.rect.size().width();
+    } else if(activityType == Activity::Type::ErrorType){
+        int rightMargin = margin;
+        int leftMargin = margin * offset;
+        int top = option.rect.top() + margin - offset;
+        int buttonSize = option.rect.height()/2.5;
+
+        // Secondary will be 'Dismiss' or '...'
+        secondaryButton.rect = option.rect;
+        secondaryButton.icon = QIcon(QLatin1String(":/client/resources/files.svg"));
+
+        int right = option.rect.right() - rightMargin;
+        int left = right - buttonSize;
+        secondaryButton.iconSize = QSize(buttonSize, buttonSize);
+        secondaryButton.rect.setLeft(left);
+        secondaryButton.rect.setRight(right);
+        secondaryButton.rect.setTop(top);
+        secondaryButton.rect.setHeight(_buttonHeight);
+        secondaryButton.features |= QStyleOptionButton::DefaultButton;
+        secondaryButton.state |= QStyle::State_Raised;
+
+        // Primary button will be 'More Information'
+        primaryButton.rect = option.rect;
+        primaryButton.text = tr("Open Browser");
+        right = secondaryButton.rect.left() - rightMargin;
+        left = secondaryButton.rect.left() - leftMargin;
+        primaryButton.rect.setLeft(left - fm.width(primaryButton.text));
+        primaryButton.rect.setRight(right);
+        primaryButton.rect.setTop(top);
+        primaryButton.rect.setHeight(_buttonHeight);
+        primaryButton.features |= QStyleOptionButton::DefaultButton;
+        primaryButton.state |= QStyle::State_Raised;
+
         // save info to be able to filter mouse clicks
         _buttonHeight = buttonSize;
         _spaceBetweenButtons = leftMargin;
@@ -200,7 +237,7 @@ void ActivityItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
     painter->drawText(actionTextBox, elidedAction);
 
     // draw the buttons
-    if(activityType == Activity::Type::NotificationType){
+    if(activityType == Activity::Type::NotificationType || activityType == Activity::Type::ErrorType){
         QApplication::style()->drawControl(QStyle::CE_PushButton, &primaryButton, painter);
         QApplication::style()->drawControl(QStyle::CE_PushButton, &secondaryButton, painter);
     }
@@ -235,7 +272,8 @@ void ActivityItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
 bool ActivityItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
     const QStyleOptionViewItem &option, const QModelIndex &index)
 {
-    if(qvariant_cast<Activity::Type>(index.data(ActionRole)) == Activity::Type::NotificationType){
+    if(qvariant_cast<Activity::Type>(index.data(ActionRole)) == Activity::Type::NotificationType
+            || qvariant_cast<Activity::Type>(index.data(ActionRole)) == Activity::Type::ErrorType){
         if (event->type() == QEvent::MouseButtonRelease){
             QMouseEvent *mouseEvent = (QMouseEvent*)event;
             if(mouseEvent){

+ 23 - 4
src/gui/activitylistmodel.cpp

@@ -29,6 +29,8 @@
 #include "activitydata.h"
 #include "activitylistmodel.h"
 
+#include "theme.h"
+
 #include "servernotificationhandler.h"
 
 namespace OCC {
@@ -83,15 +85,24 @@ QVariant ActivityListModel::data(const QModelIndex &index, int role) const
         return customList;
         break;
     }
-//    case ActivityItemDelegate::UserIconRole:
-//        return QIcon(QLatin1String(":/client/resources/account.png"));
-//        break;
     case ActivityItemDelegate::ActionIconRole:
         if(a._type == Activity::NotificationType){
            QIcon cachedIcon = ServerNotificationHandler::iconCache.value(a._id);
            if(!cachedIcon.isNull())
                return cachedIcon;
            else return QIcon(QLatin1String(":/client/resources/bell.svg"));
+        } else if(a._type == Activity::ErrorType){
+               if(a._status == SyncFileItem::NormalError
+                   || a._status == SyncFileItem::FatalError
+                   || a._status == SyncFileItem::DetailError
+                   || a._status == SyncFileItem::BlacklistedError) {
+                   return Theme::instance()->syncStateIcon(SyncResult::Error);
+               } else if(a._status == SyncFileItem::SoftError
+                         || a._status == SyncFileItem::FileIgnored
+                         || a._status == SyncFileItem::Conflict
+                         || a._status == SyncFileItem::Restoration){
+                   return Theme::instance()->syncStateIcon(SyncResult::Problem);
+               }
         } else return QIcon(QLatin1String(":/client/resources/activity.png"));
         return QVariant();
         break;
@@ -204,7 +215,12 @@ void ActivityListModel::slotActivitiesReceived(const QJsonDocument &json, int st
     combineActivityLists();
 }
 
-void ActivityListModel::addToActivityList(Activity activity) {
+void ActivityListModel::addErrorToActivityList(Activity activity) {
+    _notificationErrorsLists.prepend(activity);
+    combineActivityLists();
+}
+
+void ActivityListModel::addNotificationToActivityList(Activity activity) {
     _notificationLists.prepend(activity);
     combineActivityLists();
 }
@@ -219,6 +235,9 @@ void ActivityListModel::combineActivityLists()
 {
     ActivityList resultList;
 
+    std::sort(_notificationErrorsLists.begin(), _notificationErrorsLists.end());
+    resultList.append(_notificationErrorsLists);
+
     std::sort(_notificationLists.begin(), _notificationLists.end());
     resultList.append(_notificationLists);
 

+ 3 - 1
src/gui/activitylistmodel.h

@@ -47,7 +47,8 @@ public:
     void fetchMore(const QModelIndex &) Q_DECL_OVERRIDE;
 
     ActivityList activityList() { return _finalList; }
-    void addToActivityList(Activity activity);
+    void addNotificationToActivityList(Activity activity);
+    void addErrorToActivityList(Activity activity);
     void removeFromActivityList(int row);
 
 public slots:
@@ -66,6 +67,7 @@ private:
 
     ActivityList _activityLists;
     ActivityList _notificationLists;
+    ActivityList _notificationErrorsLists;
     ActivityList _finalList;
     AccountState *_accountState;
     bool _currentlyFetching = true;

+ 107 - 18
src/gui/activitywidget.cpp

@@ -95,11 +95,17 @@ ActivityWidget::ActivityWidget(AccountState *accountState, QWidget *parent)
 
     connect(delegate, &ActivityItemDelegate::primaryButtonClickedOnItemView, this, &ActivityWidget::slotPrimaryButtonClickedOnListView);
     connect(delegate, &ActivityItemDelegate::secondaryButtonClickedOnItemView, this, &ActivityWidget::slotSecondaryButtonClickedOnListView);
-    //connect(this, &ActivityWidget::sendNotificationRequest, this, &ActivityWidget::slotSendNotificationRequest);
 
     connect(_ui->_activityList, &QListView::activated, this, &ActivityWidget::slotOpenFile);
-
     connect(&_removeTimer, &QTimer::timeout, this, &ActivityWidget::slotCheckToCleanWidgets);
+
+    connect(ProgressDispatcher::instance(), &ProgressDispatcher::progressInfo,
+        this, &ActivityWidget::slotProgressInfo);
+    connect(ProgressDispatcher::instance(), &ProgressDispatcher::itemCompleted,
+        this, &ActivityWidget::slotItemCompleted);
+    connect(ProgressDispatcher::instance(), &ProgressDispatcher::syncError,
+        this, &ActivityWidget::addError);
+
     _removeTimer.setInterval(1000);
 }
 
@@ -108,6 +114,75 @@ ActivityWidget::~ActivityWidget()
     delete _ui;
 }
 
+void ActivityWidget::slotProgressInfo(const QString &folder, const ProgressInfo &progress)
+{
+    if (progress.status() == ProgressInfo::Starting) {
+        // The sync is restarting, clean the old items
+        //cleanItems(folder);
+    }
+}
+
+void ActivityWidget::slotItemCompleted(const QString &folder, const SyncFileItemPtr &item){
+    auto folderInstance = FolderMan::instance()->folder(folder);
+    if (!folderInstance)
+        return;
+
+    // check if we are adding it to the right account and if it is useful information (error)
+    if(folderInstance->accountState() == _accountState){
+        Activity activity;
+        activity._type = Activity::ErrorType;
+        activity._dateTime = QDateTime::fromString(QDateTime::currentDateTime().toString(), Qt::ISODate);
+        activity._subject = item->_errorString;
+        qDebug() << "TOTAL " << folder;
+        activity._message = item->_originalFile;
+        activity._link = folderInstance->remotePath();
+        activity._status = item->_status;
+        activity._accName = folderInstance->accountState()->account()->displayName();
+        activity._file = item->_file;
+
+        ActivityLink al;
+        al._label = tr("Open Folder");
+        al._link = folderInstance->path();
+        al._verb = "";
+        al._isPrimary = true;
+        activity._links.append(al);
+
+        _model->addErrorToActivityList(activity);
+        // add error widget
+    }
+}
+
+void ActivityWidget::addError(const QString &folderAlias, const QString &message,
+    ErrorCategory category)
+{
+    auto folderInstance = FolderMan::instance()->folder(folderAlias);
+    if (!folderInstance)
+        return;
+
+    if(folderInstance->accountState() == _accountState){
+        Activity activity;
+        activity._type = Activity::ErrorType;
+        activity._dateTime = QDateTime::fromString(QDateTime::currentDateTime().toString(), Qt::ISODate);
+        activity._subject = message;
+        activity._message = folderInstance->shortGuiLocalPath();
+        activity._link = folderInstance->shortGuiLocalPath();
+        activity._status = SyncResult::Error;
+        activity._accName = folderInstance->accountState()->account()->displayName();
+
+        if (category == ErrorCategory::InsufficientRemoteStorage) {
+            ActivityLink link;
+            link._label = tr("Retry all uploads");
+            link._link = folderInstance->path();
+            link._verb = "";
+            link._isPrimary = true;
+            activity._links.append(link);
+        }
+
+        _model->addErrorToActivityList(activity);
+    }
+}
+
+
 void ActivityWidget::slotPrimaryButtonClickedOnListView(const QModelIndex &index){
     QUrl link = qvariant_cast<QString>(index.data(ActivityItemDelegate::LinkRole));
     if(!link.isEmpty())
@@ -121,20 +196,32 @@ void ActivityWidget::slotSecondaryButtonClickedOnListView(const QModelIndex &ind
         actionLinks << qvariant_cast<ActivityLink>(customItem);
     }
 
-    const QString accountName = index.data(ActivityItemDelegate::AccountRole).toString();
-    if(actionLinks.size() == 1){
-        if(actionLinks.at(0)._verb == "DELETE")
-            slotSendNotificationRequest(index.data(ActivityItemDelegate::AccountRole).toString(), actionLinks.at(0)._link, actionLinks.at(0)._verb, index.row());
-    } else if(actionLinks.size() > 1){
-        QMenu menu;
-        foreach (ActivityLink actionLink, actionLinks) {
-            QAction *menuAction = new QAction(actionLink._label, &menu);
-            connect(menuAction, &QAction::triggered, this, [this, index, accountName, actionLink] {
-                this->slotSendNotificationRequest(accountName, actionLink._link, actionLink._verb, index.row());
-            });
-            menu.addAction(menuAction);
+    if(qvariant_cast<Activity::Type>(index.data(ActivityItemDelegate::ActionRole)) == Activity::Type::NotificationType){
+        const QString accountName = index.data(ActivityItemDelegate::AccountRole).toString();
+        if(actionLinks.size() == 1){
+            if(actionLinks.at(0)._verb == "DELETE")
+                slotSendNotificationRequest(index.data(ActivityItemDelegate::AccountRole).toString(), actionLinks.at(0)._link, actionLinks.at(0)._verb, index.row());
+        } else if(actionLinks.size() > 1){
+            QMenu menu;
+            foreach (ActivityLink actionLink, actionLinks) {
+                QAction *menuAction = new QAction(actionLink._label, &menu);
+                connect(menuAction, &QAction::triggered, this, [this, index, accountName, actionLink] {
+                    this->slotSendNotificationRequest(accountName, actionLink._link, actionLink._verb, index.row());
+                });
+                menu.addAction(menuAction);
+            }
+            menu.exec(QCursor::pos());
+        }
+    }
+
+    if(qvariant_cast<Activity::Type>(index.data(ActivityItemDelegate::ActionRole)) == Activity::Type::ErrorType){
+        QString fileName = index.data(ActivityItemDelegate::PathRole).toString();
+        if (Folder *folder = FolderMan::instance()->folderForPath(actionLinks.first()._link)) {
+            QString fullPath = folder->path() + fileName;
+            if (QFile(fullPath).exists()) {
+                showInFileManager(fullPath);
+            }
         }
-        menu.exec(QCursor::pos());
     }
 }
 
@@ -369,7 +456,7 @@ void ActivityWidget::slotBuildNotificationDisplay(const ActivityList &list)
                 }
             }
 
-            _model->addToActivityList(activity);
+            _model->addNotificationToActivityList(activity);
         }
     }
 
@@ -566,11 +653,13 @@ ActivitySettings::ActivitySettings(AccountState *accountState, QWidget *parent)
     connect(_activityWidget, &ActivityWidget::guiLog, this, &ActivitySettings::guiLog);
     connect(_activityWidget, &ActivityWidget::newNotification, this, &ActivitySettings::slotShowActivityTab);
 
-//    _protocolWidget = new ProtocolWidget(this);
+    _protocolWidget = new ProtocolWidget(this);
+    _vbox->addWidget(_protocolWidget);
 //    _protocolTabId = _tab->addTab(_protocolWidget, Theme::instance()->syncStateIcon(SyncResult::Success), tr("Sync Protocol"));
 //    connect(_protocolWidget, &ProtocolWidget::copyToClipboard, this, &ActivitySettings::slotCopyToClipboard);
 
-//    _issuesWidget = new IssuesWidget(this);
+    _issuesWidget = new IssuesWidget(this);
+    _vbox->addWidget(_issuesWidget);
 //    _syncIssueTabId = _tab->addTab(_issuesWidget, Theme::instance()->syncStateIcon(SyncResult::Problem), QString());
 //    slotShowIssueItemCount(0); // to display the label.
 //    connect(_issuesWidget, &IssuesWidget::issueCountUpdated,

+ 8 - 0
src/gui/activitywidget.h

@@ -79,6 +79,12 @@ public slots:
     void slotRemoveAccount();
     void slotAccountActivityStatus(int statusCode);
     void slotRequestCleanupAndBlacklist(const Activity &blacklistActivity);
+    //
+    void addError(const QString &folderAlias, const QString &message, ErrorCategory category);
+    void slotProgressInfo(const QString &folder, const ProgressInfo &progress);
+    void slotItemCompleted(const QString &folder, const SyncFileItemPtr &item);
+    //void slotOpenFile(QTreeWidgetItem *item, int);
+
 
 signals:
     void guiLog(const QString &, const QString &);
@@ -164,6 +170,8 @@ private:
     bool event(QEvent *e) Q_DECL_OVERRIDE;
 
     ActivityWidget *_activityWidget;
+    ProtocolWidget *_protocolWidget;
+    IssuesWidget *_issuesWidget;
     QProgressIndicator *_progressIndicator;
     QTimer _notificationCheckTimer;
     QHash<AccountState *, QElapsedTimer> _timeSinceLastCheck;

Some files were not shown because too many files changed in this diff