From: Christian Kamm Date: Wed, 5 Apr 2017 07:38:46 +0000 (+0200) Subject: ShareDialog: Add support for multiple public link shares #5655 X-Git-Tag: archive/raspbian/3.16.7-1_deb13u1+rpi1~1^2~767^2~1 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=a1f7168d2a7d9f6d5181e55af644d15745fd2026;p=nextcloud-desktop.git ShareDialog: Add support for multiple public link shares #5655 Starting from oC 10.0.0 having several public link shares with different attributes for a path will be supported. This adds functionality to create, edit and delete these public link shares. The behavior is currently gated by server version, but should be adapted to use a capability as soon as one is introduced, see owncloud/core#27622. The UI reduces to a single-share version when talking to older servers. Testing scenarios: * Link sharing is disabled (by capability, not by theme) * Required passwords * Required expiry * Forbidden 'allow upload' for folders * New and old servers --- diff --git a/src/gui/ocssharejob.cpp b/src/gui/ocssharejob.cpp index 60155e3e9..7c13df43e 100644 --- a/src/gui/ocssharejob.cpp +++ b/src/gui/ocssharejob.cpp @@ -96,7 +96,8 @@ void OcsShareJob::setPermissions(const QString &shareId, start(); } -void OcsShareJob::createLinkShare(const QString &path, +void OcsShareJob::createLinkShare(const QString &path, + const QString &name, const QString &password) { setVerb("POST"); @@ -104,6 +105,9 @@ void OcsShareJob::createLinkShare(const QString &path, addParam(QString::fromLatin1("path"), path); addParam(QString::fromLatin1("shareType"), QString::number(Share::TypeLink)); + if (!name.isEmpty()) { + addParam(QString::fromLatin1("name"), name); + } if (!password.isEmpty()) { addParam(QString::fromLatin1("password"), password); } diff --git a/src/gui/ocssharejob.h b/src/gui/ocssharejob.h index beb7067f3..675c64592 100644 --- a/src/gui/ocssharejob.h +++ b/src/gui/ocssharejob.h @@ -86,10 +86,12 @@ public: * Create a new link share * * @param path The path of the file/folder to share + * @param name The name of the link share, empty name auto-generates one * @param password Optionally a password for the share */ void createLinkShare(const QString& path, - const QString& password = ""); + const QString& name, + const QString& password); /** * Create a new share diff --git a/src/gui/sharedialog.cpp b/src/gui/sharedialog.cpp index 6fd2807cc..5c5e6ff13 100644 --- a/src/gui/sharedialog.cpp +++ b/src/gui/sharedialog.cpp @@ -181,8 +181,6 @@ void ShareDialog::showSharingUi() theme->userGroupSharing() && _accountState->account()->serverVersionInt() >= Account::makeServerVersion(8, 2, 0); - bool autoShare = !userGroupSharing; - if (userGroupSharing) { _userGroupWidget = new ShareUserGroupWidget(_accountState->account(), _sharePath, _localPath, _maxSharingPermissions, this); _ui->shareWidgets->addTab(_userGroupWidget, tr("Users and Groups")); @@ -199,7 +197,7 @@ void ShareDialog::showSharingUi() hline->setPalette(p); } - _linkWidget = new ShareLinkWidget(_accountState->account(), _sharePath, _localPath, _maxSharingPermissions, autoShare, this); + _linkWidget = new ShareLinkWidget(_accountState->account(), _sharePath, _localPath, _maxSharingPermissions, this); _linkWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); _ui->shareWidgets->addTab(_linkWidget, tr("Public Links")); _linkWidget->getShares(); diff --git a/src/gui/sharelinkwidget.cpp b/src/gui/sharelinkwidget.cpp index 456c02be7..63fd0b576 100644 --- a/src/gui/sharelinkwidget.cpp +++ b/src/gui/sharelinkwidget.cpp @@ -26,52 +26,51 @@ #include #include #include +#include +#include namespace OCC { +const char propertyShareC[] = "oc_share"; + ShareLinkWidget::ShareLinkWidget(AccountPtr account, const QString &sharePath, const QString &localPath, SharePermissions maxSharingPermissions, - bool autoShare, QWidget *parent) : QWidget(parent), _ui(new Ui::ShareLinkWidget), _account(account), _sharePath(sharePath), _localPath(localPath), - _passwordJobRunning(false), - _manager(NULL), - _share(NULL), - _maxSharingPermissions(maxSharingPermissions), - _autoShare(autoShare), - _passwordRequired(false) + _manager(0), + _passwordRequired(false), + _expiryRequired(false), + _namesSupported(true) { _ui->setupUi(this); + _ui->linkShares->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); + _ui->linkShares->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents); + _ui->linkShares->horizontalHeader()->setSectionResizeMode(2, QHeaderView::ResizeToContents); + //Is this a file or folder? _isFile = QFileInfo(localPath).isFile(); - _ui->pushButton_copy->setIcon(QIcon::fromTheme("edit-copy")); - _ui->pushButton_copy->setEnabled(false); - connect(_ui->pushButton_copy, SIGNAL(clicked(bool)), SLOT(slotPushButtonCopyLinkPressed())); - - _ui->pushButton_mail->setIcon(QIcon::fromTheme("mail-send")); - _ui->pushButton_mail->setEnabled(false); - connect(_ui->pushButton_mail, SIGNAL(clicked(bool)), SLOT(slotPushButtonMailLinkPressed())); - // the following progress indicator widgets are added to layouts which makes them // automatically deleted once the dialog dies. - _pi_link = new QProgressIndicator(); + _pi_create = new QProgressIndicator(); _pi_password = new QProgressIndicator(); _pi_date = new QProgressIndicator(); _pi_editing = new QProgressIndicator(); - _ui->horizontalLayout_shareLink->addWidget(_pi_link); + _ui->horizontalLayout_create->addWidget(_pi_create); _ui->horizontalLayout_password->addWidget(_pi_password); _ui->horizontalLayout_editing->addWidget(_pi_editing); - // _ui->horizontalLayout_expire->addWidget(_pi_date); + _ui->horizontalLayout_expire->insertWidget(_ui->horizontalLayout_expire->count() - 1, _pi_date); - connect(_ui->checkBox_shareLink, SIGNAL(clicked()), this, SLOT(slotCheckBoxShareLinkClicked())); + connect(_ui->nameLineEdit, SIGNAL(returnPressed()), SLOT(slotShareNameEntered())); + connect(_ui->createShareButton, SIGNAL(clicked(bool)), SLOT(slotShareNameEntered())); + connect(_ui->linkShares, SIGNAL(itemSelectionChanged()), SLOT(slotShareSelectionChanged())); connect(_ui->checkBox_password, SIGNAL(clicked()), this, SLOT(slotCheckBoxPasswordClicked())); connect(_ui->lineEdit_password, SIGNAL(returnPressed()), this, SLOT(slotPasswordReturnPressed())); connect(_ui->lineEdit_password, SIGNAL(textChanged(QString)), this, SLOT(slotPasswordChanged(QString))); @@ -80,19 +79,34 @@ ShareLinkWidget::ShareLinkWidget(AccountPtr account, connect(_ui->calendar, SIGNAL(dateChanged(QDate)), SLOT(slotExpireDateChanged(QDate))); connect(_ui->checkBox_editing, SIGNAL(clicked()), this, SLOT(slotCheckBoxEditingClicked())); - //Disable checkbox - _ui->checkBox_shareLink->setEnabled(false); - _pi_link->startAnimation(); + if (!_account->capabilities().sharePublicLink()) { + displayError(tr("Link shares have been disabled")); + _ui->nameLineEdit->setEnabled(false); + _ui->createShareButton->setEnabled(false); + } else if ( !(maxSharingPermissions & SharePermissionShare) ) { + displayError(tr("The file can not be shared because it was shared without sharing permission.")); + _ui->nameLineEdit->setEnabled(false); + _ui->createShareButton->setEnabled(false); + } + + // Older servers don't support multiple public link shares + // TODO: Tying to the server version isn't nice, see owncloud/core#27622 + if (_account->serverVersionInt() < Account::makeServerVersion(10, 0, 0)) { + _namesSupported = false; + _ui->nameLineEdit->hide(); + _ui->createShareButton->setText(tr("Create public link share")); + } + + _ui->shareProperties->setEnabled(false); _ui->pushButton_setPassword->setEnabled(false); - _ui->widget_shareLink->hide(); - _ui->lineEdit_password->hide(); - _ui->pushButton_setPassword->hide(); + _ui->lineEdit_password->setEnabled(false); + _ui->pushButton_setPassword->setEnabled(false); + _ui->checkBox_password->setText(tr("P&assword protect")); _ui->calendar->setMinimumDate(QDate::currentDate().addDays(1)); _ui->calendar->setEnabled(false); - _ui->checkBox_password->setText(tr("P&assword protect")); // check if the file is already inside of a synced folder if( sharePath.isEmpty() ) { // The file is not yet in an ownCloud synced folder. We could automatically @@ -122,6 +136,7 @@ ShareLinkWidget::ShareLinkWidget(AccountPtr account, _ui->calendar->setMaximumDate(QDate::currentDate().addDays( _account->capabilities().sharePublicLinkExpireDateDays() )); + _expiryRequired = true; } // File can't have public upload set. @@ -129,6 +144,14 @@ ShareLinkWidget::ShareLinkWidget(AccountPtr account, _ui->checkBox_editing->setEnabled( _account->capabilities().sharePublicLinkAllowUpload()); + + // Prepare sharing menu + + _shareLinkMenu = new QMenu(this); + _openLinkAction = _shareLinkMenu->addAction(tr("Open link in browser")); + _copyLinkAction = _shareLinkMenu->addAction(tr("Copy link to clipboard")); + _emailLinkAction = _shareLinkMenu->addAction(tr("Send link by email")); + /* * Create the share manager and connect it properly */ @@ -140,20 +163,169 @@ ShareLinkWidget::ShareLinkWidget(AccountPtr account, connect(_manager, SIGNAL(serverError(int, QString)), SLOT(slotServerError(int,QString))); } -void ShareLinkWidget::setExpireDate(const QDate &date) +ShareLinkWidget::~ShareLinkWidget() +{ + delete _ui; +} + +void ShareLinkWidget::getShares() +{ + _manager->fetchShares(_sharePath); +} + +void ShareLinkWidget::slotSharesFetched(const QList> &shares) +{ + const QString versionString = _account->serverVersion(); + qDebug() << Q_FUNC_INFO << versionString << "Fetched" << shares.count() << "shares"; + + // Preserve the previous selection + QString selectedShareId; + if (auto share = selectedShare()) { + selectedShareId = share->getId(); + } + // ...except if selection should move to a new share + if (!_newShareOverrideSelectionId.isEmpty()) { + selectedShareId = _newShareOverrideSelectionId; + _newShareOverrideSelectionId.clear(); + } + + auto table = _ui->linkShares; + table->clearContents(); + table->setRowCount(0); + + auto shareIcon = QIcon::fromTheme(QLatin1String("mail-send")); + auto deleteIcon = QIcon::fromTheme(QLatin1String("user-trash"), + QIcon(QLatin1String(":/client/resources/delete.png"))); + + foreach (auto share, shares) { + if (share->getShareType() != Share::TypeLink) { + continue; + } + auto linkShare = qSharedPointerDynamicCast(share); + + // Connect all shares signals to gui slots + connect(share.data(), SIGNAL(serverError(int, QString)), SLOT(slotServerError(int,QString))); + connect(share.data(), SIGNAL(shareDeleted()), SLOT(slotDeleteShareFetched())); + connect(share.data(), SIGNAL(expireDateSet()), SLOT(slotExpireSet())); + connect(share.data(), SIGNAL(publicUploadSet()), SLOT(slotPublicUploadSet())); + connect(share.data(), SIGNAL(passwordSet()), SLOT(slotPasswordSet())); + connect(share.data(), SIGNAL(passwordSetError(int, QString)), SLOT(slotPasswordSetError(int,QString))); + + // Build the table row + auto row = table->rowCount(); + table->insertRow(row); + + QString name = linkShare->getName(); + if (name.isEmpty()) { + name = tr("Public link"); + } + auto nameItem = new QTableWidgetItem(name); + nameItem->setData(Qt::UserRole, QVariant::fromValue(linkShare)); + table->setItem(row, 0, nameItem); + + auto shareButton = new QToolButton; + shareButton->setIcon(shareIcon); + shareButton->setProperty(propertyShareC, QVariant::fromValue(linkShare)); + shareButton->setMenu(_shareLinkMenu); + shareButton->setPopupMode(QToolButton::InstantPopup); + connect(shareButton, SIGNAL(triggered(QAction*)), SLOT(slotShareLinkButtonTriggered(QAction*))); + table->setCellWidget(row, 1, shareButton); + + auto deleteButton = new QToolButton; + deleteButton->setIcon(deleteIcon); + deleteButton->setProperty(propertyShareC, QVariant::fromValue(linkShare)); + connect(deleteButton, SIGNAL(clicked(bool)), SLOT(slotDeleteShareClicked())); + table->setCellWidget(row, 2, deleteButton); + + // Reestablish the previous selection + if (selectedShareId == share->getId()) { + table->selectRow(row); + } + } + + // Select the first share by default + if (!selectedShare() && table->rowCount() != 0) { + table->selectRow(0); + } + + if (!_namesSupported) { + _ui->createShareButton->setEnabled(table->rowCount() == 0); + } +} + +void ShareLinkWidget::slotShareSelectionChanged() { - _pi_date->startAnimation(); + // Disable running progress indicators + _pi_create->stopAnimation(); + _pi_editing->stopAnimation(); + _pi_date->stopAnimation(); + _pi_password->stopAnimation(); + _ui->errorLabel->hide(); - _share->setExpireDate(date); + + auto share = selectedShare(); + if (!share) { + _ui->shareProperties->setEnabled(false); + _ui->checkBox_editing->setChecked(false); + _ui->checkBox_expire->setChecked(false); + _ui->checkBox_password->setChecked(false); + return; + } + + _ui->shareProperties->setEnabled(true); + + _ui->checkBox_password->setEnabled(!_passwordRequired); + _ui->checkBox_expire->setEnabled(!_expiryRequired); + _ui->checkBox_editing->setEnabled( + _account->capabilities().sharePublicLinkAllowUpload()); + + // Password state + _ui->checkBox_password->setText(tr("P&assword protect")); + if (share->isPasswordSet()) { + _ui->checkBox_password->setChecked(true); + _ui->lineEdit_password->setEnabled(true); + _ui->lineEdit_password->setPlaceholderText("********"); + _ui->lineEdit_password->setText(QString()); + _ui->lineEdit_password->setEnabled(true); + _ui->pushButton_setPassword->setEnabled(true); + } else { + _ui->checkBox_password->setChecked(false); + _ui->lineEdit_password->setPlaceholderText(QString()); + _ui->lineEdit_password->setEnabled(false); + _ui->pushButton_setPassword->setEnabled(false); + } + + // Expiry state + _ui->calendar->setMinimumDate(QDate::currentDate().addDays(1)); + if (share->getExpireDate().isValid()) { + _ui->checkBox_expire->setChecked(true); + _ui->calendar->setDate(share->getExpireDate()); + _ui->calendar->setEnabled(true); + } else { + _ui->checkBox_expire->setChecked(false); + _ui->calendar->setEnabled(false); + } + + // Public upload state (box is hidden for files) + if (!_isFile) { + _ui->checkBox_editing->setChecked(share->getPublicUpload()); + } +} + +void ShareLinkWidget::setExpireDate(const QDate &date) +{ + if (auto current = selectedShare()) { + _pi_date->startAnimation(); + _ui->errorLabel->hide(); + current->setExpireDate(date); + } } void ShareLinkWidget::slotExpireSet() { - auto date = _share->getExpireDate(); - if (date.isValid()) { - _ui->calendar->setDate(date); + if (sender() == selectedShare().data()) { + slotShareSelectionChanged(); } - _pi_date->stopAnimation(); } void ShareLinkWidget::slotExpireDateChanged(const QDate &date) @@ -163,14 +335,24 @@ void ShareLinkWidget::slotExpireDateChanged(const QDate &date) } } -ShareLinkWidget::~ShareLinkWidget() -{ - delete _ui; -} - void ShareLinkWidget::slotPasswordReturnPressed() { - setPassword(_ui->lineEdit_password->text()); + if (!selectedShare()) { + // If share creation requires a password, we'll be in this case + if (_namesSupported && _ui->nameLineEdit->text().isEmpty()) { + _ui->nameLineEdit->setFocus(); + return; + } + if (_ui->lineEdit_password->text().isEmpty()) { + _ui->lineEdit_password->setFocus(); + return; + } + + _pi_create->startAnimation(); + _manager->createLinkShare(_sharePath, _ui->nameLineEdit->text(), _ui->lineEdit_password->text()); + } else { + setPassword(_ui->lineEdit_password->text()); + } _ui->lineEdit_password->clearFocus(); } @@ -182,23 +364,20 @@ void ShareLinkWidget::slotPasswordChanged(const QString& newText) void ShareLinkWidget::setPassword(const QString &password) { - _pi_link->startAnimation(); - _pi_password->startAnimation(); - _ui->errorLabel->hide(); + if (auto current = selectedShare()) { + _pi_password->startAnimation(); + _ui->errorLabel->hide(); - _ui->checkBox_password->setEnabled(false); - _ui->lineEdit_password->setEnabled(false); + _ui->checkBox_password->setEnabled(false); + _ui->lineEdit_password->setEnabled(false); - if( !_share.isNull() ) { - _share->setPassword(password); - } else { - _ui->checkBox_shareLink->setEnabled(false); - _manager->createLinkShare(_sharePath, password); + current->setPassword(password); } } void ShareLinkWidget::slotPasswordSet() { + _pi_password->stopAnimation(); _ui->lineEdit_password->setText(QString()); _ui->lineEdit_password->setPlaceholderText(tr("Password Protected")); @@ -208,226 +387,43 @@ void ShareLinkWidget::slotPasswordSet() * at this point. */ getShares(); - - _pi_password->stopAnimation(); } -void ShareLinkWidget::getShares() +void ShareLinkWidget::slotShareNameEntered() { - _manager->fetchShares(_sharePath); -} - -void ShareLinkWidget::slotSharesFetched(const QList> &shares) -{ - const QString versionString = _account->serverVersion(); - qDebug() << Q_FUNC_INFO << versionString << "Fetched" << shares.count() << "shares"; - - //Show link checkbox now if capabilities allow it - _ui->checkBox_shareLink->setEnabled(_account->capabilities().sharePublicLink()); - _pi_link->stopAnimation(); - - Q_FOREACH(auto share, shares) { - - if (share->getShareType() == Share::TypeLink) { - _share = qSharedPointerDynamicCast(share); - _ui->pushButton_copy->show(); - _ui->pushButton_mail->show(); - - _ui->widget_shareLink->show(); - _ui->checkBox_shareLink->setChecked(true); - - _ui->checkBox_password->setEnabled(!_passwordRequired); - - if (_share->isPasswordSet()) { - _ui->lineEdit_password->setEnabled(true); - _ui->checkBox_password->setChecked(true); - _ui->lineEdit_password->setPlaceholderText("********"); - _ui->lineEdit_password->setText(QString()); - _ui->lineEdit_password->show(); - _ui->pushButton_setPassword->show(); - } else { - _ui->checkBox_password->setChecked(false); - // _ui->lineEdit_password->setPlaceholderText("********"); - _ui->lineEdit_password->hide(); - _ui->pushButton_setPassword->hide(); - } - - _ui->checkBox_expire->setEnabled( - !_account->capabilities().sharePublicLinkEnforceExpireDate()); - - _ui->calendar->setMinimumDate(QDate::currentDate().addDays(1)); - if (_share->getExpireDate().isValid()) { - _ui->calendar->setDate(_share->getExpireDate()); - _ui->calendar->setEnabled(true); - _ui->checkBox_expire->setChecked(true); - } else { - _ui->calendar->setEnabled(false); - _ui->checkBox_expire->setChecked(false); - } - - /* - * Only directories can have public upload set - * For public links the server sets CREATE and UPDATE permissions. - */ - _ui->checkBox_editing->setEnabled( - _account->capabilities().sharePublicLinkAllowUpload()); - if (!_isFile) { - _ui->checkBox_editing->setChecked(_share->getPublicUpload()); - } - - setShareLink(_share->getLink().toString()); - _ui->pushButton_mail->setEnabled(true); - _ui->pushButton_copy->setEnabled(true); - - // Connect all shares signals to gui slots - connect(_share.data(), SIGNAL(expireDateSet()), SLOT(slotExpireSet())); - connect(_share.data(), SIGNAL(publicUploadSet()), SLOT(slotPublicUploadSet())); - connect(_share.data(), SIGNAL(passwordSet()), SLOT(slotPasswordSet())); - connect(_share.data(), SIGNAL(shareDeleted()), SLOT(slotDeleteShareFetched())); - connect(_share.data(), SIGNAL(serverError(int, QString)), SLOT(slotServerError(int,QString))); - connect(_share.data(), SIGNAL(passwordSetError(int, QString)), SLOT(slotPasswordSetError(int,QString))); - - break; - } + if (!_ui->nameLineEdit->text().isEmpty() || !_namesSupported) { + _pi_create->startAnimation(); + _manager->createLinkShare(_sharePath, _ui->nameLineEdit->text(), QString()); } - if( !_share.isNull() ) { - setShareCheckBoxTitle(true); - } else { - // If its clear that resharing is not allowed, display an error - if( !(_maxSharingPermissions & SharePermissionShare) ) { - displayError(tr("The file can not be shared because it was shared without sharing permission.")); - _ui->checkBox_shareLink->setEnabled(false); - } else if (_autoShare && _ui->checkBox_shareLink->isEnabled()) { - _ui->checkBox_shareLink->setChecked(true); - slotCheckBoxShareLinkClicked(); - } - } -} - -void ShareLinkWidget::resizeEvent(QResizeEvent *e) -{ - QWidget::resizeEvent(e); - redrawElidedUrl(); -} - -void ShareLinkWidget::redrawElidedUrl() -{ - QString u; - - if( !_shareUrl.isEmpty() ) { - QFontMetrics fm( _ui->_labelShareLink->font() ); - int linkLengthPixel = _ui->_labelShareLink->width(); - - const QUrl realUrl(_shareUrl); - QString elidedUrl = fm.elidedText(_shareUrl, Qt::ElideRight, linkLengthPixel); - - u = QString("%2").arg(Utility::escape(realUrl.toString(QUrl::None)), Utility::escape(elidedUrl)); - } - _ui->_labelShareLink->setText(u); -} - -void ShareLinkWidget::setShareLink( const QString& url ) -{ - // FIXME: shorten the url for output. - const QUrl realUrl(url); - if( realUrl.isValid() ) { - _shareUrl = url; - _ui->pushButton_copy->setEnabled(true); - _ui->pushButton_mail->setEnabled(true); - } else { - _shareUrl.clear(); - _ui->_labelShareLink->setText(QString::null); - } - redrawElidedUrl(); - } void ShareLinkWidget::slotDeleteShareFetched() { - _share.clear(); - _pi_link->stopAnimation(); - _ui->lineEdit_password->clear(); - _ui->_labelShareLink->clear(); - _ui->pushButton_copy->setEnabled(false); - _ui->pushButton_mail->setEnabled(false); - _ui->widget_shareLink->hide(); - _ui->lineEdit_password->hide(); - _ui->pushButton_setPassword->setEnabled(false); - _ui->pushButton_setPassword->hide(); - _ui->checkBox_expire->setChecked(false); - _ui->checkBox_password->setChecked(false); - _ui->calendar->setEnabled(false); - - _shareUrl.clear(); - - setShareCheckBoxTitle(false); -} - -void ShareLinkWidget::slotCheckBoxShareLinkClicked() -{ - qDebug() << Q_FUNC_INFO <<( _ui->checkBox_shareLink->checkState() == Qt::Checked); - if (_ui->checkBox_shareLink->checkState() == Qt::Checked) { - /* - * Check the capabilities if the server requires a password for a share - * Ask for it directly - */ - if (_account->capabilities().sharePublicLinkEnforcePassword()) { - _ui->checkBox_password->setChecked(true); - _ui->checkBox_password->setEnabled(false); - _ui->checkBox_password->setText(tr("Public shå requires a password")); - _ui->checkBox_expire->setEnabled(false); - _ui->checkBox_editing->setEnabled(false); - _ui->lineEdit_password->setEnabled(true); - _ui->lineEdit_password->setFocus(); - _ui->pushButton_copy->hide(); - _ui->pushButton_mail->hide(); - _ui->widget_shareLink->show(); - - slotCheckBoxPasswordClicked(); - return; - } - - _pi_link->startAnimation(); - _ui->checkBox_shareLink->setEnabled(false); - _ui->errorLabel->hide(); - _manager->createLinkShare(_sharePath); - } else { - - if (!_share.isNull()) { - // We have a share so delete it - _pi_link->startAnimation(); - _share->deleteShare(); - } else { - // No share object so we are deleting while a password is required - _ui->widget_shareLink->hide(); - } - - - } + getShares(); } void ShareLinkWidget::slotCreateShareFetched(const QSharedPointer share) { - _pi_link->stopAnimation(); + _pi_create->stopAnimation(); _pi_password->stopAnimation(); + _ui->nameLineEdit->clear(); - _share = share; + _newShareOverrideSelectionId = share->getId(); getShares(); } void ShareLinkWidget::slotCreateShareRequiresPassword(const QString& message) { - // there needs to be a password - _pi_link->stopAnimation(); + // Deselect existing shares + _ui->linkShares->clearSelection(); + + // Prepare password entry + _pi_create->stopAnimation(); _pi_password->stopAnimation(); + _ui->shareProperties->setEnabled(true); _ui->checkBox_password->setChecked(true); _ui->checkBox_password->setEnabled(false); _ui->checkBox_password->setText(tr("Public shå requires a password")); - _ui->lineEdit_password->setEnabled(true); - _ui->lineEdit_password->setFocus(); - _ui->pushButton_copy->hide(); - _ui->pushButton_mail->hide(); - _ui->widget_shareLink->show(); _ui->checkBox_expire->setEnabled(false); _ui->checkBox_editing->setEnabled(false); if (!message.isEmpty()) { @@ -443,17 +439,16 @@ void ShareLinkWidget::slotCreateShareRequiresPassword(const QString& message) void ShareLinkWidget::slotCheckBoxPasswordClicked() { if (_ui->checkBox_password->checkState() == Qt::Checked) { - _ui->lineEdit_password->show(); - _ui->pushButton_setPassword->show(); - _ui->lineEdit_password->setPlaceholderText(tr("Please Set Password")); _ui->lineEdit_password->setEnabled(true); + _ui->pushButton_setPassword->setEnabled(true); + _ui->lineEdit_password->setPlaceholderText(tr("Please Set Password")); _ui->lineEdit_password->setFocus(); } else { setPassword(QString()); _ui->lineEdit_password->setPlaceholderText(QString()); _pi_password->startAnimation(); - _ui->lineEdit_password->hide(); - _ui->pushButton_setPassword->hide(); + _ui->lineEdit_password->setEnabled(false); + _ui->pushButton_setPassword->setEnabled(false); } } @@ -478,17 +473,17 @@ void ShareLinkWidget::slotCheckBoxExpireClicked() extern void copyToPasteboard(const QString &string); #endif -void ShareLinkWidget::slotPushButtonCopyLinkPressed() +void ShareLinkWidget::copyShareLink(const QUrl &url) { #ifdef Q_OS_MAC - copyToPasteboard(_shareUrl); + copyToPasteboard(url.toString()); #else QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(_shareUrl); + clipboard->setText(url.toString()); #endif } -void ShareLinkWidget::slotPushButtonMailLinkPressed() +void ShareLinkWidget::emailShareLink(const QUrl &url) { QString fileName = _sharePath.mid(_sharePath.lastIndexOf('/') + 1); @@ -497,7 +492,7 @@ void ShareLinkWidget::slotPushButtonMailLinkPressed() "?subject=I shared %1 with you" "&body=%2").arg( fileName, - _shareUrl), + url.toString()), QUrl::TolerantMode))) { QMessageBox::warning( this, @@ -508,42 +503,69 @@ void ShareLinkWidget::slotPushButtonMailLinkPressed() } } -void ShareLinkWidget::slotCheckBoxEditingClicked() +void ShareLinkWidget::openShareLink(const QUrl &url) { - ShareLinkWidget::setPublicUpload(_ui->checkBox_editing->checkState() == Qt::Checked); + if (!QDesktopServices::openUrl(url)) { + QMessageBox::warning( + this, + tr("Could not open browser"), + tr("There was an error when launching the browser to " + "view the public link share. Maybe no default browser is " + "configured?")); + } } -void ShareLinkWidget::setPublicUpload(bool publicUpload) +void ShareLinkWidget::slotShareLinkButtonTriggered(QAction *action) { - _ui->checkBox_editing->setEnabled(false); - _pi_editing->startAnimation(); - _ui->errorLabel->hide(); - - _share->setPublicUpload(publicUpload); + auto share = sender()->property(propertyShareC).value>(); + QUrl url = share->getLink(); + + if (action == _copyLinkAction) { + copyShareLink(url); + } else if (action == _emailLinkAction) { + emailShareLink(url); + } else if (action == _openLinkAction) { + openShareLink(url); + } } -void ShareLinkWidget::slotPublicUploadSet() +void ShareLinkWidget::slotDeleteShareClicked() { - _pi_editing->stopAnimation(); - _ui->checkBox_editing->setEnabled(true); + auto share = sender()->property(propertyShareC).value>(); + share->deleteShare(); } -void ShareLinkWidget::setShareCheckBoxTitle(bool haveShares) +void ShareLinkWidget::slotCheckBoxEditingClicked() { - const QString noSharesTitle(tr("&Share link")); - const QString haveSharesTitle(tr("&Share link")); + if (auto current = selectedShare()) { + _ui->checkBox_editing->setEnabled(false); + _pi_editing->startAnimation(); + _ui->errorLabel->hide(); - if( haveShares ) { - _ui->checkBox_shareLink->setText( haveSharesTitle ); - } else { - _ui->checkBox_shareLink->setText( noSharesTitle ); + current->setPublicUpload(_ui->checkBox_editing->isChecked()); + } +} + +QSharedPointer ShareLinkWidget::selectedShare() const +{ + const auto items = _ui->linkShares->selectedItems(); + if (items.isEmpty()) { + return QSharedPointer(); } + return items.first()->data(Qt::UserRole).value>(); +} + +void ShareLinkWidget::slotPublicUploadSet() +{ + if (sender() == selectedShare().data()) { + slotShareSelectionChanged(); + } } void ShareLinkWidget::slotServerError(int code, const QString &message) { - _pi_link->stopAnimation(); + _pi_create->stopAnimation(); _pi_date->stopAnimation(); _pi_password->stopAnimation(); _pi_editing->stopAnimation(); @@ -556,7 +578,7 @@ void ShareLinkWidget::slotPasswordSetError(int code, const QString &message) { slotServerError(code, message); - _ui->checkBox_password->setEnabled(true); + _ui->checkBox_password->setEnabled(!_passwordRequired); _ui->lineEdit_password->setEnabled(true); _ui->lineEdit_password->setFocus(); } @@ -567,5 +589,4 @@ void ShareLinkWidget::displayError(const QString& errMsg) _ui->errorLabel->show(); } - } diff --git a/src/gui/sharelinkwidget.h b/src/gui/sharelinkwidget.h index bc663a307..c12e121c1 100644 --- a/src/gui/sharelinkwidget.h +++ b/src/gui/sharelinkwidget.h @@ -24,6 +24,8 @@ #include #include +class QMenu; + namespace OCC { namespace Ui { @@ -50,67 +52,76 @@ public: const QString &sharePath, const QString &localPath, SharePermissions maxSharingPermissions, - bool autoShare = false, QWidget *parent = 0); ~ShareLinkWidget(); void getShares(); private slots: void slotSharesFetched(const QList> &shares); - void slotCreateShareFetched(const QSharedPointer share); - void slotCreateShareRequiresPassword(const QString& message); - void slotDeleteShareFetched(); - void slotPasswordSet(); - void slotExpireSet(); - void slotExpireDateChanged(const QDate &date); - void slotCheckBoxShareLinkClicked(); + void slotShareSelectionChanged(); + + void slotShareNameEntered(); + void slotDeleteShareClicked(); void slotCheckBoxPasswordClicked(); void slotCheckBoxExpireClicked(); void slotPasswordReturnPressed(); - void slotPasswordChanged(const QString& newText); - void slotPushButtonCopyLinkPressed(); - void slotPushButtonMailLinkPressed(); void slotCheckBoxEditingClicked(); + void slotExpireDateChanged(const QDate &date); + void slotPasswordChanged(const QString& newText); + + void slotShareLinkButtonTriggered(QAction* action); + + void slotDeleteShareFetched(); + void slotCreateShareFetched(const QSharedPointer share); + void slotCreateShareRequiresPassword(const QString& message); + void slotPasswordSet(); + void slotExpireSet(); void slotPublicUploadSet(); void slotServerError(int code, const QString &message); void slotPasswordSetError(int code, const QString &message); private: - void setShareCheckBoxTitle(bool haveShares); void displayError(const QString& errMsg); - void setShareLink( const QString& url ); - void resizeEvent(QResizeEvent *e); - void redrawElidedUrl(); - void setPublicUpload(bool publicUpload); + + void setPassword(const QString &password); + void setExpireDate(const QDate &date); + + void copyShareLink(const QUrl &url); + void emailShareLink(const QUrl &url); + void openShareLink(const QUrl &url); + + /** + * Retrieve the selected share, returning 0 if none. + */ + QSharedPointer selectedShare() const; Ui::ShareLinkWidget *_ui; AccountPtr _account; QString _sharePath; QString _localPath; QString _shareUrl; -#if 0 - QString _folderAlias; - int _uploadFails; - QString _expectedSyncFile; -#endif - bool _passwordJobRunning; - void setPassword(const QString &password); - void setExpireDate(const QDate &date); - - QProgressIndicator *_pi_link; + QProgressIndicator *_pi_create; QProgressIndicator *_pi_password; QProgressIndicator *_pi_date; QProgressIndicator *_pi_editing; ShareManager *_manager; - QSharedPointer _share; - SharePermissions _maxSharingPermissions; bool _isFile; - bool _autoShare; bool _passwordRequired; + bool _expiryRequired; + bool _namesSupported; + + // When a new share is created, we want to select it + // the next time getShares() finishes. This stores its id. + QString _newShareOverrideSelectionId; + + QMenu *_shareLinkMenu; + QAction *_openLinkAction; + QAction *_copyLinkAction; + QAction *_emailLinkAction; }; } diff --git a/src/gui/sharelinkwidget.ui b/src/gui/sharelinkwidget.ui index 05809b8e2..25d8ba417 100644 --- a/src/gui/sharelinkwidget.ui +++ b/src/gui/sharelinkwidget.ui @@ -6,95 +6,71 @@ 0 0 - 372 - 237 + 376 + 375 Share NewDocument.odt - - - 0 - - - 0 - - - 0 - - - 0 - - - + + + - + + + Enter a name to create a new public link... + + + + + - Share link + &Create - - + + - + 0 0 - - - - - - - 255 - 0 - 0 - - - - - - - - - 255 - 0 - 0 - - - - - - - - - 123 - 121 - 134 - - - - - + + Qt::ScrollBarAlwaysOff - - TextLabel + + QAbstractItemView::SingleSelection - - Qt::PlainText + + QAbstractItemView::SelectRows + + false + + + 3 + + + false + + + false + + + + - - + + - 20 + 0 0 @@ -102,35 +78,11 @@ 0 - - - - 20 - - - - - QLineEdit::Password - - - - - - - - 0 - 0 - - - - Set &password - - - - - - - + + 0 + + + 0 @@ -150,80 +102,7 @@ - - - - - - - 0 - 0 - - - - Set password - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - QLayout::SetDefaultConstraint - - - - - - 0 - 0 - - - - QFrame::NoFrame - - - - - - Qt::RichText - - - true - - - - - - - &Mail link - - - - - - - Copy &link - - - - - - @@ -261,28 +140,126 @@ + + + + 20 + + + + + QLineEdit::Password + + + + + + + + 0 + 0 + + + + Set &password + + + + + + + + + + + + 0 + 0 + + + + Set password + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + - - - - Qt::Vertical + + + + + 0 + 0 + + + + + + + + + 255 + 0 + 0 + + + + + + + + + 255 + 0 + 0 + + + + + + + + + 123 + 121 + 134 + + + + + - - - 20 - 40 - + + TextLabel - + + Qt::PlainText + + - checkBox_shareLink - pushButton_copy + nameLineEdit + createShareButton + linkShares checkBox_editing checkBox_password lineEdit_password diff --git a/src/gui/sharemanager.cpp b/src/gui/sharemanager.cpp index 7b6032bbb..4f25fa477 100644 --- a/src/gui/sharemanager.cpp +++ b/src/gui/sharemanager.cpp @@ -122,11 +122,13 @@ bool LinkShare::isPasswordSet() const LinkShare::LinkShare(AccountPtr account, const QString& id, const QString& path, + const QString &name, Permissions permissions, bool passwordSet, const QUrl& url, const QDate& expireDate) : Share(account, id, path, Share::TypeLink, permissions), + _name(name), _passwordSet(passwordSet), _expireDate(expireDate), _url(url) @@ -148,6 +150,11 @@ void LinkShare::setPublicUpload(bool publicUpload) job->setPublicUpload(getId(), publicUpload); } +QString LinkShare::getName() const +{ + return _name; +} + void LinkShare::slotPublicUploadSet(const QVariantMap&, const QVariant &value) { if (value.toBool()) { @@ -210,12 +217,13 @@ ShareManager::ShareManager(AccountPtr account, QObject *parent) } void ShareManager::createLinkShare(const QString &path, + const QString &name, const QString &password) { OcsShareJob *job = new OcsShareJob(_account); connect(job, SIGNAL(shareJobFinished(QVariantMap, QVariant)), SLOT(slotLinkShareCreated(QVariantMap))); connect(job, SIGNAL(ocsError(int, QString)), SLOT(slotOcsError(int, QString))); - job->createLinkShare(path, password); + job->createLinkShare(path, name, password); } void ShareManager::slotLinkShareCreated(const QVariantMap &reply) @@ -358,9 +366,12 @@ QSharedPointer ShareManager::parseLinkShare(const QVariantMap &data) expireDate = QDate::fromString(data.value("expiration").toString(), "yyyy-MM-dd 00:00:00"); } + QString name = data.value("name").toString(); + return QSharedPointer(new LinkShare(_account, data.value("id").toString(), data.value("path").toString(), + name, (Share::Permissions)data.value("permissions").toInt(), data.value("share_with").isValid(), url, diff --git a/src/gui/sharemanager.h b/src/gui/sharemanager.h index eaec2e61f..742170dff 100644 --- a/src/gui/sharemanager.h +++ b/src/gui/sharemanager.h @@ -132,6 +132,7 @@ public: explicit LinkShare(AccountPtr account, const QString& id, const QString& path, + const QString& name, const Permissions permissions, bool passwordSet, const QUrl& url, @@ -156,6 +157,11 @@ public: */ void setPublicUpload(bool publicUpload); + /* + * Returns the name of the link share. + */ + QString getName() const; + /* * Set the password * @@ -195,6 +201,7 @@ private slots: void slotSetPasswordError(int statusCode, const QString &message); private: + QString _name; bool _passwordSet; QDate _expireDate; QUrl _url; @@ -214,14 +221,16 @@ public: * Tell the manager to create a link share * * @param path The path of the linkshare relative to the user folder on the server - * @param password The password of the share + * @param name The name of the created share, may be empty + * @param password The password of the share, may be empty * * On success the signal linkShareCreated is emitted * For older server the linkShareRequiresPassword signal is emitted when it seems appropiate * In case of a server error the serverError signal is emitted */ void createLinkShare(const QString& path, - const QString& password=""); + const QString& name, + const QString& password); /** * Tell the manager to create a new share