Improvements to UI to make behaviour more similar to twitter.

Add new UI elements.
Can show PulseFocus or GroupFocus at the moment.
WIP, Much more work to get this finalised.
This commit is contained in:
drbob 2020-05-15 22:36:50 +10:00
parent ccf849159a
commit 11ce959b2f
26 changed files with 3747 additions and 135 deletions

View file

@ -0,0 +1,364 @@
/*******************************************************************************
* gui/TheWire/PulseViewItem.cpp *
* *
* Copyright (c) 2012-2020 Robert Fernie <retroshare.project@gmail.com> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Affero General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Affero General Public License for more details. *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#include <QDateTime>
#include <QMessageBox>
#include <QMouseEvent>
#include <QBuffer>
#include "PulseViewItem.h"
#include "gui/gxs/GxsIdDetails.h"
#include "util/DateTime.h"
/** Constructor */
PulseViewItem::PulseViewItem(PulseViewHolder *holder)
:QWidget(NULL), mHolder(holder)
{
}
PulseDataItem::PulseDataItem(PulseViewHolder *holder, RsWirePulseSPtr pulse)
:PulseViewItem(holder), mPulse(pulse)
{
}
void PulseDataItem::actionReply()
{
std::cerr << "PulseDataItem::actionReply()";
std::cerr << std::endl;
if (mHolder) {
std::string groupName = "unknownGroupName";
mHolder->PVHreply(*mPulse, groupName);
}
}
void PulseDataItem::actionRepublish()
{
std::cerr << "PulseDataItem::actionRepublish()";
std::cerr << std::endl;
if (mHolder) {
std::string groupName = "unknownGroupName";
mHolder->PVHrepublish(*mPulse, groupName);
}
}
void PulseDataItem::actionLike()
{
std::cerr << "PulseDataItem::actionLike()";
std::cerr << std::endl;
if (mHolder) {
std::string groupName = "unknownGroupName";
mHolder->PVHlike(*mPulse, groupName);
}
}
void PulseDataItem::actionViewGroup()
{
std::cerr << "PulseDataItem::actionViewGroup()";
std::cerr << std::endl;
RsGxsGroupId groupId;
if (mPulse) {
if ((mPulse->mPulseType & WIRE_PULSE_TYPE_ORIGINAL) ||
(mPulse->mPulseType & WIRE_PULSE_TYPE_RESPONSE))
{
/* use pulse group */
groupId = mPulse->mMeta.mGroupId;
}
else
{
/* IS REF use pulse group */
groupId = mPulse->mRefGroupId;
}
}
if (mHolder) {
mHolder->PVHviewGroup(groupId);
}
}
void PulseDataItem::actionViewParent()
{
std::cerr << "PulseDataItem::actionViewParent()";
std::cerr << std::endl;
// TODO
RsGxsGroupId groupId;
RsGxsMessageId msgId;
if (mPulse) {
if (mPulse->mPulseType & WIRE_PULSE_TYPE_ORIGINAL)
{
std::cerr << "PulseDataItem::actionViewParent() Error ORIGINAL no parent";
std::cerr << std::endl;
}
else if (mPulse->mPulseType & WIRE_PULSE_TYPE_RESPONSE)
{
/* mRefs refer to parent */
groupId = mPulse->mRefGroupId;
msgId = mPulse->mRefOrigMsgId;
}
else
{
/* type = REF, group / thread ref to parent */
groupId = mPulse->mMeta.mGroupId;
msgId = mPulse->mMeta.mThreadId;
}
}
if (mHolder) {
mHolder->PVHviewPulse(groupId, msgId);
}
}
void PulseDataItem::actionViewPulse()
{
std::cerr << "PulseDataItem::actionViewPulse()";
std::cerr << std::endl;
// TODO
RsGxsGroupId groupId;
RsGxsMessageId msgId;
if (mPulse) {
if ((mPulse->mPulseType & WIRE_PULSE_TYPE_ORIGINAL) ||
(mPulse->mPulseType & WIRE_PULSE_TYPE_RESPONSE))
{
groupId = mPulse->mMeta.mGroupId;
msgId = mPulse->mMeta.mOrigMsgId;
}
else
{
/* type = REF, mRefs link to message */
std::cerr << "PulseDataItem::actionViewPulse() REF unlikely retrievable";
std::cerr << std::endl;
groupId = mPulse->mRefGroupId;
msgId = mPulse->mRefOrigMsgId;
}
}
if (mHolder) {
mHolder->PVHviewPulse(groupId, msgId);
}
}
void PulseDataItem::actionFollow()
{
std::cerr << "PulseDataItem::actionFollow()";
std::cerr << std::endl;
// TODO
RsGxsGroupId groupId;
if (mHolder) {
mHolder->PVHfollow(groupId);
}
}
void PulseDataItem::actionRate()
{
std::cerr << "PulseDataItem::actionRate()";
std::cerr << std::endl;
// TODO
RsGxsId authorId;
if (mHolder) {
mHolder->PVHrate(authorId);
}
}
void PulseDataItem::showPulse()
{
std::cerr << "PulseDataItem::showPulse()";
std::cerr << std::endl;
if (!mPulse) {
std::cerr << "PulseDataItem::showPulse() PULSE invalid - skipping";
std::cerr << std::endl;
return;
}
/* 3 Modes:
* ORIGINAL
* RESPONSE
* REFERENCE
*
* ORIG / RESPONSE are similar.
*/
if (mPulse->mPulseType & WIRE_PULSE_TYPE_REFERENCE)
{
// Group
setGroupName(mPulse->mRefGroupName);
setAuthor(mPulse->mRefAuthorId.toStdString());
// Msg
setRefMessage(QString::fromStdString(mPulse->mRefPulseText), mPulse->mRefImageCount);
setDate(mPulse->mRefPublishTs);
// References (unknown for a REFERENCE)
// should show FOLLOW button instead.
// setLikes(mPulse->mLikes.size());
// setReplies(mPulse->mReplies.size());
// setRepublishes(mPulse->mRepublishes.size());
showResponseStats(false);
//
setReference(mPulse->mPulseType & WIRE_PULSE_RESPONSE_MASK, mPulse->mMeta.mGroupId, "GroupName TODO");
}
else // ORIG / RESPONSE.
{
// Group
bool headshotOkay = false;
if (mPulse->mGroupPtr) {
setGroupName(mPulse->mGroupPtr->mMeta.mGroupName);
if (mPulse->mGroupPtr->mHeadshot.mData)
{
QPixmap pixmap;
if (GxsIdDetails::loadPixmapFromData(
mPulse->mGroupPtr->mHeadshot.mData,
mPulse->mGroupPtr->mHeadshot.mSize,
pixmap,GxsIdDetails::ORIGINAL))
{
headshotOkay = true;
pixmap = pixmap.scaled(50,50);
setHeadshot(pixmap);
}
}
} else {
setGroupName("GroupName UNKNOWN");
}
if (!headshotOkay)
{
// default.
QPixmap pixmap = QPixmap(":/icons/png/posted.png").scaled(50,50);
setHeadshot(pixmap); // QPixmap(":/icons/png/posted.png"));
}
setAuthor(mPulse->mMeta.mAuthorId.toStdString());
// Msg
setMessage(mPulse);
setDate(mPulse->mMeta.mPublishTs);
// References
showResponseStats(true);
setLikes(mPulse->mLikes.size());
setReplies(mPulse->mReplies.size());
setRepublishes(mPulse->mRepublishes.size());
if (mPulse->mPulseType & WIRE_PULSE_TYPE_RESPONSE)
{
setReference(mPulse->mPulseType & WIRE_PULSE_RESPONSE_MASK, mPulse->mRefGroupId, mPulse->mRefGroupName);
}
}
}
void PulseDataItem::setGroupName(std::string name)
{
setGroupNameString(QString::fromStdString(name));
}
void PulseDataItem::setAuthor(std::string name)
{
setAuthorString(QString::fromStdString(name));
}
void PulseDataItem::setDate(rstime_t date)
{
// could be more intelligent.
// eg. 3 Hr ago, if recent.
setDateString(DateTime::formatDateTime(date));
}
void PulseDataItem::setLikes(uint32_t count)
{
setLikesString(ToNumberUnits(count));
}
void PulseDataItem::setRepublishes(uint32_t count)
{
setRepublishesString(ToNumberUnits(count));
}
void PulseDataItem::setReplies(uint32_t count)
{
std::cerr << "PulseDataItem::setReplies(" << count << ")";
std::cerr << std::endl;
setRepliesString(ToNumberUnits(count));
}
void PulseDataItem::setReference(uint32_t response_type, RsGxsGroupId groupId, std::string groupName)
{
QString ref;
if (response_type == WIRE_PULSE_TYPE_REPLY) {
ref = "In reply to @" + QString::fromStdString(groupName);
}
else if (response_type == WIRE_PULSE_TYPE_REPUBLISH) {
ref = "retweeting @" + QString::fromStdString(groupName);
}
else if (response_type == WIRE_PULSE_TYPE_LIKE) {
ref = "liking @" + QString::fromStdString(groupName);
}
setReferenceString(ref);
}
// Utils.
QString BoldString(QString msg)
{
QString output = "<html><head/><body><p><span style=\" font-weight:600;\">";
output += msg;
output += "</span></p></body></html>";
return output;
}
QString ToNumberUnits(uint32_t count)
{
QString ans;
if (count > 1000000)
{
ans.sprintf("%6.2fm", count / 1000000.0);
}
else if (count > 1000)
{
ans.sprintf("%6.2fk", count / 1000.0);
}
else
{
ans.sprintf("%6d", count);
}
return ans;
}