diff --git a/src/gui/sharemanager.cpp b/src/gui/sharemanager.cpp index 9c84822509..2401305b4b 100644 --- a/src/gui/sharemanager.cpp +++ b/src/gui/sharemanager.cpp @@ -23,6 +23,8 @@ #include #include +Q_LOGGING_CATEGORY(lcUserGroupShare, "nextcloud.gui.usergroupshare", QtInfoMsg) + namespace OCC { /** @@ -278,6 +280,72 @@ void LinkShare::slotNameSet(const QJsonDocument &, const QVariant &value) emit nameSet(); } +UserGroupShare::UserGroupShare(AccountPtr account, + const QString &id, + const QString &owner, + const QString &ownerDisplayName, + const QString &path, + const ShareType shareType, + const Permissions permissions, + const QSharedPointer shareWith, + const QDate &expireDate, + const QString ¬e) + : Share(account, id, owner, ownerDisplayName, path, shareType, permissions, shareWith) + , _expireDate(expireDate) + , _note(note) +{ + Q_ASSERT(shareType == TypeUser || shareType == TypeGroup); + Q_ASSERT(shareWith); +} + +void UserGroupShare::setNote(const QString ¬e) +{ + auto *job = new OcsShareJob(_account); + connect(job, &OcsShareJob::shareJobFinished, this, &UserGroupShare::slotNoteSet); + connect(job, &OcsJob::ocsError, this, &UserGroupShare::slotOcsError); + job->setNote(getId(), note); +} + +QString UserGroupShare::getNote() const +{ + return _note; +} + +void UserGroupShare::slotNoteSet(const QJsonDocument &, const QVariant ¬e) +{ + _note = note.toString(); + emit noteSet(); +} + +QDate UserGroupShare::getExpireDate() const +{ + return _expireDate; +} + +void UserGroupShare::setExpireDate(const QDate &date) +{ + auto *job = new OcsShareJob(_account); + connect(job, &OcsShareJob::shareJobFinished, this, &UserGroupShare::slotExpireDateSet); + connect(job, &OcsJob::ocsError, this, &UserGroupShare::slotOcsError); + job->setExpireDate(getId(), date); +} + +void UserGroupShare::slotExpireDateSet(const QJsonDocument &reply, const QVariant &value) +{ + auto data = reply.object().value("ocs").toObject().value("data").toObject(); + + /* + * If the reply provides a data back (more REST style) + * they use this date. + */ + if (data.value("expiration").isString()) { + _expireDate = QDate::fromString(data.value("expiration").toString(), "yyyy-MM-dd 00:00:00"); + } else { + _expireDate = value.toDate(); + } + emit expireDateSet(); +} + ShareManager::ShareManager(AccountPtr account, QObject *parent) : QObject(parent) , _account(account) @@ -390,6 +458,8 @@ void ShareManager::slotSharesFetched(const QJsonDocument &reply) if (shareType == Share::TypeLink) { newShare = parseLinkShare(data); + } else if (shareType == Share::TypeGroup || shareType == Share::TypeUser) { + newShare = parseUserGroupShare(data); } else { newShare = parseShare(data); } @@ -401,6 +471,34 @@ void ShareManager::slotSharesFetched(const QJsonDocument &reply) emit sharesFetched(shares); } +QSharedPointer ShareManager::parseUserGroupShare(const QJsonObject &data) +{ + QSharedPointer sharee(new Sharee(data.value("share_with").toString(), + data.value("share_with_displayname").toString(), + static_cast(data.value("share_type").toInt()))); + + QDate expireDate; + if (data.value("expiration").isString()) { + expireDate = QDate::fromString(data.value("expiration").toString(), "yyyy-MM-dd 00:00:00"); + } + + QString note; + if (data.value("note").isString()) { + note = data.value("note").toString(); + } + + return QSharedPointer(new UserGroupShare(_account, + data.value("id").toVariant().toString(), // "id" used to be an integer, support both + data.value("uid_owner").toVariant().toString(), + data.value("displayname_owner").toVariant().toString(), + data.value("path").toString(), + static_cast(data.value("share_type").toInt()), + static_cast(data.value("permissions").toInt()), + sharee, + expireDate, + note)); +} + QSharedPointer ShareManager::parseLinkShare(const QJsonObject &data) { QUrl url; diff --git a/src/gui/sharemanager.h b/src/gui/sharemanager.h index 64a860d14f..6477edc463 100644 --- a/src/gui/sharemanager.h +++ b/src/gui/sharemanager.h @@ -259,6 +259,42 @@ private: QUrl _url; }; +class UserGroupShare : public Share +{ + Q_OBJECT +public: + UserGroupShare(AccountPtr account, + const QString &id, + const QString &owner, + const QString &ownerDisplayName, + const QString &path, + const ShareType shareType, + const Permissions permissions, + const QSharedPointer shareWith, + const QDate &expireDate, + const QString ¬e); + + void setNote(const QString ¬e); + + QString getNote() const; + + void slotNoteSet(const QJsonDocument &, const QVariant ¬e); + + void setExpireDate(const QDate &date); + + QDate getExpireDate() const; + + void slotExpireDateSet(const QJsonDocument &reply, const QVariant &value); + +signals: + void noteSet(); + void expireDateSet(); + +private: + QString _note; + QDate _expireDate; +}; + /** * The share manager allows for creating, retrieving and deletion * of shares. It abstracts away from the OCS Share API, all the usages @@ -331,6 +367,7 @@ private slots: void slotOcsError(int statusCode, const QString &message); private: QSharedPointer parseLinkShare(const QJsonObject &data); + QSharedPointer parseUserGroupShare(const QJsonObject &data); QSharedPointer parseShare(const QJsonObject &data); AccountPtr _account; diff --git a/src/gui/shareusergroupwidget.cpp b/src/gui/shareusergroupwidget.cpp index 0a5ea25315..480d58cc48 100644 --- a/src/gui/shareusergroupwidget.cpp +++ b/src/gui/shareusergroupwidget.cpp @@ -12,6 +12,7 @@ * for more details. */ +#include "sharee.h" #include "ui_shareusergroupwidget.h" #include "ui_shareuserline.h" #include "shareusergroupwidget.h" @@ -228,7 +229,10 @@ void ShareUserGroupWidget::slotSharesFetched(const QList> _ui->mainOwnerLabel->setText(QString("Shared with you by ").append(share->getOwnerDisplayName())); } - auto *s = new ShareUserLine(share, _maxSharingPermissions, _isFile, _parentScrollArea); + + Q_ASSERT(share->getShareType() == Share::TypeUser || share->getShareType() == Share::TypeGroup); + auto userGroupShare = qSharedPointerDynamicCast(share); + auto *s = new ShareUserLine(userGroupShare, _maxSharingPermissions, _isFile, _parentScrollArea); connect(s, &ShareUserLine::resizeRequested, this, &ShareUserGroupWidget::slotAdjustScrollWidgetSize); connect(s, &ShareUserLine::visualDeletionDone, this, &ShareUserGroupWidget::getShares); s->setBackgroundRole(layout->count() % 2 == 0 ? QPalette::Base : QPalette::AlternateBase); @@ -267,12 +271,19 @@ void ShareUserGroupWidget::slotSharesFetched(const QList> void ShareUserGroupWidget::slotAdjustScrollWidgetSize() { QScrollArea *scrollArea = _parentScrollArea; - int count = scrollArea->findChildren().count(); - scrollArea->setVisible(count > 0); - if (count > 0 && count <= 3) { + const auto shareUserLineChilds = scrollArea->findChildren(); + + // Ask the child widgets to calculate their size + for (const auto shareUserLineChild : shareUserLineChilds) { + shareUserLineChild->adjustSize(); + } + + const auto shareUserLineChildsCount = shareUserLineChilds.count(); + scrollArea->setVisible(shareUserLineChildsCount > 0); + if (shareUserLineChildsCount > 0 && shareUserLineChildsCount <= 3) { scrollArea->setFixedHeight(scrollArea->widget()->sizeHint().height()); } - scrollArea->setFrameShape(count > 3 ? QFrame::StyledPanel : QFrame::NoFrame); + scrollArea->setFrameShape(shareUserLineChildsCount > 3 ? QFrame::StyledPanel : QFrame::NoFrame); } void ShareUserGroupWidget::slotPrivateLinkShare() @@ -413,7 +424,7 @@ void ShareUserGroupWidget::activateShareeLineEdit() _ui->shareeLineEdit->setFocus(); } -ShareUserLine::ShareUserLine(QSharedPointer share, +ShareUserLine::ShareUserLine(QSharedPointer share, SharePermissions maxSharingPermissions, bool isFile, QWidget *parent) @@ -422,6 +433,7 @@ ShareUserLine::ShareUserLine(QSharedPointer share, , _share(share) , _isFile(isFile) { + Q_ASSERT(_share); _ui->setupUi(this); _ui->sharedWith->setElideMode(Qt::ElideRight); @@ -434,6 +446,12 @@ ShareUserLine::ShareUserLine(QSharedPointer share, maxSharingPermissions & SharePermissionDelete); _ui->permissionsEdit->setEnabled(enabled); connect(_ui->permissionsEdit, &QAbstractButton::clicked, this, &ShareUserLine::slotEditPermissionsChanged); + connect(_ui->noteConfirmButton, &QAbstractButton::clicked, this, &ShareUserLine::onNoteConfirmButtonClicked); + connect(_ui->confirmExpirationDate, &QAbstractButton::clicked, this, &ShareUserLine::setExpireDate); + connect(_ui->calendar, &QDateTimeEdit::dateChanged, this, &ShareUserLine::setExpireDate); + + connect(_share.data(), &UserGroupShare::noteSet, this, &ShareUserLine::disableProgessIndicatorAnimation); + connect(_share.data(), &UserGroupShare::expireDateSet, this, &ShareUserLine::disableProgessIndicatorAnimation); // create menu with checkable permissions auto *menu = new QMenu(this); @@ -443,6 +461,28 @@ ShareUserLine::ShareUserLine(QSharedPointer share, menu->addAction(_permissionReshare); connect(_permissionReshare, &QAction::triggered, this, &ShareUserLine::slotPermissionsChanged); + showNoteOptions(false); + _noteLinkAction = new QAction(tr("Note to recipient")); + _noteLinkAction->setCheckable(true); + menu->addAction(_noteLinkAction); + connect(_noteLinkAction, &QAction::triggered, this, &ShareUserLine::toggleNoteOptions); + if (!_share->getNote().isEmpty()) { + _noteLinkAction->setChecked(true); + showNoteOptions(true); + } + + showExpireDateOptions(false); + _expirationDateLinkAction = new QAction(tr("Set expiration date")); + _expirationDateLinkAction->setCheckable(true); + menu->addAction(_expirationDateLinkAction); + connect(_expirationDateLinkAction, &QAction::triggered, this, &ShareUserLine::toggleExpireDateOptions); + const auto expireDate = _share->getExpireDate().isValid() ? share.data()->getExpireDate() : QDate(); + if (!expireDate.isNull()) { + _ui->calendar->setDate(expireDate); + _expirationDateLinkAction->setChecked(true); + showExpireDateOptions(true); + } + menu->addSeparator(); // Adds action to delete share widget @@ -708,6 +748,93 @@ void ShareUserLine::customizeStyle() QIcon deleteicon = QIcon::fromTheme(QLatin1String("user-trash"),Theme::createColorAwareIcon(QLatin1String(":/client/theme/delete.svg"))); _deleteShareButton->setIcon(deleteicon); + + _ui->noteConfirmButton->setIcon(Theme::createColorAwareIcon(":/client/theme/confirm.svg")); + _ui->confirmExpirationDate->setIcon(Theme::createColorAwareIcon(":/client/theme/confirm.svg")); + _ui->progressIndicator->setColor(QGuiApplication::palette().color(QPalette::WindowText)); } +void ShareUserLine::showNoteOptions(bool show) +{ + _ui->noteLabel->setVisible(show); + _ui->noteTextEdit->setVisible(show); + _ui->noteConfirmButton->setVisible(show); + + if (show) { + const auto note = _share->getNote(); + _ui->noteTextEdit->setText(note); + _ui->noteTextEdit->setFocus(); + } + + emit resizeRequested(); +} + + +void ShareUserLine::toggleNoteOptions(bool enable) +{ + showNoteOptions(enable); + + if (!enable) { + // Delete note + _share->setNote(QString()); + } +} + +void ShareUserLine::onNoteConfirmButtonClicked() +{ + setNote(_ui->noteTextEdit->toPlainText()); +} + +void ShareUserLine::setNote(const QString ¬e) +{ + enableProgessIndicatorAnimation(true); + _share->setNote(note); +} + +void ShareUserLine::toggleExpireDateOptions(bool enable) +{ + showExpireDateOptions(enable); + + if (!enable) { + _share->setExpireDate(QDate()); + } +} + +void ShareUserLine::showExpireDateOptions(bool show) +{ + _ui->expirationLabel->setVisible(show); + _ui->calendar->setVisible(show); + _ui->confirmExpirationDate->setVisible(show); + + if (show) { + const QDate date = QDate::currentDate().addDays(1); + _ui->calendar->setDate(date); + _ui->calendar->setMinimumDate(date); + _ui->calendar->setFocus(); + } + + emit resizeRequested(); +} + +void ShareUserLine::setExpireDate() +{ + enableProgessIndicatorAnimation(true); + _share->setExpireDate(_ui->calendar->date()); +} + +void ShareUserLine::enableProgessIndicatorAnimation(bool enable) +{ + if (enable) { + if (!_ui->progressIndicator->isAnimated()) { + _ui->progressIndicator->startAnimation(); + } + } else { + _ui->progressIndicator->stopAnimation(); + } +} + +void ShareUserLine::disableProgessIndicatorAnimation() +{ + enableProgessIndicatorAnimation(false); +} } diff --git a/src/gui/shareusergroupwidget.h b/src/gui/shareusergroupwidget.h index fe45d1e36c..c69c64012b 100644 --- a/src/gui/shareusergroupwidget.h +++ b/src/gui/shareusergroupwidget.h @@ -16,6 +16,7 @@ #define SHAREUSERGROUPWIDGET_H #include "accountfwd.h" +#include "sharemanager.h" #include "sharepermissions.h" #include "sharee.h" #include "QProgressIndicator.h" @@ -119,7 +120,7 @@ class ShareUserLine : public QWidget Q_OBJECT public: - explicit ShareUserLine(QSharedPointer Share, + explicit ShareUserLine(QSharedPointer share, SharePermissions maxSharingPermissions, bool isFile, QWidget *parent = nullptr); @@ -150,16 +151,30 @@ private: void loadAvatar(); void customizeStyle(); - Ui::ShareUserLine *_ui; - QSharedPointer _share; - bool _isFile; + void showNoteOptions(bool show); + void toggleNoteOptions(bool enable); + void onNoteConfirmButtonClicked(); + void setNote(const QString ¬e); - // _permissionEdit is a checkbox - QAction *_permissionReshare; - QAction *_deleteShareButton; - QAction *_permissionCreate; - QAction *_permissionChange; - QAction *_permissionDelete; + void toggleExpireDateOptions(bool enable); + void showExpireDateOptions(bool show); + void setExpireDate(); + + void enableProgessIndicatorAnimation(bool enable); + void disableProgessIndicatorAnimation(); + + Ui::ShareUserLine *_ui; + QSharedPointer _share; + bool _isFile; + + // _permissionEdit is a checkbox + QAction *_permissionReshare; + QAction *_deleteShareButton; + QAction *_permissionCreate; + QAction *_permissionChange; + QAction *_permissionDelete; + QAction *_noteLinkAction; + QAction *_expirationDateLinkAction; }; } diff --git a/src/gui/shareuserline.ui b/src/gui/shareuserline.ui index a9b9b807c3..a40015bc3f 100644 --- a/src/gui/shareuserline.ui +++ b/src/gui/shareuserline.ui @@ -6,8 +6,8 @@ 0 0 - 360 - 58 + 980 + 210 @@ -25,81 +25,182 @@ false - + - - - - 0 - 0 - + + + 0 - - - 40 - 40 - - - - Qt::AlignCenter - - + + + + + 0 + 0 + + + + + 40 + 40 + + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + Username + + + Qt::PlainText + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + can edit + + + + + + + + :/client/theme/more.svg:/client/theme/more.svg + + + true + + + + - - - - 0 - 0 - + + + QLayout::SetMinimumSize - - Username - - - Qt::PlainText - - + + + + Note: + + + + + + + + 0 + 0 + + + + + 0 + 60 + + + + QAbstractScrollArea::AdjustToContents + + + + + + + ... + + + + :/client/theme/confirm.svg:/client/theme/confirm.svg + + + true + + + + - - - Qt::Horizontal - - - QSizePolicy::Expanding - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - can edit - - - - - - - - :/client/theme/more.svg:/client/theme/more.svg - - - true - - + + + + + + 78 + 0 + + + + Expires: + + + Qt::AlignCenter + + + + + + + + 1 + 0 + + + + + + + + ... + + + + :/client/theme/confirm.svg:/client/theme/confirm.svg + + + true + + + + @@ -109,6 +210,12 @@ QLabel
elidedlabel.h
+ + QProgressIndicator + QWidget +
QProgressIndicator.h
+ 1 +