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
This commit is contained in:
Christian Kamm 2017-04-05 09:38:46 +02:00
Родитель 1e1c2f8de2
Коммит a1f7168d2a
8 изменённых файлов: 576 добавлений и 543 удалений

Просмотреть файл

@ -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);
}

Просмотреть файл

@ -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

Просмотреть файл

@ -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();

Просмотреть файл

@ -26,52 +26,51 @@
#include <QFileInfo>
#include <QDesktopServices>
#include <QMessageBox>
#include <QMenu>
#include <QToolButton>
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,78 +163,11 @@ ShareLinkWidget::ShareLinkWidget(AccountPtr account,
connect(_manager, SIGNAL(serverError(int, QString)), SLOT(slotServerError(int,QString)));
}
void ShareLinkWidget::setExpireDate(const QDate &date)
{
_pi_date->startAnimation();
_ui->errorLabel->hide();
_share->setExpireDate(date);
}
void ShareLinkWidget::slotExpireSet()
{
auto date = _share->getExpireDate();
if (date.isValid()) {
_ui->calendar->setDate(date);
}
_pi_date->stopAnimation();
}
void ShareLinkWidget::slotExpireDateChanged(const QDate &date)
{
if (_ui->checkBox_expire->isChecked()) {
setExpireDate(date);
}
}
ShareLinkWidget::~ShareLinkWidget()
{
delete _ui;
}
void ShareLinkWidget::slotPasswordReturnPressed()
{
setPassword(_ui->lineEdit_password->text());
_ui->lineEdit_password->clearFocus();
}
void ShareLinkWidget::slotPasswordChanged(const QString& newText)
{
// disable the set-password button
_ui->pushButton_setPassword->setEnabled( newText.length() > 0 );
}
void ShareLinkWidget::setPassword(const QString &password)
{
_pi_link->startAnimation();
_pi_password->startAnimation();
_ui->errorLabel->hide();
_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);
}
}
void ShareLinkWidget::slotPasswordSet()
{
_ui->lineEdit_password->setText(QString());
_ui->lineEdit_password->setPlaceholderText(tr("Password Protected"));
/*
* When setting/deleting a password from a share the old share is
* deleted and a new one is created. So we need to refetch the shares
* at this point.
*/
getShares();
_pi_password->stopAnimation();
}
void ShareLinkWidget::getShares()
{
_manager->fetchShares(_sharePath);
@ -222,212 +178,252 @@ void ShareLinkWidget::slotSharesFetched(const QList<QSharedPointer<Share>> &shar
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();
// 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();
}
Q_FOREACH(auto share, shares) {
auto table = _ui->linkShares;
table->clearContents();
table->setRowCount(0);
if (share->getShareType() == Share::TypeLink) {
_share = qSharedPointerDynamicCast<LinkShare>(share);
_ui->pushButton_copy->show();
_ui->pushButton_mail->show();
auto shareIcon = QIcon::fromTheme(QLatin1String("mail-send"));
auto deleteIcon = QIcon::fromTheme(QLatin1String("user-trash"),
QIcon(QLatin1String(":/client/resources/delete.png")));
_ui->widget_shareLink->show();
_ui->checkBox_shareLink->setChecked(true);
foreach (auto share, shares) {
if (share->getShareType() != Share::TypeLink) {
continue;
}
auto linkShare = qSharedPointerDynamicCast<LinkShare>(share);
_ui->checkBox_password->setEnabled(!_passwordRequired);
// 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)));
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();
}
// Build the table row
auto row = table->rowCount();
table->insertRow(row);
_ui->checkBox_expire->setEnabled(
!_account->capabilities().sharePublicLinkEnforceExpireDate());
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);
_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);
}
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);
/*
* 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());
}
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);
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;
// Reestablish the previous selection
if (selectedShareId == share->getId()) {
table->selectRow(row);
}
}
if( !_share.isNull() ) {
setShareCheckBoxTitle(true);
// 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()
{
// Disable running progress indicators
_pi_create->stopAnimation();
_pi_editing->stopAnimation();
_pi_date->stopAnimation();
_pi_password->stopAnimation();
_ui->errorLabel->hide();
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 {
// 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();
_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()
{
if (sender() == selectedShare().data()) {
slotShareSelectionChanged();
}
}
void ShareLinkWidget::slotExpireDateChanged(const QDate &date)
{
if (_ui->checkBox_expire->isChecked()) {
setExpireDate(date);
}
}
void ShareLinkWidget::slotPasswordReturnPressed()
{
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;
}
}
}
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("<a href=\"%1\">%2</a>").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);
_pi_create->startAnimation();
_manager->createLinkShare(_sharePath, _ui->nameLineEdit->text(), _ui->lineEdit_password->text());
} else {
_shareUrl.clear();
_ui->_labelShareLink->setText(QString::null);
setPassword(_ui->lineEdit_password->text());
}
redrawElidedUrl();
_ui->lineEdit_password->clearFocus();
}
void ShareLinkWidget::slotPasswordChanged(const QString& newText)
{
// disable the set-password button
_ui->pushButton_setPassword->setEnabled( newText.length() > 0 );
}
void ShareLinkWidget::setPassword(const QString &password)
{
if (auto current = selectedShare()) {
_pi_password->startAnimation();
_ui->errorLabel->hide();
_ui->checkBox_password->setEnabled(false);
_ui->lineEdit_password->setEnabled(false);
current->setPassword(password);
}
}
void ShareLinkWidget::slotPasswordSet()
{
_pi_password->stopAnimation();
_ui->lineEdit_password->setText(QString());
_ui->lineEdit_password->setPlaceholderText(tr("Password Protected"));
/*
* When setting/deleting a password from a share the old share is
* deleted and a new one is created. So we need to refetch the shares
* at this point.
*/
getShares();
}
void ShareLinkWidget::slotShareNameEntered()
{
if (!_ui->nameLineEdit->text().isEmpty() || !_namesSupported) {
_pi_create->startAnimation();
_manager->createLinkShare(_sharePath, _ui->nameLineEdit->text(), QString());
}
}
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&aring 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<LinkShare> 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&aring 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();
auto share = sender()->property(propertyShareC).value<QSharedPointer<LinkShare>>();
QUrl url = share->getLink();
_share->setPublicUpload(publicUpload);
if (action == _copyLinkAction) {
copyShareLink(url);
} else if (action == _emailLinkAction) {
emailShareLink(url);
} else if (action == _openLinkAction) {
openShareLink(url);
}
}
void ShareLinkWidget::slotDeleteShareClicked()
{
auto share = sender()->property(propertyShareC).value<QSharedPointer<LinkShare>>();
share->deleteShare();
}
void ShareLinkWidget::slotCheckBoxEditingClicked()
{
if (auto current = selectedShare()) {
_ui->checkBox_editing->setEnabled(false);
_pi_editing->startAnimation();
_ui->errorLabel->hide();
current->setPublicUpload(_ui->checkBox_editing->isChecked());
}
}
QSharedPointer<LinkShare> ShareLinkWidget::selectedShare() const
{
const auto items = _ui->linkShares->selectedItems();
if (items.isEmpty()) {
return QSharedPointer<LinkShare>();
}
return items.first()->data(Qt::UserRole).value<QSharedPointer<LinkShare>>();
}
void ShareLinkWidget::slotPublicUploadSet()
{
_pi_editing->stopAnimation();
_ui->checkBox_editing->setEnabled(true);
}
void ShareLinkWidget::setShareCheckBoxTitle(bool haveShares)
{
const QString noSharesTitle(tr("&Share link"));
const QString haveSharesTitle(tr("&Share link"));
if( haveShares ) {
_ui->checkBox_shareLink->setText( haveSharesTitle );
} else {
_ui->checkBox_shareLink->setText( noSharesTitle );
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();
}
}

Просмотреть файл

@ -24,6 +24,8 @@
#include <QSharedPointer>
#include <QList>
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<QSharedPointer<Share>> &shares);
void slotCreateShareFetched(const QSharedPointer<LinkShare> 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<LinkShare> 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<LinkShare> 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<LinkShare> _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;
};
}

Просмотреть файл

@ -6,38 +6,201 @@
<rect>
<x>0</x>
<y>0</y>
<width>372</width>
<height>237</height>
<width>376</width>
<height>375</height>
</rect>
</property>
<property name="windowTitle">
<string>Share NewDocument.odt</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_shareLink">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_create">
<item>
<widget class="QCheckBox" name="checkBox_shareLink">
<widget class="QLineEdit" name="nameLineEdit">
<property name="placeholderText">
<string>Enter a name to create a new public link...</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="createShareButton">
<property name="text">
<string>Share link</string>
<string>&amp;Create</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0">
<item>
<widget class="QTableWidget" name="linkShares">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="showGrid">
<bool>false</bool>
</property>
<property name="columnCount">
<number>3</number>
</property>
<attribute name="horizontalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<column/>
<column/>
<column/>
</widget>
</item>
<item>
<widget class="QWidget" name="shareProperties" native="true">
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="4" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_expire">
<property name="leftMargin">
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="checkBox_expire">
<property name="text">
<string>Set &amp;expiration date</string>
</property>
</widget>
</item>
<item>
<widget class="QDateEdit" name="calendar">
<property name="calendarPopup">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QWidget" name="widget_editing" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_editing">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="checkBox_editing">
<property name="text">
<string>Allow editing</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>20</number>
</property>
<item>
<widget class="QLineEdit" name="lineEdit_password">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_setPassword">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Set &amp;password </string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_password">
<item>
<widget class="QCheckBox" name="checkBox_password">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Set password</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="errorLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
@ -90,199 +253,13 @@
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QWidget" name="widget_shareLink" native="true">
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>20</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<item row="3" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>20</number>
</property>
<item>
<widget class="QLineEdit" name="lineEdit_password">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_setPassword">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Set &amp;password </string>
</property>
</widget>
</item>
</layout>
</item>
<item row="5" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="checkBox_expire">
<property name="text">
<string>Set &amp;expiration date</string>
</property>
</widget>
</item>
<item>
<widget class="QDateEdit" name="calendar">
<property name="calendarPopup">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_password">
<item>
<widget class="QCheckBox" name="checkBox_password">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Set password</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item>
<widget class="QLabel" name="_labelShareLink">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="text">
<string/>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_mail">
<property name="text">
<string>&amp;Mail link</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_copy">
<property name="text">
<string>Copy &amp;link</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QWidget" name="widget_editing" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_editing">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="checkBox_editing">
<property name="text">
<string>Allow editing</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<tabstops>
<tabstop>checkBox_shareLink</tabstop>
<tabstop>pushButton_copy</tabstop>
<tabstop>nameLineEdit</tabstop>
<tabstop>createShareButton</tabstop>
<tabstop>linkShares</tabstop>
<tabstop>checkBox_editing</tabstop>
<tabstop>checkBox_password</tabstop>
<tabstop>lineEdit_password</tabstop>

Просмотреть файл

@ -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<LinkShare> 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<LinkShare>(new LinkShare(_account,
data.value("id").toString(),
data.value("path").toString(),
name,
(Share::Permissions)data.value("permissions").toInt(),
data.value("share_with").isValid(),
url,

Просмотреть файл

@ -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