From: Claudio Cambra Date: Thu, 16 Dec 2021 15:39:58 +0000 (+0100) Subject: Show only filenames in tray activity items, with full path in tooltip X-Git-Tag: archive/raspbian/3.16.7-1_deb13u1+rpi1~1^2~12^2~17^2~193^2 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=2a2788230739c10a507608b6be5c34d532b8e0f4;p=nextcloud-desktop.git Show only filenames in tray activity items, with full path in tooltip Signed-off-by: Claudio Cambra --- diff --git a/src/gui/tray/ActivityItem.qml b/src/gui/tray/ActivityItem.qml index 5928346cb..9fa4f8ccc 100644 --- a/src/gui/tray/ActivityItem.qml +++ b/src/gui/tray/ActivityItem.qml @@ -20,6 +20,10 @@ MouseArea { anchors.fill: parent color: (parent.containsMouse ? Style.lightHover : "transparent") } + + ToolTip.visible: containsMouse && displayLocation !== "" + ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval + ToolTip.text: qsTr("In %1").arg(displayLocation) RowLayout { id: activityItem diff --git a/src/gui/tray/activitydata.h b/src/gui/tray/activitydata.h index 11171bdfd..9b7c2ad98 100644 --- a/src/gui/tray/activitydata.h +++ b/src/gui/tray/activitydata.h @@ -61,11 +61,22 @@ public: SyncFileItemType }; + struct RichSubjectParameter { + QString type; // Required + QString id; // Required + QString name; // Required + QString path; // Required (for files only) + QUrl link; // Optional (files only) + }; + Type _type; qlonglong _id; QString _fileAction; QString _objectType; QString _subject; + QString _subjectRich; + QHash _subjectRichParameters; + QString _subjectDisplay; QString _message; QString _folder; QString _file; diff --git a/src/gui/tray/activitylistmodel.cpp b/src/gui/tray/activitylistmodel.cpp index 770074d7d..eacf36fd8 100644 --- a/src/gui/tray/activitylistmodel.cpp +++ b/src/gui/tray/activitylistmodel.cpp @@ -58,6 +58,7 @@ QHash ActivityListModel::roleNames() const roles[DisplayPathRole] = "displayPath"; roles[PathRole] = "path"; roles[AbsolutePathRole] = "absolutePath"; + roles[DisplayLocationRole] = "displayLocation"; roles[LinkRole] = "link"; roles[MessageRole] = "message"; roles[ActionRole] = "type"; @@ -114,42 +115,19 @@ QVariant ActivityListModel::data(const QModelIndex &index, int role) const if (!ast && _accountState != ast.data()) return QVariant(); - switch (role) { - case DisplayPathRole: - if (!a._file.isEmpty()) { - auto folder = FolderMan::instance()->folder(a._folder); - QString relPath(a._file); - if (folder) { - relPath.prepend(folder->remotePath()); - } - const auto localFiles = FolderMan::instance()->findFileInLocalFolders(relPath, ast->account()); - if (localFiles.count() > 0) { - if (relPath.startsWith('/') || relPath.startsWith('\\')) { - return relPath.remove(0, 1); - } else { - return relPath; - } - } - } - return QString(); - case PathRole: + const auto getFilePath = [&]() { if (!a._file.isEmpty()) { const auto folder = FolderMan::instance()->folder(a._folder); - QString relPath(a._file); - if (folder) { - relPath.prepend(folder->remotePath()); - } + const QString relPath = folder ? folder->remotePath() + a._file : a._file; - // get relative path to the file so we can open it in the file manager - const auto localFiles = FolderMan::instance()->findFileInLocalFolders(QFileInfo(relPath).path(), ast->account()); + const auto localFiles = FolderMan::instance()->findFileInLocalFolders(relPath, ast->account()); if (localFiles.isEmpty()) { return QString(); } - // If this is an E2EE file or folder, pretend we got no path, this leads to - // hiding the share button which is what we want + // If this is an E2EE file or folder, pretend we got no path, hiding the share button which is what we want if (folder) { SyncJournalFileRecord rec; folder->journalDb()->getFileRecord(a._file.mid(1), &rec); @@ -158,28 +136,44 @@ QVariant ActivityListModel::data(const QModelIndex &index, int role) const } } - return QUrl::fromLocalFile(localFiles.constFirst()); + return localFiles.constFirst(); } return QString(); - case AbsolutePathRole: { - const auto folder = FolderMan::instance()->folder(a._folder); - QString relPath(a._file); + }; + + const auto getDisplayPath = [&a, &ast]() { if (!a._file.isEmpty()) { - if (folder) { - relPath.prepend(folder->remotePath()); - } + const auto folder = FolderMan::instance()->folder(a._folder); + + QString relPath = folder ? folder->remotePath() + a._file : a._file; + const auto localFiles = FolderMan::instance()->findFileInLocalFolders(relPath, ast->account()); - if (!localFiles.empty()) { - return localFiles.constFirst(); - } else { - qWarning("File not local folders while processing absolute path request."); - return QString(); + + if (localFiles.count() > 0) { + if (relPath.startsWith('/') || relPath.startsWith('\\')) { + return relPath.remove(0, 1); + } else { + return relPath; + } } - } else { - qWarning("Received an absolute path request for an activity without a file path."); - return QString(); } - } + return QString(); + }; + + const auto displayLocation = [&]() { + const auto displayPath = QFileInfo(getDisplayPath()).path(); + return displayPath == "." || displayPath == "/" ? QString() : displayPath; + }; + + switch (role) { + case DisplayPathRole: + return getDisplayPath(); + case PathRole: + return QUrl::fromLocalFile(QFileInfo(getFilePath()).path()); + case AbsolutePathRole: + return getFilePath(); + case DisplayLocationRole: + return displayLocation(); case ActionsLinksRole: { QList customList; foreach (ActivityLink activityLink, a._links) { @@ -242,7 +236,11 @@ QVariant ActivityListModel::data(const QModelIndex &index, int role) const } } case ActionTextRole: - return a._subject; + if(a._subjectDisplay.isEmpty()) { + return a._subject; + } + + return a._subjectDisplay; case ActionTextColorRole: return a._id == -1 ? QLatin1String("#808080") : QLatin1String("#222"); // FIXME: This is a temporary workaround for _showMoreActivitiesAvailableEntry case MessageRole: @@ -332,16 +330,53 @@ void ActivityListModel::activitiesReceived(const QJsonDocument &json, int status Activity a; a._type = Activity::ActivityType; - a._objectType = json.value("object_type").toString(); + a._objectType = json.value(QStringLiteral("object_type")).toString(); a._accName = ast->account()->displayName(); - a._id = json.value("activity_id").toInt(); - a._fileAction = json.value("type").toString(); - a._subject = json.value("subject").toString(); - a._message = json.value("message").toString(); - a._file = json.value("object_name").toString(); - a._link = QUrl(json.value("link").toString()); - a._dateTime = QDateTime::fromString(json.value("datetime").toString(), Qt::ISODate); - a._icon = json.value("icon").toString(); + a._id = json.value(QStringLiteral("activity_id")).toInt(); + a._fileAction = json.value(QStringLiteral("type")).toString(); + a._subject = json.value(QStringLiteral("subject")).toString(); + a._message = json.value(QStringLiteral("message")).toString(); + a._file = json.value(QStringLiteral("object_name")).toString(); + a._link = QUrl(json.value(QStringLiteral("link")).toString()); + a._dateTime = QDateTime::fromString(json.value(QStringLiteral("datetime")).toString(), Qt::ISODate); + a._icon = json.value(QStringLiteral("icon")).toString(); + + auto richSubjectData = json.value(QStringLiteral("subject_rich")).toArray(); + Q_ASSERT(richSubjectData.size() > 1); + + if(richSubjectData.size() > 1) { + a._subjectRich = richSubjectData[0].toString(); + auto parameters = richSubjectData[1].toObject(); + const QRegularExpression subjectRichParameterRe(QStringLiteral("({[a-zA-Z0-9]*})")); + const QRegularExpression subjectRichParameterBracesRe(QStringLiteral("[{}]")); + + for (auto i = parameters.begin(); i != parameters.end(); ++i) { + const auto parameterJsonObject = i.value().toObject(); + const Activity::RichSubjectParameter parameter = { + parameterJsonObject.value(QStringLiteral("type")).toString(), + parameterJsonObject.value(QStringLiteral("id")).toString(), + parameterJsonObject.value(QStringLiteral("name")).toString(), + parameterJsonObject.contains(QStringLiteral("path")) ? parameterJsonObject.value(QStringLiteral("path")).toString() : QString(), + parameterJsonObject.contains(QStringLiteral("link")) ? QUrl(parameterJsonObject.value(QStringLiteral("link")).toString()) : QUrl(), + }; + + a._subjectRichParameters[i.key()] = parameter; + } + + auto displayString = a._subjectRich; + auto i = subjectRichParameterRe.globalMatch(displayString); + + while (i.hasNext()) { + const auto match = i.next(); + auto word = match.captured(1); + word.remove(subjectRichParameterBracesRe); + + Q_ASSERT(a._subjectRichParameters.contains(word)); + displayString = displayString.replace(match.captured(1), a._subjectRichParameters[word].name); + } + + a._subjectDisplay = displayString; + } list.append(a); _currentItem = list.last()._id; diff --git a/src/gui/tray/activitylistmodel.h b/src/gui/tray/activitylistmodel.h index 89667d1dd..07385e768 100644 --- a/src/gui/tray/activitylistmodel.h +++ b/src/gui/tray/activitylistmodel.h @@ -55,6 +55,7 @@ public: DisplayPathRole, PathRole, AbsolutePathRole, + DisplayLocationRole, // Provides the display path to a file's parent folder, relative to Nextcloud root LinkRole, PointInTimeRole, AccountConnectedRole, diff --git a/src/gui/tray/usermodel.cpp b/src/gui/tray/usermodel.cpp index c821a8b1a..a3200df3b 100644 --- a/src/gui/tray/usermodel.cpp +++ b/src/gui/tray/usermodel.cpp @@ -506,6 +506,8 @@ void User::processCompletedSyncItem(const Folder *folder, const SyncFileItemPtr activity._folder = folder->alias(); activity._fileAction = ""; + const auto fileName = QFileInfo(item->_originalFile).fileName(); + if (item->_instruction == CSYNC_INSTRUCTION_REMOVE) { activity._fileAction = "file_deleted"; } else if (item->_instruction == CSYNC_INSTRUCTION_NEW) { @@ -520,15 +522,15 @@ void User::processCompletedSyncItem(const Folder *folder, const SyncFileItemPtr qCWarning(lcActivity) << "Item " << item->_file << " retrieved successfully."; if (item->_direction != SyncFileItem::Up) { - activity._message = tr("Synced %1").arg(item->_originalFile); + activity._message = tr("Synced %1").arg(fileName); } else if (activity._fileAction == "file_renamed") { - activity._message = tr("You renamed %1").arg(item->_originalFile); + activity._message = tr("You renamed %1").arg(fileName); } else if (activity._fileAction == "file_deleted") { - activity._message = tr("You deleted %1").arg(item->_originalFile); + activity._message = tr("You deleted %1").arg(fileName); } else if (activity._fileAction == "file_created") { - activity._message = tr("You created %1").arg(item->_originalFile); + activity._message = tr("You created %1").arg(fileName); } else { - activity._message = tr("You changed %1").arg(item->_originalFile); + activity._message = tr("You changed %1").arg(fileName); } _activityModel->addSyncFileItemToActivityList(activity);