mirror of
https://github.com/RetroShare/RetroShare.git
synced 2026-09-12 19:50:17 +05:00
Merge c02069e95f into 01bc50edb3
This commit is contained in:
commit
e9afdf5c29
@ -41,6 +41,7 @@
|
||||
#include <QBuffer>
|
||||
|
||||
#include <iostream>
|
||||
#include <retroshare/rsidentity.h>
|
||||
#include <gui/RetroShareLink.h>
|
||||
#include <util/imageutil.h>
|
||||
#include "gui/common/FilesDefs.h"
|
||||
@ -55,9 +56,9 @@
|
||||
|
||||
const int MAXMESSAGESIZE = 199000;
|
||||
|
||||
PostedCreatePostDialog::PostedCreatePostDialog(RsPosted *posted, const RsGxsGroupId& grpId, const RsGxsId& default_author, QWidget *parent):
|
||||
PostedCreatePostDialog::PostedCreatePostDialog(RsPosted *posted, const RsGxsGroupId& grpId, const RsGxsId& default_author, const RsGxsMessageId& existingPostId, QWidget *parent):
|
||||
QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint),
|
||||
mPosted(posted), mGrpId(grpId),
|
||||
mPosted(posted), mGrpId(grpId), mOrigPostId(existingPostId),
|
||||
ui(new Ui::PostedCreatePostDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
@ -69,7 +70,14 @@ PostedCreatePostDialog::PostedCreatePostDialog(RsPosted *posted, const RsGxsGrou
|
||||
connect(ui->RichTextEditWidget, SIGNAL(textSizeOk(bool)),ui->postButton, SLOT(setEnabled(bool)));
|
||||
|
||||
ui->headerFrame->setHeaderImage(FilesDefs::getPixmapFromQtResourcePath(":/icons/png/postedlinks.png"));
|
||||
ui->headerFrame->setHeaderText(tr("Create a new Post"));
|
||||
|
||||
if(!mOrigPostId.isNull())
|
||||
{
|
||||
ui->headerFrame->setHeaderText(tr("Edit Post"));
|
||||
ui->postButton->setText(tr("Update"));
|
||||
}
|
||||
else
|
||||
ui->headerFrame->setHeaderText(tr("Create a new Post"));
|
||||
|
||||
setAttribute ( Qt::WA_DeleteOnClose, true );
|
||||
|
||||
@ -107,6 +115,61 @@ PostedCreatePostDialog::PostedCreatePostDialog(RsPosted *posted, const RsGxsGrou
|
||||
|
||||
// should we save the ID in the settings here? I'm not sure we want this.
|
||||
}
|
||||
|
||||
if(!mOrigPostId.isNull())
|
||||
loadExistingPost();
|
||||
}
|
||||
|
||||
void PostedCreatePostDialog::loadExistingPost()
|
||||
{
|
||||
RsGxsGroupId grpId = mGrpId;
|
||||
RsGxsMessageId postId = mOrigPostId;
|
||||
|
||||
RsThread::async([this,grpId,postId]()
|
||||
{
|
||||
std::vector<RsPostedPost> posts;
|
||||
std::vector<RsGxsComment> comments;
|
||||
std::vector<RsGxsVote> votes;
|
||||
std::set<RsGxsMessageId> s({ postId });
|
||||
|
||||
bool ok = mPosted->getBoardContent(grpId,s,posts,comments,votes) && posts.size()==1;
|
||||
|
||||
RsQThreadUtils::postToObject( [ok,posts,this]()
|
||||
{
|
||||
if(!ok)
|
||||
{
|
||||
QMessageBox::warning(this, tr("RetroShare"), tr("This post could not be loaded, it may not be available locally."), QMessageBox::Ok, QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
const RsPostedPost& post(posts[0]);
|
||||
|
||||
setTitle(QString::fromUtf8(post.mMeta.mMsgName.c_str()));
|
||||
setLink(QString::fromUtf8(post.mLink.c_str()));
|
||||
ui->RichTextEditWidget->setText(QString::fromUtf8(post.mNotes.c_str()));
|
||||
|
||||
if(post.mImage.mSize > 0 && post.mImage.mData != NULL)
|
||||
{
|
||||
imagebytes = QByteArray((const char*)post.mImage.mData, post.mImage.mSize);
|
||||
|
||||
QPixmap pix;
|
||||
if(pix.loadFromData(imagebytes))
|
||||
{
|
||||
ui->imageLabel->setPixmap(pix);
|
||||
ui->removeButton->show();
|
||||
ui->stackedWidgetPicture->setCurrentIndex(IMG_PICTURE);
|
||||
}
|
||||
}
|
||||
|
||||
// Default to editing with the original author's identity when we
|
||||
// own it (typical case: the author edits their own post). When
|
||||
// editing someone else's post as board admin, the edit will be
|
||||
// signed with whichever own identity is currently selected.
|
||||
|
||||
if(rsIdentity->isOwnId(post.mMeta.mAuthorId))
|
||||
ui->idChooser->setChosenId(post.mMeta.mAuthorId);
|
||||
}, this );
|
||||
});
|
||||
}
|
||||
|
||||
PostedCreatePostDialog::~PostedCreatePostDialog()
|
||||
@ -160,42 +223,46 @@ void PostedCreatePostDialog::createPost()
|
||||
return;
|
||||
}//switch (ui->idChooser->getChosenId(authorId))
|
||||
|
||||
RsPostedPost post;
|
||||
post.mMeta.mGroupId = mGrpId;
|
||||
post.mLink = std::string(ui->linkEdit->text().toUtf8());
|
||||
|
||||
std::string link = std::string(ui->linkEdit->text().toUtf8());
|
||||
std::string notes;
|
||||
|
||||
if(!ui->RichTextEditWidget->toPlainText().trimmed().isEmpty()) {
|
||||
QString text;
|
||||
text = ui->RichTextEditWidget->toHtml();
|
||||
post.mNotes = std::string(text.toUtf8());
|
||||
notes = std::string(text.toUtf8());
|
||||
}
|
||||
|
||||
post.mMeta.mAuthorId = authorId;
|
||||
post.mMeta.mMsgName = std::string(ui->titleEdit->text().toUtf8());
|
||||
|
||||
std::string title = std::string(ui->titleEdit->text().toUtf8());
|
||||
|
||||
RsGxsImage image;
|
||||
if(imagebytes.size() > 0)
|
||||
{
|
||||
// send posted image
|
||||
post.mImage.copy((uint8_t *) imagebytes.data(), imagebytes.size());
|
||||
}
|
||||
image.copy((uint8_t *) imagebytes.data(), imagebytes.size());
|
||||
}
|
||||
|
||||
int msgsize = post.mLink.length() + post.mMeta.mMsgName.length() + post.mNotes.length() + imagebytes.size();
|
||||
int msgsize = link.length() + title.length() + notes.length() + imagebytes.size();
|
||||
if(msgsize > MAXMESSAGESIZE) {
|
||||
QString errormessage = QString(tr("Message is too large.<br />actual size: %1 bytes, maximum size: %2 bytes.")).arg(msgsize).arg(MAXMESSAGESIZE);
|
||||
QMessageBox::warning(this, "RetroShare", errormessage, QMessageBox::Ok, QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
RsThread::async([this,post]()
|
||||
RsGxsGroupId grpId = mGrpId;
|
||||
RsGxsMessageId origPostId = mOrigPostId;
|
||||
|
||||
RsThread::async([this,grpId,title,link,notes,authorId,image,origPostId]()
|
||||
{
|
||||
RsGxsMessageId post_id;
|
||||
std::string error_message;
|
||||
|
||||
bool res = rsPosted->createPost(post,post_id);
|
||||
bool res = rsPosted->createPostV2(grpId,title,RsUrl(link),notes,authorId,image,post_id,error_message,origPostId);
|
||||
|
||||
RsQThreadUtils::postToObject( [res,this]()
|
||||
RsQThreadUtils::postToObject( [res,error_message,this]()
|
||||
{
|
||||
if(!res)
|
||||
QMessageBox::information(nullptr,tr("Error while creating post"),tr("An error occurred while creating the post."));
|
||||
QMessageBox::information(nullptr,tr("Error while creating post"),
|
||||
tr("An error occurred while creating the post: ") + QString::fromUtf8(error_message.c_str()));
|
||||
|
||||
accept();
|
||||
}, this );
|
||||
|
||||
@ -37,8 +37,12 @@ public:
|
||||
/*!
|
||||
* @param tokenQ parent callee token
|
||||
* @param posted
|
||||
* @param existingPostId When non null, the dialog edits the given
|
||||
* already existing post instead of creating a new one. Editing
|
||||
* a post requires either being its original author, or being
|
||||
* the board admin.
|
||||
*/
|
||||
explicit PostedCreatePostDialog(RsPosted* posted, const RsGxsGroupId& grpId, const RsGxsId& default_author=RsGxsId(),QWidget *parent = 0);
|
||||
explicit PostedCreatePostDialog(RsPosted* posted, const RsGxsGroupId& grpId, const RsGxsId& default_author=RsGxsId(), const RsGxsMessageId& existingPostId=RsGxsMessageId(), QWidget *parent = 0);
|
||||
~PostedCreatePostDialog();
|
||||
|
||||
void setTitle(const QString& title);
|
||||
@ -62,12 +66,14 @@ private slots:
|
||||
void setPage(int viewMode);
|
||||
private:
|
||||
void processSettings(bool load);
|
||||
void loadExistingPost();
|
||||
int viewMode();
|
||||
|
||||
QString mLink;
|
||||
QString mNotes;
|
||||
RsPosted* mPosted;
|
||||
RsGxsGroupId mGrpId;
|
||||
RsGxsMessageId mOrigPostId;
|
||||
|
||||
Ui::PostedCreatePostDialog *ui;
|
||||
};
|
||||
|
||||
@ -366,12 +366,26 @@ void PostedListWidgetWithModel::postContextMenu(const QPoint& point)
|
||||
|
||||
menu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_AUTHOR), tr("Show author in People tab"), this, SLOT(showAuthorInPeople()))->setData(index);
|
||||
|
||||
#ifdef TODO
|
||||
// This feature is not implemented yet in libretroshare.
|
||||
// Own posts can always be edited by their author. Board admins can also
|
||||
// edit any post, similarly to what is already done for forums.
|
||||
|
||||
if(IS_GROUP_PUBLISHER(mGroup.mMeta.mSubscribeFlags))
|
||||
menu.addAction(FilesDefs::getIconFromQtResourcePath(":/images/edit_16.png"), tr("Edit"), this, SLOT(editPost()));
|
||||
#endif
|
||||
bool can_edit = rsIdentity->isOwnId(post.mMeta.mAuthorId)
|
||||
|| IS_GROUP_ADMIN(mGroup.mMeta.mSubscribeFlags);
|
||||
|
||||
if(can_edit)
|
||||
menu.addAction(FilesDefs::getIconFromQtResourcePath(":/images/edit_16.png"), tr("Edit"), this, SLOT(editPost()))->setData(index);
|
||||
|
||||
// Sticking ("pinning") a post to the top of the feed is an admin-only
|
||||
// moderation action, similarly to what is already done for forums.
|
||||
|
||||
if(IS_GROUP_ADMIN(mGroup.mMeta.mSubscribeFlags))
|
||||
{
|
||||
bool is_pinned = mGroup.mPinnedPosts.ids.find(post.mMeta.mMsgId) != mGroup.mPinnedPosts.ids.end();
|
||||
|
||||
menu.addAction( FilesDefs::getIconFromQtResourcePath(":/images/pin32.png"),
|
||||
is_pinned ? tr("Un-pin this post") : tr("Pin this post up"),
|
||||
this, SLOT(togglePinPost()))->setData(index);
|
||||
}
|
||||
|
||||
menu.exec(QCursor::pos());
|
||||
}
|
||||
@ -537,16 +551,48 @@ void PostedListWidgetWithModel::copyMessageLink()
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TODO
|
||||
void PostedListWidgetWithModel::editPost()
|
||||
{
|
||||
QModelIndex index = ui->postsTree->selectionModel()->currentIndex();
|
||||
RsPostedPost post = index.data(Qt::UserRole).value<RsPostedPost>() ;
|
||||
|
||||
CreatePostedMsg *msgDialog = new CreatePostedMsg(post.mMeta.mGroupId,post.mMeta.mMsgId);
|
||||
if(!index.isValid())
|
||||
return;
|
||||
|
||||
RsPostedPost post = index.data(Qt::UserRole).value<RsPostedPost>() ;
|
||||
|
||||
if(post.mMeta.mMsgId.isNull())
|
||||
return;
|
||||
|
||||
PostedCreatePostDialog *msgDialog = new PostedCreatePostDialog(rsPosted,post.mMeta.mGroupId,post.mMeta.mAuthorId,post.mMeta.mMsgId);
|
||||
msgDialog->show();
|
||||
|
||||
/* window will destroy itself! */
|
||||
}
|
||||
|
||||
void PostedListWidgetWithModel::togglePinPost()
|
||||
{
|
||||
QModelIndex index = ui->postsTree->selectionModel()->currentIndex();
|
||||
|
||||
if(!index.isValid())
|
||||
return;
|
||||
|
||||
RsPostedPost post = index.data(Qt::UserRole).value<RsPostedPost>() ;
|
||||
|
||||
if(post.mMeta.mMsgId.isNull())
|
||||
return;
|
||||
|
||||
if(mGroup.mPinnedPosts.ids.find(post.mMeta.mMsgId) == mGroup.mPinnedPosts.ids.end())
|
||||
mGroup.mPinnedPosts.ids.insert(post.mMeta.mMsgId);
|
||||
else
|
||||
mGroup.mPinnedPosts.ids.erase(post.mMeta.mMsgId);
|
||||
|
||||
uint32_t token;
|
||||
rsPosted->updateGroup(token,mGroup);
|
||||
|
||||
// The actual model/view update will be triggered by libretroshare using
|
||||
// the rsEvent system once the board data is updated (RsPostedEventCode
|
||||
// ::PINNED_POSTS_CHANGED / UPDATED_POSTED_GROUP).
|
||||
}
|
||||
#endif
|
||||
|
||||
void PostedListWidgetWithModel::handleEvent_main_thread(std::shared_ptr<const RsEvent> event)
|
||||
{
|
||||
@ -576,6 +622,7 @@ void PostedListWidgetWithModel::handleEvent_main_thread(std::shared_ptr<const Rs
|
||||
case RsPostedEventCode::UPDATED_POSTED_GROUP: [[fallthrough]];
|
||||
case RsPostedEventCode::UPDATED_MESSAGE: [[fallthrough]];
|
||||
case RsPostedEventCode::BOARD_DELETED: [[fallthrough]];
|
||||
case RsPostedEventCode::PINNED_POSTS_CHANGED: [[fallthrough]];
|
||||
case RsPostedEventCode::SYNC_PARAMETERS_UPDATED:
|
||||
{
|
||||
if(e->mPostedGroupId == groupId())
|
||||
|
||||
@ -137,6 +137,8 @@ private slots:
|
||||
void showPostDetails();
|
||||
#endif
|
||||
void postContextMenu(const QPoint&);
|
||||
void editPost();
|
||||
void togglePinPost();
|
||||
void showAuthorInPeople();
|
||||
void tabCloseRequested(int index);
|
||||
void updateSorting(int);
|
||||
|
||||
@ -480,10 +480,21 @@ class PostSorter
|
||||
{
|
||||
public:
|
||||
|
||||
PostSorter(RsPostedPostsModel::SortingStrategy s) : mSortingStrategy(s) {}
|
||||
PostSorter(RsPostedPostsModel::SortingStrategy s, const RsTlvGxsMsgIdSet& pinned_posts)
|
||||
: mSortingStrategy(s), mPinnedPosts(pinned_posts) {}
|
||||
|
||||
bool operator()(const RsPostedPost& p1,const RsPostedPost& p2) const
|
||||
{
|
||||
// Pinned ("stuck") posts are always shown on top of the feed,
|
||||
// regardless of the currently selected sorting strategy. This
|
||||
// mirrors the behaviour already implemented for forums.
|
||||
|
||||
bool p1_pinned = mPinnedPosts.ids.find(p1.mMeta.mMsgId) != mPinnedPosts.ids.end();
|
||||
bool p2_pinned = mPinnedPosts.ids.find(p2.mMeta.mMsgId) != mPinnedPosts.ids.end();
|
||||
|
||||
if(p1_pinned != p2_pinned)
|
||||
return p1_pinned;
|
||||
|
||||
switch(mSortingStrategy)
|
||||
{
|
||||
default:
|
||||
@ -495,6 +506,7 @@ public:
|
||||
|
||||
private:
|
||||
RsPostedPostsModel::SortingStrategy mSortingStrategy;
|
||||
const RsTlvGxsMsgIdSet& mPinnedPosts;
|
||||
};
|
||||
|
||||
Qt::ItemFlags RsPostedPostsModel::flags(const QModelIndex& index) const
|
||||
@ -510,7 +522,7 @@ void RsPostedPostsModel::setSortingStrategy(RsPostedPostsModel::SortingStrategy
|
||||
preMods();
|
||||
|
||||
mSortingStrategy = s;
|
||||
std::sort(mPosts.begin(),mPosts.end(), PostSorter(s));
|
||||
std::sort(mPosts.begin(),mPosts.end(), PostSorter(s,mPostedGroup.mPinnedPosts));
|
||||
|
||||
postMods();
|
||||
}
|
||||
@ -564,7 +576,7 @@ void RsPostedPostsModel::setPosts(const RsPostedGroup& group, std::vector<RsPost
|
||||
|
||||
createPostsArray(posts);
|
||||
|
||||
std::sort(mPosts.begin(),mPosts.end(), PostSorter(mSortingStrategy));
|
||||
std::sort(mPosts.begin(),mPosts.end(), PostSorter(mSortingStrategy,mPostedGroup.mPinnedPosts));
|
||||
|
||||
uint32_t tmpval;
|
||||
setFilter(QStringList(),tmpval);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user