mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-08-01 10:46:23 -04:00
started creation of board model. Does not compile yet.
This commit is contained in:
parent
4fc670695d
commit
7db48990c3
6 changed files with 1604 additions and 5 deletions
|
@ -21,7 +21,7 @@
|
||||||
#include "PostedDialog.h"
|
#include "PostedDialog.h"
|
||||||
#include "PostedItem.h"
|
#include "PostedItem.h"
|
||||||
#include "PostedGroupDialog.h"
|
#include "PostedGroupDialog.h"
|
||||||
#include "PostedListWidget.h"
|
#include "PostedListWidgetWithModel.h"
|
||||||
#include "PostedUserNotify.h"
|
#include "PostedUserNotify.h"
|
||||||
#include "gui/gxs/GxsGroupShareKey.h"
|
#include "gui/gxs/GxsGroupShareKey.h"
|
||||||
#include "gui/settings/rsharesettings.h"
|
#include "gui/settings/rsharesettings.h"
|
||||||
|
@ -195,7 +195,7 @@ int PostedDialog::shareKeyType()
|
||||||
|
|
||||||
GxsMessageFrameWidget *PostedDialog::createMessageFrameWidget(const RsGxsGroupId &groupId)
|
GxsMessageFrameWidget *PostedDialog::createMessageFrameWidget(const RsGxsGroupId &groupId)
|
||||||
{
|
{
|
||||||
return new PostedListWidget(groupId);
|
return new PostedListWidgetWithModel(groupId);
|
||||||
}
|
}
|
||||||
|
|
||||||
RsGxsCommentService *PostedDialog::getCommentService()
|
RsGxsCommentService *PostedDialog::getCommentService()
|
||||||
|
|
146
retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.h
Normal file
146
retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.h
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* retroshare-gui/src/gui/gxschannels/BoardPostsWidget.h *
|
||||||
|
* *
|
||||||
|
* Copyright 2013 by 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/>. *
|
||||||
|
* *
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _GXS_CHANNELPOSTSWIDGET_H
|
||||||
|
#define _GXS_CHANNELPOSTSWIDGET_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <QStyledItemDelegate>
|
||||||
|
|
||||||
|
#include "retroshare/rsposted.h"
|
||||||
|
|
||||||
|
#include "gui/gxs/GxsMessageFramePostWidget.h"
|
||||||
|
#include "gui/feeds/FeedHolder.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class PostedListWidgetWithModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
class QTreeWidgetItem;
|
||||||
|
class QSortFilterProxyModel;
|
||||||
|
class RsPostedPostsModel;
|
||||||
|
|
||||||
|
class PostedPostDelegate: public QAbstractItemDelegate
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
PostedPostDelegate(QObject *parent=0) : QAbstractItemDelegate(parent){}
|
||||||
|
virtual ~PostedPostDelegate(){}
|
||||||
|
|
||||||
|
void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const override;
|
||||||
|
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||||
|
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const override;
|
||||||
|
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||||
|
|
||||||
|
int cellSize(const QFont& font) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PostedListWidgetWithModel: public GxsMessageFrameWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* Filters */
|
||||||
|
enum Filter {
|
||||||
|
SORT_TITLE = 1,
|
||||||
|
SORT_MSG = 2,
|
||||||
|
SORT_FILE_NAME = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Default Constructor */
|
||||||
|
PostedListWidgetWithModel(const RsGxsGroupId &postedId, QWidget *parent = 0);
|
||||||
|
/** Default Destructor */
|
||||||
|
~PostedListWidgetWithModel();
|
||||||
|
|
||||||
|
/* GxsMessageFrameWidget */
|
||||||
|
virtual QIcon groupIcon() override;
|
||||||
|
virtual void groupIdChanged() override { updateDisplay(true); }
|
||||||
|
virtual QString groupName(bool) override ;
|
||||||
|
virtual bool navigate(const RsGxsMessageId&) override;
|
||||||
|
|
||||||
|
void updateDisplay(bool complete) ;
|
||||||
|
|
||||||
|
#ifdef TODO
|
||||||
|
/* FeedHolder */
|
||||||
|
virtual QScrollArea *getScrollArea();
|
||||||
|
virtual void deleteFeedItem(FeedItem *feedItem, uint32_t type);
|
||||||
|
virtual void openChat(const RsPeerId& peerId);
|
||||||
|
#endif
|
||||||
|
virtual void openComments(uint32_t type, const RsGxsGroupId &groupId, const QVector<RsGxsMessageId> &msg_versions, const RsGxsMessageId &msgId, const QString &title);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* GxsMessageFramePostWidget */
|
||||||
|
virtual void groupNameChanged(const QString &name);
|
||||||
|
|
||||||
|
#ifdef TODO
|
||||||
|
virtual bool insertGroupData(const RsGxsGenericGroupData *data) override;
|
||||||
|
#endif
|
||||||
|
virtual void blank() ;
|
||||||
|
|
||||||
|
#ifdef TODO
|
||||||
|
virtual bool getGroupData(RsGxsGenericGroupData *& data) override;
|
||||||
|
virtual void getMsgData(const std::set<RsGxsMessageId>& msgIds,std::vector<RsGxsGenericMsgData*>& posts) override;
|
||||||
|
virtual void getAllMsgData(std::vector<RsGxsGenericMsgData*>& posts) override;
|
||||||
|
virtual void insertPosts(const std::vector<RsGxsGenericMsgData*>& posts) override;
|
||||||
|
virtual void insertAllPosts(const std::vector<RsGxsGenericMsgData*>& posts, GxsMessageFramePostThread *thread) override;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* GxsMessageFrameWidget */
|
||||||
|
virtual void setAllMessagesReadDo(bool read, uint32_t &token);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void updateGroupData();
|
||||||
|
void createMsg();
|
||||||
|
void subscribeGroup(bool subscribe);
|
||||||
|
void setViewMode(int viewMode);
|
||||||
|
void settingsChanged();
|
||||||
|
void handlePostsTreeSizeChange(QSize s);
|
||||||
|
void postChannelPostLoad();
|
||||||
|
void postContextMenu(const QPoint&);
|
||||||
|
void copyMessageLink();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void sortColumnFiles(int col,Qt::SortOrder so);
|
||||||
|
void sortColumnPostFiles(int col,Qt::SortOrder so);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void processSettings(bool load);
|
||||||
|
int viewMode();
|
||||||
|
|
||||||
|
void insertBoardDetails(const RsPostedGroup &group);
|
||||||
|
void handleEvent_main_thread(std::shared_ptr<const RsEvent> event);
|
||||||
|
|
||||||
|
private:
|
||||||
|
RsPostedGroup mGroup;
|
||||||
|
RsEventsHandlerId_t mEventHandlerId ;
|
||||||
|
|
||||||
|
RsPostedPostsModel *mPostedPostsModel;
|
||||||
|
PostedPostDelegate *mPostedPostsDelegate;
|
||||||
|
|
||||||
|
RsGxsMessageId mSelectedPost;
|
||||||
|
|
||||||
|
/* UI - from Designer */
|
||||||
|
Ui::PostedListWidgetWithModel *ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
566
retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.ui
Normal file
566
retroshare-gui/src/gui/Posted/PostedListWidgetWithModel.ui
Normal file
|
@ -0,0 +1,566 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>PostedListWidgetWithModel</class>
|
||||||
|
<widget class="QWidget" name="PostedListWidgetWithModel">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>950</width>
|
||||||
|
<height>771</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_5">
|
||||||
|
<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>
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QFrame" name="infoframe">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::StyledPanel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Raised</enum>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_3">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QGroupBox" name="infoGroupBox">
|
||||||
|
<property name="autoFillBackground">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>Board Details</string>
|
||||||
|
</property>
|
||||||
|
<property name="flat">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<layout class="QFormLayout" name="formLayout">
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Popularity</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLabel" name="poplabel">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>0</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="infoPostsLabel">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Posts</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QLabel" name="infoPosts">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true">0</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QLabel" name="createdlabel">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Created</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<widget class="QLabel" name="createdinfolabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>unknown</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Administrator:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="1">
|
||||||
|
<widget class="GxsIdLabel" name="infoAdministrator">
|
||||||
|
<property name="text">
|
||||||
|
<string>unknown</string>
|
||||||
|
</property>
|
||||||
|
<property name="openExternalLinks">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="0">
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Distribution:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="1">
|
||||||
|
<widget class="QLabel" name="infoDistribution">
|
||||||
|
<property name="text">
|
||||||
|
<string>unknown</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="infoLastPostLabel">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Last Post:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QLabel" name="infoLastPost">
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true">unknown</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="logoLabel">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>64</width>
|
||||||
|
<height>64</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>64</width>
|
||||||
|
<height>64</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="pixmap">
|
||||||
|
<pixmap resource="../icons.qrc">:/icons/png/postedlinks.png</pixmap>
|
||||||
|
</property>
|
||||||
|
<property name="scaledContents">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLabel" name="namelabel">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>14</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>TextLabel</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>421</width>
|
||||||
|
<height>114</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QTextBrowser" name="infoDescription">
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
|
<property name="html">
|
||||||
|
<string notr="true"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||||
|
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||||
|
p, li { white-space: pre-wrap; }
|
||||||
|
</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;">
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Description</span></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
|
<property name="openExternalLinks">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="openLinks">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="RSTreeView" name="postsTree"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QFrame" name="headerFrame">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::Box</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Sunken</enum>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="SubscribeToolButton" name="subscribeToolButton">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>50</weight>
|
||||||
|
<italic>false</italic>
|
||||||
|
<bold>false</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true">Subscribe</string>
|
||||||
|
</property>
|
||||||
|
<property name="autoRaise">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="submitPostButton">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Create Post</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="Posted_images.qrc">
|
||||||
|
<normaloff>:/images/write.png</normaloff>:/images/write.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>24</width>
|
||||||
|
<height>24</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolButtonStyle">
|
||||||
|
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||||
|
</property>
|
||||||
|
<property name="autoRaise">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="comboBox">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p><span style=" font-family:'-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol'; font-size:14px; color:#24292e; background-color:#ffffff;">Select sorting</span></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>24</width>
|
||||||
|
<height>24</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Hot</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../icons.qrc">
|
||||||
|
<normaloff>:/icons/png/flame.png</normaloff>:/icons/png/flame.png</iconset>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>New</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../icons.qrc">
|
||||||
|
<normaloff>:/icons/png/new.png</normaloff>:/icons/png/new.png</iconset>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Top</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../icons.qrc">
|
||||||
|
<normaloff>:/icons/png/top.png</normaloff>:/icons/png/top.png</iconset>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="classicViewButton">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Classic view</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="Posted_images.qrc">
|
||||||
|
<normaloff>:/images/classic.png</normaloff>:/images/classic.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>24</width>
|
||||||
|
<height>24</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="flat">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="cardViewButton">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Card View</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="Posted_images.qrc">
|
||||||
|
<normaloff>:/images/card.png</normaloff>:/images/card.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>24</width>
|
||||||
|
<height>24</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="flat">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="prevButton">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Previous</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../icons.qrc">
|
||||||
|
<normaloff>:/icons/png/arrow-left.png</normaloff>:/icons/png/arrow-left.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="showLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>1-10</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="nextButton">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Next</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../icons.qrc">
|
||||||
|
<normaloff>:/icons/png/arrow-right.png</normaloff>:/icons/png/arrow-right.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="GxsIdChooser" name="idChooser">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Default identity used when voting</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>GxsIdLabel</class>
|
||||||
|
<extends>QLabel</extends>
|
||||||
|
<header>gui/gxs/GxsIdLabel.h</header>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>SubscribeToolButton</class>
|
||||||
|
<extends>QToolButton</extends>
|
||||||
|
<header>gui/common/SubscribeToolButton.h</header>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>RSTreeView</class>
|
||||||
|
<extends>QTreeView</extends>
|
||||||
|
<header>gui/common/RSTreeView.h</header>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>GxsIdChooser</class>
|
||||||
|
<extends>QComboBox</extends>
|
||||||
|
<header>gui/gxs/GxsIdChooser.h</header>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources>
|
||||||
|
<include location="../icons.qrc"/>
|
||||||
|
<include location="Posted_images.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
688
retroshare-gui/src/gui/Posted/PostedPostsModel.cpp
Normal file
688
retroshare-gui/src/gui/Posted/PostedPostsModel.cpp
Normal file
|
@ -0,0 +1,688 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* retroshare-gui/src/gui/gxschannels/GxsChannelPostsModel.cpp *
|
||||||
|
* *
|
||||||
|
* Copyright 2020 by Cyril Soler <csoler@users.sourceforge.net> *
|
||||||
|
* *
|
||||||
|
* 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 <QApplication>
|
||||||
|
#include <QFontMetrics>
|
||||||
|
#include <QModelIndex>
|
||||||
|
#include <QIcon>
|
||||||
|
|
||||||
|
#include "retroshare/rsgxsflags.h"
|
||||||
|
#include "retroshare/rsexpr.h"
|
||||||
|
|
||||||
|
#include "gui/common/FilesDefs.h"
|
||||||
|
#include "util/qtthreadsutils.h"
|
||||||
|
#include "util/HandleRichText.h"
|
||||||
|
#include "util/DateTime.h"
|
||||||
|
|
||||||
|
#include "PostedPostsModel.h"
|
||||||
|
|
||||||
|
//#define DEBUG_CHANNEL_MODEL
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(RsMsgMetaData)
|
||||||
|
Q_DECLARE_METATYPE(RsPostedPost)
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& o, const QModelIndex& i);// defined elsewhere
|
||||||
|
|
||||||
|
RsPostedPostsModel::RsPostedPostsModel(QObject *parent)
|
||||||
|
: QAbstractItemModel(parent), mTreeMode(TREE_MODE_PLAIN), mColumns(6)
|
||||||
|
{
|
||||||
|
initEmptyHierarchy();
|
||||||
|
|
||||||
|
mEventHandlerId = 0;
|
||||||
|
// Needs to be asynced because this function is called by another thread!
|
||||||
|
|
||||||
|
rsEvents->registerEventsHandler( [this](std::shared_ptr<const RsEvent> event)
|
||||||
|
{
|
||||||
|
RsQThreadUtils::postToObject([=](){ handleEvent_main_thread(event); }, this );
|
||||||
|
}, mEventHandlerId, RsEventType::GXS_CHANNELS );
|
||||||
|
}
|
||||||
|
|
||||||
|
RsPostedPostsModel::~RsPostedPostsModel()
|
||||||
|
{
|
||||||
|
rsEvents->unregisterEventsHandler(mEventHandlerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RsPostedPostsModel::handleEvent_main_thread(std::shared_ptr<const RsEvent> event)
|
||||||
|
{
|
||||||
|
const RsGxsPostedEvent *e = dynamic_cast<const RsGxsPostedEvent*>(event.get());
|
||||||
|
|
||||||
|
if(!e)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch(e->mPostedEventCode)
|
||||||
|
{
|
||||||
|
case RsPostedEventCode::UPDATED_MESSAGE:
|
||||||
|
case RsPostedEventCode::READ_STATUS_CHANGED:
|
||||||
|
{
|
||||||
|
// Normally we should just emit dataChanged() on the index of the data that has changed:
|
||||||
|
//
|
||||||
|
// We need to update the data!
|
||||||
|
|
||||||
|
if(e->mPostedGroupId == mPostedGroup.mMeta.mGroupId)
|
||||||
|
RsThread::async([this, e]()
|
||||||
|
{
|
||||||
|
// 1 - get message data from p3GxsChannels
|
||||||
|
|
||||||
|
std::vector<RsPostedPost> posts;
|
||||||
|
std::vector<RsGxsComment> comments;
|
||||||
|
std::vector<RsGxsVote> votes;
|
||||||
|
|
||||||
|
if(!rsPosted->getBoardContent(mPostedGroup.mMeta.mGroupId,std::set<RsGxsMessageId>{ e->mPostedMsgId }, posts,comments,votes))
|
||||||
|
{
|
||||||
|
std::cerr << __PRETTY_FUNCTION__ << " failed to retrieve channel message data for channel/msg " << e->mChannelGroupId << "/" << e->mChannelMsgId << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2 - update the model in the UI thread.
|
||||||
|
|
||||||
|
RsQThreadUtils::postToObject( [posts,comments,votes,this]()
|
||||||
|
{
|
||||||
|
for(uint32_t i=0;i<posts.size();++i)
|
||||||
|
{
|
||||||
|
// linear search. Not good at all, but normally this is for a single post.
|
||||||
|
|
||||||
|
for(uint32_t j=0;j<mPosts.size();++j)
|
||||||
|
if(mPosts[j].mMeta.mMsgId == posts[i].mMeta.mMsgId)
|
||||||
|
{
|
||||||
|
mPosts[j] = posts[i];
|
||||||
|
|
||||||
|
emit dataChanged(createIndex(0,0,(void*)NULL), createIndex(mFilteredPosts.size(),mColumns-1,(void*)NULL));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},this);
|
||||||
|
});
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RsPostedPostsModel::initEmptyHierarchy()
|
||||||
|
{
|
||||||
|
preMods();
|
||||||
|
|
||||||
|
mPosts.clear();
|
||||||
|
mFilteredPosts.clear();
|
||||||
|
|
||||||
|
postMods();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RsPostedPostsModel::preMods()
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
}
|
||||||
|
void RsPostedPostsModel::postMods()
|
||||||
|
{
|
||||||
|
endResetModel();
|
||||||
|
|
||||||
|
emit dataChanged(createIndex(0,0,(void*)NULL), createIndex(mFilteredPosts.size(),mColumns-1,(void*)NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
void RsPostedPostsModel::setFilter(const QStringList& strings, uint32_t& count)
|
||||||
|
{
|
||||||
|
preMods();
|
||||||
|
|
||||||
|
beginRemoveRows(QModelIndex(),0,rowCount()-1);
|
||||||
|
endRemoveRows();
|
||||||
|
|
||||||
|
if(strings.empty())
|
||||||
|
{
|
||||||
|
mFilteredPosts.clear();
|
||||||
|
for(int i=0;i<mPosts.size();++i)
|
||||||
|
mFilteredPosts.push_back(i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mFilteredPosts.clear();
|
||||||
|
//mFilteredPosts.push_back(0);
|
||||||
|
|
||||||
|
for(int i=0;i<mPosts.size();++i)
|
||||||
|
{
|
||||||
|
bool passes_strings = true;
|
||||||
|
|
||||||
|
for(auto& s:strings)
|
||||||
|
passes_strings = passes_strings && QString::fromStdString(mPosts[i].mMeta.mMsgName).contains(s,Qt::CaseInsensitive);
|
||||||
|
|
||||||
|
if(passes_strings)
|
||||||
|
mFilteredPosts.push_back(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
count = mFilteredPosts.size();
|
||||||
|
|
||||||
|
std::cerr << "After filtering: " << count << " posts remain." << std::endl;
|
||||||
|
|
||||||
|
beginInsertRows(QModelIndex(),0,rowCount()-1);
|
||||||
|
endInsertRows();
|
||||||
|
|
||||||
|
postMods();
|
||||||
|
}
|
||||||
|
|
||||||
|
int RsPostedPostsModel::rowCount(const QModelIndex& parent) const
|
||||||
|
{
|
||||||
|
if(parent.column() > 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(mFilteredPosts.empty()) // security. Should never happen.
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(!parent.isValid())
|
||||||
|
return mFilteredPosts.size() ;
|
||||||
|
|
||||||
|
RsErr() << __PRETTY_FUNCTION__ << " rowCount cannot figure out the porper number of rows." << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RsPostedPostsModel::columnCount(const QModelIndex &/*parent*/) const
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RsPostedPostsModel::getPostData(const QModelIndex& i,RsPostedPost& fmpe) const
|
||||||
|
{
|
||||||
|
if(!i.isValid())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
quintptr ref = i.internalId();
|
||||||
|
uint32_t entry = 0;
|
||||||
|
|
||||||
|
if(!convertRefPointerToTabEntry(ref,entry) || entry >= mFilteredPosts.size())
|
||||||
|
return false ;
|
||||||
|
|
||||||
|
fmpe = mPosts[mFilteredPosts[entry]];
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RsPostedPostsModel::hasChildren(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
if(!parent.isValid())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false; // by default, no post has children
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RsPostedPostsModel::convertTabEntryToRefPointer(uint32_t entry,quintptr& ref)
|
||||||
|
{
|
||||||
|
// the pointer is formed the following way:
|
||||||
|
//
|
||||||
|
// [ 32 bits ]
|
||||||
|
//
|
||||||
|
// This means that the whole software has the following build-in limitation:
|
||||||
|
// * 4 B simultaenous posts. Should be enough !
|
||||||
|
|
||||||
|
ref = (intptr_t)(entry+1);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RsPostedPostsModel::convertRefPointerToTabEntry(quintptr ref, uint32_t& entry)
|
||||||
|
{
|
||||||
|
intptr_t val = (intptr_t)ref;
|
||||||
|
|
||||||
|
if(val > (1<<30)) // make sure the pointer is an int that fits in 32bits and not too big which would look suspicious
|
||||||
|
{
|
||||||
|
RsErr() << "(EE) trying to make a ChannelPostsModelIndex out of a number that is larger than 2^32-1 !" << std::endl;
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
if(val==0)
|
||||||
|
{
|
||||||
|
RsErr() << "(EE) trying to make a ChannelPostsModelIndex out of index 0." << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = val - 1;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex RsPostedPostsModel::index(int row, int column, const QModelIndex & parent) const
|
||||||
|
{
|
||||||
|
if(row < 0 || column < 0)
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
quintptr ref = getChildRef(parent.internalId(),row);
|
||||||
|
|
||||||
|
#ifdef DEBUG_CHANNEL_MODEL
|
||||||
|
std::cerr << "index-3(" << row << "," << column << " parent=" << parent << ") : " << createIndex(row,column,ref) << std::endl;
|
||||||
|
#endif
|
||||||
|
return createIndex(row,column,ref) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex RsPostedPostsModel::parent(const QModelIndex& index) const
|
||||||
|
{
|
||||||
|
if(!index.isValid())
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
return QModelIndex(); // there's no hierarchy here. So nothing to do!
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags RsPostedPostsModel::flags(const QModelIndex& index) const
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return QAbstractItemModel::flags(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
quintptr RsPostedPostsModel::getChildRef(quintptr ref,int index) const
|
||||||
|
{
|
||||||
|
if (index < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(ref == quintptr(0))
|
||||||
|
{
|
||||||
|
quintptr new_ref;
|
||||||
|
convertTabEntryToRefPointer(index,new_ref);
|
||||||
|
return new_ref;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
quintptr RsPostedPostsModel::getParentRow(quintptr ref,int& row) const
|
||||||
|
{
|
||||||
|
PostedPostsModelIndex ref_entry;
|
||||||
|
|
||||||
|
if(!convertRefPointerToTabEntry(ref,ref_entry) || ref_entry >= mFilteredPosts.size())
|
||||||
|
return 0 ;
|
||||||
|
|
||||||
|
if(ref_entry == 0)
|
||||||
|
{
|
||||||
|
RsErr() << "getParentRow() shouldn't be asked for the parent of NULL" << std::endl;
|
||||||
|
row = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
row = ref_entry-1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RsPostedPostsModel::getChildrenCount(quintptr ref) const
|
||||||
|
{
|
||||||
|
uint32_t entry = 0 ;
|
||||||
|
|
||||||
|
if(ref == quintptr(0))
|
||||||
|
return rowCount()-1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant RsPostedPostsModel::data(const QModelIndex& index, int role) const
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_CHANNEL_MODEL
|
||||||
|
std::cerr << "calling data(" << index << ") role=" << role << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(!index.isValid())
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
switch(role)
|
||||||
|
{
|
||||||
|
case Qt::SizeHintRole: return sizeHintRole(index.column()) ;
|
||||||
|
case Qt::StatusTipRole:return QVariant();
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
quintptr ref = (index.isValid())?index.internalId():0 ;
|
||||||
|
uint32_t entry = 0;
|
||||||
|
|
||||||
|
#ifdef DEBUG_CHANNEL_MODEL
|
||||||
|
std::cerr << "data(" << index << ")" ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(!ref)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_CHANNEL_MODEL
|
||||||
|
std::cerr << " [empty]" << std::endl;
|
||||||
|
#endif
|
||||||
|
return QVariant() ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!convertRefPointerToTabEntry(ref,entry) || entry >= mFilteredPosts.size())
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_CHANNEL_MODEL
|
||||||
|
std::cerr << "Bad pointer: " << (void*)ref << std::endl;
|
||||||
|
#endif
|
||||||
|
return QVariant() ;
|
||||||
|
}
|
||||||
|
|
||||||
|
const RsPostedPost& fmpe(mPosts[mFilteredPosts[entry]]);
|
||||||
|
|
||||||
|
switch(role)
|
||||||
|
{
|
||||||
|
case Qt::DisplayRole: return displayRole (fmpe,index.column()) ;
|
||||||
|
case Qt::UserRole: return userRole (fmpe,index.column()) ;
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant RsPostedPostsModel::sizeHintRole(int col) const
|
||||||
|
{
|
||||||
|
float factor = QFontMetricsF(QApplication::font()).height()/14.0f ;
|
||||||
|
|
||||||
|
return QVariant( QSize(factor * 170, factor*14 ));
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant RsPostedPostsModel::displayRole(const RsPostedPost& fmpe,int col) const
|
||||||
|
{
|
||||||
|
switch(col)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
return QString::fromUtf8(fmpe.mMeta.mMsgName.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return QVariant("[ERROR]");
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant RsPostedPostsModel::userRole(const RsPostedPost& fmpe,int col) const
|
||||||
|
{
|
||||||
|
switch(col)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
return QVariant::fromValue(fmpe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const RsGxsGroupId& RsPostedPostsModel::currentGroupId() const
|
||||||
|
{
|
||||||
|
return mPostedGroup.mMeta.mGroupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RsPostedPostsModel::updateBoard(const RsGxsGroupId& board_group_id)
|
||||||
|
{
|
||||||
|
if(board_group_id.isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
|
update_posts(board_group_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RsPostedPostsModel::clear()
|
||||||
|
{
|
||||||
|
preMods();
|
||||||
|
|
||||||
|
mPosts.clear();
|
||||||
|
initEmptyHierarchy();
|
||||||
|
|
||||||
|
postMods();
|
||||||
|
emit boardPostsLoaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const RsPostedPost& p1,const RsPostedPost& p2)
|
||||||
|
{
|
||||||
|
return p1.mMeta.mPublishTs > p2.mMeta.mPublishTs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RsPostedPostsModel::setPosts(const RsPostedGroup& group, std::vector<RsPostedPost>& posts)
|
||||||
|
{
|
||||||
|
preMods();
|
||||||
|
|
||||||
|
beginRemoveRows(QModelIndex(),0,rowCount()-1);
|
||||||
|
endRemoveRows();
|
||||||
|
|
||||||
|
mPosts.clear();
|
||||||
|
mPostedGroup = group;
|
||||||
|
|
||||||
|
createPostsArray(posts);
|
||||||
|
|
||||||
|
std::sort(mPosts.begin(),mPosts.end());
|
||||||
|
|
||||||
|
mFilteredPosts.clear();
|
||||||
|
for(int i=0;i<mPosts.size();++i)
|
||||||
|
mFilteredPosts.push_back(i);
|
||||||
|
|
||||||
|
beginInsertRows(QModelIndex(),0,rowCount()-1);
|
||||||
|
endInsertRows();
|
||||||
|
|
||||||
|
postMods();
|
||||||
|
|
||||||
|
emit boardPostsLoaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RsPostedPostsModel::update_posts(const RsGxsGroupId& group_id)
|
||||||
|
{
|
||||||
|
if(group_id.isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
|
RsThread::async([this, group_id]()
|
||||||
|
{
|
||||||
|
// 1 - get message data from p3GxsChannels
|
||||||
|
|
||||||
|
std::list<RsGxsGroupId> groupIds;
|
||||||
|
std::vector<RsMsgMetaData> msg_metas;
|
||||||
|
std::vector<RsPostedGroup> groups;
|
||||||
|
|
||||||
|
groupIds.push_back(group_id);
|
||||||
|
|
||||||
|
if(!rsPosted->getBoardsInfo(groupIds,groups) || groups.size() != 1)
|
||||||
|
{
|
||||||
|
std::cerr << __PRETTY_FUNCTION__ << " failed to retrieve channel group info for channel " << group_id << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RsPostedGroup group = groups[0];
|
||||||
|
|
||||||
|
// We use the heap because the arrays need to be stored accross async
|
||||||
|
|
||||||
|
std::vector<RsPostedPost> *posts = new std::vector<RsPostedPost>();
|
||||||
|
std::vector<RsGxsComment> *comments = new std::vector<RsGxsComment>();
|
||||||
|
std::vector<RsGxsVote> *votes = new std::vector<RsGxsVote>();
|
||||||
|
|
||||||
|
if(!rsPosted->getBoardContent(group_id, *posts,*comments,*votes))
|
||||||
|
{
|
||||||
|
std::cerr << __PRETTY_FUNCTION__ << " failed to retrieve channel messages for channel " << group_id << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2 - update the model in the UI thread.
|
||||||
|
|
||||||
|
RsQThreadUtils::postToObject( [group,posts,comments,votes,this]()
|
||||||
|
{
|
||||||
|
/* Here it goes any code you want to be executed on the Qt Gui
|
||||||
|
* thread, for example to update the data model with new information
|
||||||
|
* after a blocking call to RetroShare API complete, note that
|
||||||
|
* Qt::QueuedConnection is important!
|
||||||
|
*/
|
||||||
|
|
||||||
|
setPosts(group,*posts) ;
|
||||||
|
|
||||||
|
delete posts;
|
||||||
|
delete comments;
|
||||||
|
delete votes;
|
||||||
|
|
||||||
|
}, this );
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool decreasing_time_comp(const std::pair<time_t,RsGxsMessageId>& e1,const std::pair<time_t,RsGxsMessageId>& e2) { return e2.first < e1.first ; }
|
||||||
|
|
||||||
|
void RsPostedPostsModel::createPostsArray(std::vector<RsPostedPost>& posts)
|
||||||
|
{
|
||||||
|
// Collect new versions of posts if any. For now Boards do not have versions, but if that ever happens, we'll be handlign it already. This code
|
||||||
|
// is a blind copy of the channel code.
|
||||||
|
|
||||||
|
#ifdef DEBUG_CHANNEL_MODEL
|
||||||
|
std::cerr << "Inserting channel posts" << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::vector<uint32_t> new_versions ;
|
||||||
|
for (uint32_t i=0;i<posts.size();++i)
|
||||||
|
{
|
||||||
|
if(posts[i].mMeta.mOrigMsgId == posts[i].mMeta.mMsgId)
|
||||||
|
posts[i].mMeta.mOrigMsgId.clear();
|
||||||
|
|
||||||
|
#ifdef DEBUG_CHANNEL_MODEL
|
||||||
|
std::cerr << " " << i << ": name=\"" << posts[i].mMeta.mMsgName << "\" msg_id=" << posts[i].mMeta.mMsgId << ": orig msg id = " << posts[i].mMeta.mOrigMsgId << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(!posts[i].mMeta.mOrigMsgId.isNull())
|
||||||
|
new_versions.push_back(i) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_CHANNEL_MODEL
|
||||||
|
std::cerr << "New versions: " << new_versions.size() << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(!new_versions.empty())
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_CHANNEL_MODEL
|
||||||
|
std::cerr << " New versions present. Replacing them..." << std::endl;
|
||||||
|
std::cerr << " Creating search map." << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// make a quick search map
|
||||||
|
std::map<RsGxsMessageId,uint32_t> search_map ;
|
||||||
|
for (uint32_t i=0;i<posts.size();++i)
|
||||||
|
search_map[posts[i].mMeta.mMsgId] = i ;
|
||||||
|
|
||||||
|
for(uint32_t i=0;i<new_versions.size();++i)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_CHANNEL_MODEL
|
||||||
|
std::cerr << " Taking care of new version at index " << new_versions[i] << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint32_t current_index = new_versions[i] ;
|
||||||
|
uint32_t source_index = new_versions[i] ;
|
||||||
|
#ifdef DEBUG_CHANNEL_MODEL
|
||||||
|
RsGxsMessageId source_msg_id = posts[source_index].mMeta.mMsgId ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// What we do is everytime we find a replacement post, we climb up the replacement graph until we find the original post
|
||||||
|
// (or the most recent version of it). When we reach this post, we replace it with the data of the source post.
|
||||||
|
// In the mean time, all other posts have their MsgId cleared, so that the posts are removed from the list.
|
||||||
|
|
||||||
|
//std::vector<uint32_t> versions ;
|
||||||
|
std::map<RsGxsMessageId,uint32_t>::const_iterator vit ;
|
||||||
|
|
||||||
|
while(search_map.end() != (vit=search_map.find(posts[current_index].mMeta.mOrigMsgId)))
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_CHANNEL_MODEL
|
||||||
|
std::cerr << " post at index " << current_index << " replaces a post at position " << vit->second ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Now replace the post only if the new versionis more recent. It may happen indeed that the same post has been corrected multiple
|
||||||
|
// times. In this case, we only need to replace the post with the newest version
|
||||||
|
|
||||||
|
//uint32_t prev_index = current_index ;
|
||||||
|
current_index = vit->second ;
|
||||||
|
|
||||||
|
if(posts[current_index].mMeta.mMsgId.isNull()) // This handles the branching situation where this post has been already erased. No need to go down further.
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_CHANNEL_MODEL
|
||||||
|
std::cerr << " already erased. Stopping." << std::endl;
|
||||||
|
#endif
|
||||||
|
break ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(posts[current_index].mMeta.mPublishTs < posts[source_index].mMeta.mPublishTs)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_CHANNEL_MODEL
|
||||||
|
std::cerr << " and is more recent => following" << std::endl;
|
||||||
|
#endif
|
||||||
|
for(std::set<RsGxsMessageId>::const_iterator itt(posts[current_index].mOlderVersions.begin());itt!=posts[current_index].mOlderVersions.end();++itt)
|
||||||
|
posts[source_index].mOlderVersions.insert(*itt);
|
||||||
|
|
||||||
|
posts[source_index].mOlderVersions.insert(posts[current_index].mMeta.mMsgId);
|
||||||
|
posts[current_index].mMeta.mMsgId.clear(); // clear the msg Id so the post will be ignored
|
||||||
|
}
|
||||||
|
#ifdef DEBUG_CHANNEL_MODEL
|
||||||
|
else
|
||||||
|
std::cerr << " but is older -> Stopping" << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_CHANNEL_MODEL
|
||||||
|
std::cerr << "Now adding " << posts.size() << " posts into array structure..." << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mPosts.clear();
|
||||||
|
|
||||||
|
for (std::vector<RsPostedPost>::const_reverse_iterator it = posts.rbegin(); it != posts.rend(); ++it)
|
||||||
|
{
|
||||||
|
if(!(*it).mMeta.mMsgId.isNull())
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_CHANNEL_MODEL
|
||||||
|
std::cerr << " adding post \"" << (*it).mMeta.mMsgName << "\"" << std::endl;
|
||||||
|
#endif
|
||||||
|
mPosts.push_back(*it);
|
||||||
|
}
|
||||||
|
#ifdef DEBUG_CHANNEL_MODEL
|
||||||
|
else
|
||||||
|
std::cerr << " skipped older version post \"" << (*it).mMeta.mMsgName << "\"" << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RsPostedPostsModel::setMsgReadStatus(const QModelIndex& i,bool read_status,bool with_children)
|
||||||
|
{
|
||||||
|
if(!i.isValid())
|
||||||
|
return ;
|
||||||
|
|
||||||
|
// no need to call preMods()/postMods() here because we'renot changing the model
|
||||||
|
|
||||||
|
quintptr ref = i.internalId();
|
||||||
|
uint32_t entry = 0;
|
||||||
|
|
||||||
|
if(!convertRefPointerToTabEntry(ref,entry) || entry >= mFilteredPosts.size())
|
||||||
|
return ;
|
||||||
|
|
||||||
|
#warning TODO
|
||||||
|
// bool has_unread_below, has_read_below;
|
||||||
|
// recursSetMsgReadStatus(entry,read_status,with_children) ;
|
||||||
|
// recursUpdateReadStatusAndTimes(0,has_unread_below,has_read_below);
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex RsPostedPostsModel::getIndexOfMessage(const RsGxsMessageId& mid) const
|
||||||
|
{
|
||||||
|
// Brutal search. This is not so nice, so dont call that in a loop! If too costly, we'll use a map.
|
||||||
|
|
||||||
|
RsGxsMessageId postId = mid;
|
||||||
|
|
||||||
|
for(uint32_t i=0;i<mFilteredPosts.size();++i)
|
||||||
|
{
|
||||||
|
// First look into msg versions, in case the msg is a version of an existing message
|
||||||
|
|
||||||
|
for(auto& msg_id:mPosts[mFilteredPosts[i]].mOlderVersions)
|
||||||
|
if(msg_id == postId)
|
||||||
|
{
|
||||||
|
quintptr ref ;
|
||||||
|
convertTabEntryToRefPointer(i,ref); // we dont use i+1 here because i is not a row, but an index in the mPosts tab
|
||||||
|
|
||||||
|
return createIndex(i/mColumns,i%mColumns, ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mPosts[mFilteredPosts[i]].mMeta.mMsgId == postId)
|
||||||
|
{
|
||||||
|
quintptr ref ;
|
||||||
|
convertTabEntryToRefPointer(i,ref); // we dont use i+1 here because i is not a row, but an index in the mPosts tab
|
||||||
|
|
||||||
|
return createIndex(i/mColumns,i%mColumns, ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
197
retroshare-gui/src/gui/Posted/PostedPostsModel.h
Normal file
197
retroshare-gui/src/gui/Posted/PostedPostsModel.h
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* retroshare-gui/src/gui/gxschannels/GxsChannelPostsModel.h *
|
||||||
|
* *
|
||||||
|
* Copyright 2020 by Cyril Soler <csoler@users.sourceforge.net> *
|
||||||
|
* *
|
||||||
|
* 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 "retroshare/rsposted.h"
|
||||||
|
#include "retroshare/rsgxsifacetypes.h"
|
||||||
|
#include "retroshare/rsevents.h"
|
||||||
|
|
||||||
|
#include <QModelIndex>
|
||||||
|
#include <QColor>
|
||||||
|
|
||||||
|
// This class holds the actual hierarchy of posts, represented by identifiers
|
||||||
|
// It is responsible for auto-updating when necessary and holds a mutex to allow the Model to
|
||||||
|
// safely access the data.
|
||||||
|
|
||||||
|
// The model contains a post in place 0 that is the parent of all posts.
|
||||||
|
|
||||||
|
typedef uint32_t PostedPostsModelIndex;
|
||||||
|
|
||||||
|
// struct ChannelPostsModelPostEntry
|
||||||
|
// {
|
||||||
|
// ChannelPostsModelPostEntry() : mPublishTs(0),mPostFlags(0),mMsgStatus(0),prow(0) {}
|
||||||
|
//
|
||||||
|
// enum { // flags for display of posts. To be used in mPostFlags
|
||||||
|
// FLAG_POST_IS_PINNED = 0x0001,
|
||||||
|
// FLAG_POST_IS_MISSING = 0x0002,
|
||||||
|
// FLAG_POST_IS_REDACTED = 0x0004,
|
||||||
|
// FLAG_POST_HAS_UNREAD_CHILDREN = 0x0008,
|
||||||
|
// FLAG_POST_HAS_READ_CHILDREN = 0x0010,
|
||||||
|
// FLAG_POST_PASSES_FILTER = 0x0020,
|
||||||
|
// FLAG_POST_CHILDREN_PASSES_FILTER = 0x0040,
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// std::string mTitle ;
|
||||||
|
// RsGxsMessageId mMsgId;
|
||||||
|
// uint32_t mPublishTs;
|
||||||
|
// uint32_t mPostFlags;
|
||||||
|
// int mMsgStatus;
|
||||||
|
//
|
||||||
|
// int prow ;// parent row, which basically means position in the array of posts
|
||||||
|
// };
|
||||||
|
|
||||||
|
// This class is the item model used by Qt to display the information
|
||||||
|
|
||||||
|
class RsPostedPostsModel : public QAbstractItemModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit RsPostedPostsModel(QObject *parent = NULL);
|
||||||
|
virtual ~RsPostedPostsModel() override;
|
||||||
|
|
||||||
|
static const int COLUMN_THREAD_NB_COLUMNS = 0x01;
|
||||||
|
|
||||||
|
enum Columns {
|
||||||
|
COLUMN_POSTS =0x00,
|
||||||
|
COLUMN_THREAD_MSGID =0x01,
|
||||||
|
COLUMN_THREAD_DATA =0x02,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Roles{ SortRole = Qt::UserRole+1,
|
||||||
|
StatusRole = Qt::UserRole+2,
|
||||||
|
FilterRole = Qt::UserRole+3,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum TreeMode{ TREE_MODE_UNKWN = 0x00,
|
||||||
|
TREE_MODE_PLAIN = 0x01,
|
||||||
|
TREE_MODE_FILES = 0x02,
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef TODO
|
||||||
|
enum SortMode{ SORT_MODE_PUBLISH_TS = 0x00,
|
||||||
|
SORT_MODE_CHILDREN_PUBLISH_TS = 0x01,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QModelIndex root() const{ return createIndex(0,0,(void*)NULL) ;}
|
||||||
|
QModelIndex getIndexOfMessage(const RsGxsMessageId& mid) const;
|
||||||
|
|
||||||
|
// This method will asynchroneously update the data
|
||||||
|
|
||||||
|
void updateBoard(const RsGxsGroupId& posted_group_id);
|
||||||
|
const RsGxsGroupId& currentGroupId() const;
|
||||||
|
|
||||||
|
#ifdef TODO
|
||||||
|
void setSortMode(SortMode mode) ;
|
||||||
|
|
||||||
|
void setTextColorRead (QColor color) { mTextColorRead = color;}
|
||||||
|
void setTextColorUnread (QColor color) { mTextColorUnread = color;}
|
||||||
|
void setTextColorUnreadChildren(QColor color) { mTextColorUnreadChildren = color;}
|
||||||
|
void setTextColorNotSubscribed (QColor color) { mTextColorNotSubscribed = color;}
|
||||||
|
void setTextColorMissing (QColor color) { mTextColorMissing = color;}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void setMsgReadStatus(const QModelIndex &i, bool read_status, bool with_children);
|
||||||
|
void setFilter(const QStringList &strings, uint32_t &count) ;
|
||||||
|
|
||||||
|
#ifdef TODO
|
||||||
|
void setAuthorOpinion(const QModelIndex& indx,RsOpinion op);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Helper functions
|
||||||
|
|
||||||
|
bool getPostData(const QModelIndex& i,RsPostedPost& fmpe) const ;
|
||||||
|
void clear() ;
|
||||||
|
|
||||||
|
// AbstractItemModel functions.
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||||
|
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
bool hasChildren(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
|
QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const override;
|
||||||
|
QModelIndex parent(const QModelIndex& child) const override;
|
||||||
|
Qt::ItemFlags flags(const QModelIndex& index) const override;
|
||||||
|
|
||||||
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
|
|
||||||
|
// Custom item roles
|
||||||
|
|
||||||
|
QVariant sizeHintRole (int col) const;
|
||||||
|
QVariant displayRole (const RsPostedPost& fmpe, int col) const;
|
||||||
|
QVariant toolTipRole (const RsPostedPost& fmpe, int col) const;
|
||||||
|
QVariant userRole (const RsPostedPost& fmpe, int col) const;
|
||||||
|
#ifdef TODO
|
||||||
|
QVariant decorationRole(const RsPostedPost& fmpe, int col) const;
|
||||||
|
QVariant pinnedRole (const RsPostedPost& fmpe, int col) const;
|
||||||
|
QVariant missingRole (const RsPostedPost& fmpe, int col) const;
|
||||||
|
QVariant statusRole (const RsPostedPost& fmpe, int col) const;
|
||||||
|
QVariant authorRole (const RsPostedPost& fmpe, int col) const;
|
||||||
|
QVariant sortRole (const RsPostedPost& fmpe, int col) const;
|
||||||
|
QVariant fontRole (const RsPostedPost& fmpe, int col) const;
|
||||||
|
QVariant filterRole (const RsPostedPost& fmpe, int col) const;
|
||||||
|
QVariant textColorRole (const RsPostedPost& fmpe, int col) const;
|
||||||
|
QVariant backgroundRole(const RsPostedPost& fmpe, int col) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief debug_dump
|
||||||
|
* Dumps the hierarchy of posts in the terminal, to allow checking whether the internal representation is correct.
|
||||||
|
*/
|
||||||
|
void debug_dump();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void boardlPostsLoaded(); // emitted after the posts have been loaded.
|
||||||
|
|
||||||
|
private:
|
||||||
|
RsPostedGroup mPostedGroup;
|
||||||
|
|
||||||
|
TreeMode mTreeMode;
|
||||||
|
|
||||||
|
void preMods() ;
|
||||||
|
void postMods() ;
|
||||||
|
|
||||||
|
quintptr getParentRow(quintptr ref,int& row) const;
|
||||||
|
quintptr getChildRef(quintptr ref, int index) const;
|
||||||
|
int getChildrenCount(quintptr ref) const;
|
||||||
|
|
||||||
|
static bool convertTabEntryToRefPointer(uint32_t entry, quintptr &ref);
|
||||||
|
static bool convertRefPointerToTabEntry(quintptr ref,uint32_t& entry);
|
||||||
|
static void computeReputationLevel(uint32_t forum_sign_flags, RsPostedPost& entry);
|
||||||
|
|
||||||
|
void update_posts(const RsGxsGroupId& group_id);
|
||||||
|
|
||||||
|
#ifdef TODO
|
||||||
|
void setForumMessageSummary(const std::vector<RsGxsForumMsg>& messages);
|
||||||
|
void recursUpdateReadStatusAndTimes(ChannelPostsModelIndex i,bool& has_unread_below,bool& has_read_below);
|
||||||
|
uint32_t recursUpdateFilterStatus(ChannelPostsModelIndex i,int column,const QStringList& strings);
|
||||||
|
void recursSetMsgReadStatus(ChannelPostsModelIndex i,bool read_status,bool with_children);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void createPostsArray(std::vector<RsPostedPost> &posts);
|
||||||
|
void setPosts(const RsPostedGroup& group, std::vector<RsPostedPost> &posts);
|
||||||
|
void initEmptyHierarchy();
|
||||||
|
void handleEvent_main_thread(std::shared_ptr<const RsEvent> event);
|
||||||
|
|
||||||
|
std::vector<int> mFilteredPosts; // stores the list of displayes indices due to filtering.
|
||||||
|
std::vector<RsPostedPost> mPosts ; // store the list of posts updated from rsForums.
|
||||||
|
|
||||||
|
RsEventsHandlerId_t mEventHandlerId ;
|
||||||
|
};
|
|
@ -1368,7 +1368,8 @@ gxschannels {
|
||||||
posted {
|
posted {
|
||||||
|
|
||||||
HEADERS += gui/Posted/PostedDialog.h \
|
HEADERS += gui/Posted/PostedDialog.h \
|
||||||
gui/Posted/PostedListWidget.h \
|
gui/Posted/PostedListWidgetWithModel.h \
|
||||||
|
gui/Posted/PostedPostsModel.h \
|
||||||
gui/Posted/PostedItem.h \
|
gui/Posted/PostedItem.h \
|
||||||
gui/Posted/PostedCardView.h \
|
gui/Posted/PostedCardView.h \
|
||||||
gui/Posted/PostedGroupDialog.h \
|
gui/Posted/PostedGroupDialog.h \
|
||||||
|
@ -1380,7 +1381,7 @@ posted {
|
||||||
#gui/Posted/PostedCreateCommentDialog.h \
|
#gui/Posted/PostedCreateCommentDialog.h \
|
||||||
#gui/Posted/PostedComments.h \
|
#gui/Posted/PostedComments.h \
|
||||||
|
|
||||||
FORMS += gui/Posted/PostedListWidget.ui \
|
FORMS += gui/Posted/PostedListWidgetWithModel.ui \
|
||||||
gui/feeds/PostedGroupItem.ui \
|
gui/feeds/PostedGroupItem.ui \
|
||||||
gui/Posted/PostedItem.ui \
|
gui/Posted/PostedItem.ui \
|
||||||
gui/Posted/PostedCardView.ui \
|
gui/Posted/PostedCardView.ui \
|
||||||
|
@ -1391,7 +1392,8 @@ posted {
|
||||||
#gui/Posted/PostedCreateCommentDialog.ui
|
#gui/Posted/PostedCreateCommentDialog.ui
|
||||||
|
|
||||||
SOURCES += gui/Posted/PostedDialog.cpp \
|
SOURCES += gui/Posted/PostedDialog.cpp \
|
||||||
gui/Posted/PostedListWidget.cpp \
|
gui/Posted/PostedListWidgetWithModel.cpp \
|
||||||
|
gui/Posted/PostedPostsModel.cpp \
|
||||||
gui/feeds/PostedGroupItem.cpp \
|
gui/feeds/PostedGroupItem.cpp \
|
||||||
gui/Posted/PostedItem.cpp \
|
gui/Posted/PostedItem.cpp \
|
||||||
gui/Posted/PostedCardView.cpp \
|
gui/Posted/PostedCardView.cpp \
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue