Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add context menu to activity list #8585

Merged
merged 2 commits into from
May 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/unreleased/8158
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ https://github.com/owncloud/client/issues/8158
https://github.com/owncloud/client/issues/4336
https://github.com/owncloud/client/issues/8528
https://github.com/owncloud/client/pull/8584
https://github.com/owncloud/client/pull/8585
14 changes: 14 additions & 0 deletions src/gui/activitylistmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,20 @@ QVariant ActivityListModel::headerData(int section, Qt::Orientation orientation,
Q_UNREACHABLE();
break;
};
case Models::StringFormatWidthRole:
switch (actionRole) {
case ActivityRole::Text:
return 120;
case ActivityRole::Account:
return 20;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might use Q_FALLTHROUGH here.

case ActivityRole::PointInTime:
return 20;
case ActivityRole::Path:
return 30;
case ActivityRole::ColumnCount:
Q_UNREACHABLE();
break;
}
};
}
return QAbstractTableModel::headerData(section, orientation, role);
Expand Down
114 changes: 39 additions & 75 deletions src/gui/activitywidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ ActivityWidget::ActivityWidget(QWidget *parent)
_ui->setupUi(this);

_model = new ActivityListModel(this);
auto sortModel = new QSortFilterProxyModel(this);
sortModel->setSourceModel(_model);
_ui->_activityList->setModel(sortModel);
sortModel->setSortRole(Models::UnderlyingDataRole);
_sortModel = new QSortFilterProxyModel(this);
_sortModel->setSourceModel(_model);
_ui->_activityList->setModel(_sortModel);
_sortModel->setSortRole(Models::UnderlyingDataRole);
_ui->_activityList->hideColumn(static_cast<int>(ActivityListModel::ActivityRole::Path));
_ui->_activityList->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
_ui->_activityList->horizontalHeader()->setSectionResizeMode(static_cast<int>(ActivityListModel::ActivityRole::Text), QHeaderView::Stretch);
Expand Down Expand Up @@ -97,16 +97,15 @@ ActivityWidget::ActivityWidget(QWidget *parent)
showLabels();
}

for (const auto widget : _widgetForNotifId) {
for (const auto widget : qAsConst(_widgetForNotifId)) {
if (widget->activity().uuid() == ast->account()->uuid()) {
scheduleWidgetToRemove(widget);
}
}
});

connect(_model, &QAbstractItemModel::modelReset, this, &ActivityWidget::dataChanged);

connect(_ui->_activityList, &QListView::activated, this, &ActivityWidget::slotOpenFile);
connect(_ui->_activityList, &QListView::customContextMenuRequested, this, &ActivityWidget::slotItemContextMenu);

connect(&_removeTimer, &QTimer::timeout, this, &ActivityWidget::slotCheckToCleanWidgets);
_removeTimer.setInterval(1000);
Expand Down Expand Up @@ -174,55 +173,6 @@ void ActivityWidget::slotAccountActivityStatus(AccountState *ast, int statusCode
showLabels();
}

// FIXME: Reused from protocol widget. Move over to utilities.
QString ActivityWidget::timeString(QDateTime dt, QLocale::FormatType format) const
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change appears to be unrelated cleanup and should be in a separate commit. Otherwise, the Git history becomes quite useless.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just removed custom date handling, we just provide a qdate to the view and it takes care of the presentation.
As we no longer sort by the display string we don't need to have seconds in the display string.

{
const QLocale loc = QLocale::system();
QString dtFormat = loc.dateTimeFormat(format);
static const QRegExp re("(HH|H|hh|h):mm(?!:s)");
dtFormat.replace(re, "\\1:mm:ss");
return loc.toString(dt, dtFormat);
}

void ActivityWidget::storeActivityList(QTextStream &ts)
{
ActivityList activities = _model->activityList();

foreach (Activity activity, activities) {
ts << right
// account name
<< qSetFieldWidth(30)
<< activity.accName()
// separator
<< qSetFieldWidth(0) << ","

// date and time
<< qSetFieldWidth(34)
<< activity.dateTime().toString()
// separator
<< qSetFieldWidth(0) << ","

// file
<< qSetFieldWidth(30)
<< activity.file()
// separator
<< qSetFieldWidth(0) << ","

// subject
<< qSetFieldWidth(100)
<< activity.subject()
// separator
<< qSetFieldWidth(0) << ","

// message (mostly empty)
<< qSetFieldWidth(55)
<< activity.message()
//
<< qSetFieldWidth(0)
<< endl;
}
}

void ActivityWidget::checkActivityTabVisibility()
{
int accountCount = AccountManager::instance()->accounts().count();
Expand All @@ -239,16 +189,6 @@ void ActivityWidget::checkActivityTabVisibility()
emit hideActivityTab(!hasAccountsWithActivity && !hasNotifications);
}

void ActivityWidget::slotOpenFile(QModelIndex indx)
{
if (indx.isValid()) {
const auto fullPath = indx.data(static_cast<int>(ActivityListModel::ActivityRole::Path)).toString();
if (QFile::exists(fullPath)) {
showInFileManager(fullPath);
}
}
}

// GUI: Display the notifications.
// All notifications in list are coming from the same account
// but in the _widgetForNotifId hash widgets for all accounts are
Expand Down Expand Up @@ -313,24 +253,23 @@ void ActivityWidget::slotBuildNotificationDisplay(const ActivityList &list)

const auto accId = list.first().uuid();
QList<Activity::Identifier> strayCats;
for (const auto &id : _widgetForNotifId.keys()) {
NotificationWidget *widget = _widgetForNotifId[id];
for (auto it = _widgetForNotifId.cbegin(); it != _widgetForNotifId.cend(); ++it) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change somehow related to the topic of the PR? I don't see the relation between using an iterator here and the new context menu.

bool found = false;
// do not mark widgets of other accounts to delete.
if (widget->activity().uuid() != accId) {
if (it.value()->activity().uuid() != accId) {
continue;
}

for (const auto &activity : list) {
if (activity.id() == id) {
if (activity.id() == it.key()) {
// found an activity
found = true;
break;
}
}
if (!found) {
// the activity does not exist any more.
strayCats.append(id);
strayCats.append(it.key());
}
}

Expand Down Expand Up @@ -376,10 +315,10 @@ void ActivityWidget::slotSendNotificationRequest(const QString &accountName, con
qCInfo(lcActivity) << "Server Notification Request " << verb << link << "on account" << accountName;
NotificationWidget *theSender = qobject_cast<NotificationWidget *>(sender());

const QStringList validVerbs = QStringList() << "GET"
<< "PUT"
<< "POST"
<< "DELETE";
const QStringList validVerbs = { QStringLiteral("GET"),
QStringLiteral("PUT"),
QStringLiteral("POST"),
QStringLiteral("DELETE") };

if (validVerbs.contains(verb)) {
AccountStatePtr acc = AccountManager::instance()->account(accountName);
Expand Down Expand Up @@ -502,6 +441,31 @@ void ActivityWidget::slotCheckToCleanWidgets()
}
}

void ActivityWidget::slotItemContextMenu()
{
auto rows = _ui->_activityList->selectionModel()->selectedRows();
auto menu = new QMenu(this);
menu->setAttribute(Qt::WA_DeleteOnClose);

// keep in sync with ProtocolWidget::showContextMenu
menu->addAction(tr("Copy to clipboard"), this, [text = Models::formatSelection(rows)] {
QApplication::clipboard()->setText(text);
});

if (rows.size() == 1) {
// keep in sync with ProtocolWidget::showContextMenu
const auto localPath = rows.first().siblingAtColumn(static_cast<int>(ActivityListModel::ActivityRole::Path)).data(Models::UnderlyingDataRole).toString();
if (!localPath.isEmpty()) {
menu->addAction(tr("Show in file browser"), this, [localPath] {
if (QFileInfo::exists(localPath)) {
showInFileManager(localPath);
}
});
}
}
menu->popup(QCursor::pos());
}


/* ==================================================================== */

Expand Down
3 changes: 2 additions & 1 deletion src/gui/activitywidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ class ActivityWidget : public QWidget
void checkActivityTabVisibility();

public slots:
void slotOpenFile(QModelIndex indx);
void slotRefreshActivities(AccountState *ptr);
void slotRefreshNotifications(AccountState *ptr);
void slotRemoveAccount(AccountState *ptr);
Expand All @@ -94,6 +93,7 @@ private slots:
void slotCheckToCleanWidgets();

private:
void slotItemContextMenu();
void showLabels();
QString timeString(QDateTime dt, QLocale::FormatType format) const;
Ui::ActivityWidget *_ui;
Expand All @@ -113,6 +113,7 @@ private slots:
int _notificationRequestsRunning;

ActivityListModel *_model;
QSortFilterProxyModel *_sortModel;
QVBoxLayout *_notificationsLayout;
};

Expand Down
3 changes: 3 additions & 0 deletions src/gui/activitywidget.ui
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
Expand Down
1 change: 0 additions & 1 deletion src/gui/protocolitemmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,6 @@ QVariant ProtocolItemModel::headerData(int section, Qt::Orientation orientation,
};

case Models::StringFormatWidthRole:
// TODO: fine tune
switch (actionRole) {
case ProtocolItemRole::Time:
return 20;
Expand Down
3 changes: 2 additions & 1 deletion src/gui/protocolwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ void ProtocolWidget::showContextMenu(QWidget *parent, ProtocolItemModel *model,
auto menu = new QMenu(parent);
menu->setAttribute(Qt::WA_DeleteOnClose);

// keep in sync with ActivityWidget::slotItemContextMenu
menu->addAction(tr("Copy to clipboard"), parent, [text = Models::formatSelection(items)] {
QApplication::clipboard()->setText(text);
});
Expand All @@ -89,6 +90,7 @@ void ProtocolWidget::showContextMenu(QWidget *parent, ProtocolItemModel *model,
{
const QString localPath = folder->path() + data.path();
if (QFileInfo::exists(localPath)) {
// keep in sync with ActivityWidget::slotItemContextMenu
menu->addAction(tr("Show in file browser"), parent, [localPath] {
if (QFileInfo::exists(localPath)) {
showInFileManager(localPath);
Expand Down Expand Up @@ -129,7 +131,6 @@ void ProtocolWidget::showContextMenu(QWidget *parent, ProtocolItemModel *model,

void ProtocolWidget::slotItemContextMenu()
{
QModelIndexList list;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like some unrelated cleanup as well.

auto rows = _ui->_tableView->selectionModel()->selectedRows();
for (int i = 0; i < rows.size(); ++i) {
rows[i] = _sortModel->mapToSource(rows[i]);
Expand Down