diff --git a/retroshare-gui/src/gui/common/RSTreeView.cpp b/retroshare-gui/src/gui/common/RSTreeView.cpp index da1aa5840..36034166f 100644 --- a/retroshare-gui/src/gui/common/RSTreeView.cpp +++ b/retroshare-gui/src/gui/common/RSTreeView.cpp @@ -24,6 +24,25 @@ RSTreeView::RSTreeView(QWidget *parent) : QTreeView(parent) { + setMouseTracking(false); // normally the default, but who knows if it's not goign to change in the future. +} + +void RSTreeView::mouseMoveEvent(QMouseEvent *e) +{ + QModelIndex idx = indexAt(e->pos()); + + if(idx != selectionModel()->currentIndex()) + selectionModel()->setCurrentIndex(idx,QItemSelectionModel::ClearAndSelect); + + QTreeView::mouseMoveEvent(e); +} + +void RSTreeView::setAutoSelect(bool b) +{ + if(b) + setMouseTracking(true); + else + setMouseTracking(false); } void RSTreeView::resizeEvent(QResizeEvent *e) diff --git a/retroshare-gui/src/gui/common/RSTreeView.h b/retroshare-gui/src/gui/common/RSTreeView.h index f895571f0..f7942ef64 100644 --- a/retroshare-gui/src/gui/common/RSTreeView.h +++ b/retroshare-gui/src/gui/common/RSTreeView.h @@ -33,10 +33,16 @@ public: void setPlaceholderText(const QString &text); + // Use this to make selection automatic based on mouse position. This is useful to trigger selection and therefore editing mode + // in trees that show editing widgets using a QStyledItemDelegate + + void setAutoSelect(bool b); + signals: void sizeChanged(QSize); protected: + virtual void mouseMoveEvent(QMouseEvent *e) override; // overriding so as to manage auto-selection virtual void resizeEvent(QResizeEvent *e) override; virtual void paintEvent(QPaintEvent *event) override; diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsModel.cpp b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsModel.cpp index e0af09eee..6fc4325a5 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsModel.cpp +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsModel.cpp @@ -84,28 +84,6 @@ void RsGxsChannelPostsModel::setTreeMode(TreeMode mode) postMods(); } -#ifdef TODO -void RsGxsChannelPostsModel::setSortMode(SortMode mode) -{ - preMods(); - - mSortMode = mode; - - postMods(); -} - -void RsGxsForumModel::initEmptyHierarchy(std::vector& posts) -{ - preMods(); - - posts.resize(1); // adds a sentinel item - posts[0].mTitle = "Root sentinel post" ; - posts[0].mParent = 0; - - postMods(); -} -#endif - int RsGxsChannelPostsModel::rowCount(const QModelIndex& parent) const { if(parent.column() > 0) @@ -126,16 +104,6 @@ int RsGxsChannelPostsModel::columnCount(const QModelIndex &/*parent*/) const return mColumns ; } -// std::vector > RsGxsChannelPostsModel::getPostVersions(const RsGxsMessageId& mid) const -// { -// auto it = mPostVersions.find(mid); -// -// if(it != mPostVersions.end()) -// return it->second; -// else -// return std::vector >(); -// } - bool RsGxsChannelPostsModel::getPostData(const QModelIndex& i,RsGxsChannelPost& fmpe) const { if(!i.isValid()) @@ -328,303 +296,28 @@ QVariant RsGxsChannelPostsModel::data(const QModelIndex &index, int role) const const RsGxsChannelPost& fmpe(mPosts[entry]); -#ifdef TODO - if(role == Qt::FontRole) - { - QFont font ; - font.setBold( (fmpe.mPostFlags & (ForumModelPostEntry::FLAG_POST_HAS_UNREAD_CHILDREN | ForumModelPostEntry::FLAG_POST_IS_PINNED)) || IS_MSG_UNREAD(fmpe.mMsgStatus)); - return QVariant(font); - } - - if(role == UnreadChildrenRole) - return bool(fmpe.mPostFlags & ForumModelPostEntry::FLAG_POST_HAS_UNREAD_CHILDREN); - -#ifdef DEBUG_CHANNEL_MODEL - std::cerr << " [ok]" << std::endl; -#endif -#endif - switch(role) { case Qt::DisplayRole: return displayRole (fmpe,index.column()) ; case Qt::UserRole: return userRole (fmpe,index.column()) ; -#ifdef TODO - case Qt::DecorationRole: return decorationRole(fmpe,index.column()) ; - case Qt::ToolTipRole: return toolTipRole (fmpe,index.column()) ; - case Qt::TextColorRole: return textColorRole (fmpe,index.column()) ; - case Qt::BackgroundRole: return backgroundRole(fmpe,index.column()) ; - - case FilterRole: return filterRole (fmpe,index.column()) ; - case ThreadPinnedRole: return pinnedRole (fmpe,index.column()) ; - case MissingRole: return missingRole (fmpe,index.column()) ; - case StatusRole: return statusRole (fmpe,index.column()) ; - case SortRole: return sortRole (fmpe,index.column()) ; -#endif default: return QVariant(); } } -#ifdef TODO -QVariant RsGxsForumModel::textColorRole(const ForumModelPostEntry& fmpe,int /*column*/) const -{ - if( (fmpe.mPostFlags & ForumModelPostEntry::FLAG_POST_IS_MISSING)) - return QVariant(mTextColorMissing); - - if(IS_MSG_UNREAD(fmpe.mMsgStatus) || (fmpe.mPostFlags & ForumModelPostEntry::FLAG_POST_IS_PINNED)) - return QVariant(mTextColorUnread); - else - return QVariant(mTextColorRead); - - return QVariant(); -} - -QVariant RsGxsForumModel::statusRole(const ForumModelPostEntry& fmpe,int column) const -{ - if(column != COLUMN_THREAD_DATA) - return QVariant(); - - return QVariant(fmpe.mMsgStatus); -} - -QVariant RsGxsForumModel::filterRole(const ForumModelPostEntry& fmpe,int /*column*/) const -{ - if(!mFilteringEnabled || (fmpe.mPostFlags & ForumModelPostEntry::FLAG_POST_CHILDREN_PASSES_FILTER)) - return QVariant(FilterString); - - return QVariant(QString()); -} - -uint32_t RsGxsForumModel::recursUpdateFilterStatus(ForumModelIndex i,int column,const QStringList& strings) -{ - QString s ; - uint32_t count = 0; - - switch(column) - { - default: - case COLUMN_THREAD_DATE: - case COLUMN_THREAD_TITLE: s = displayRole(mPosts[i],column).toString(); - break; - case COLUMN_THREAD_AUTHOR: - { - QString comment ; - QList icons; - - GxsIdDetails::MakeIdDesc(mPosts[i].mAuthorId, false,s, icons, comment,GxsIdDetails::ICON_TYPE_NONE); - } - break; - } - - if(!strings.empty()) - { - mPosts[i].mPostFlags &= ~(ForumModelPostEntry::FLAG_POST_PASSES_FILTER | ForumModelPostEntry::FLAG_POST_CHILDREN_PASSES_FILTER); - - for(auto iter(strings.begin()); iter != strings.end(); ++iter) - if(s.contains(*iter,Qt::CaseInsensitive)) - { - mPosts[i].mPostFlags |= ForumModelPostEntry::FLAG_POST_PASSES_FILTER | ForumModelPostEntry::FLAG_POST_CHILDREN_PASSES_FILTER; - - count++; - break; - } - } - else - { - mPosts[i].mPostFlags |= ForumModelPostEntry::FLAG_POST_PASSES_FILTER |ForumModelPostEntry::FLAG_POST_CHILDREN_PASSES_FILTER; - count++; - } - - for(uint32_t j=0;j 0) - mPosts[i].mPostFlags |= ForumModelPostEntry::FLAG_POST_CHILDREN_PASSES_FILTER; - } - - return count; -} - - -void RsGxsForumModel::setFilter(int column,const QStringList& strings,uint32_t& count) -{ - preMods(); - - if(!strings.empty()) - { - count = recursUpdateFilterStatus(ForumModelIndex(0),column,strings); - mFilteringEnabled = true; - } - else - { - count=0; - mFilteringEnabled = false; - } - - postMods(); -} - -QVariant RsGxsForumModel::missingRole(const ForumModelPostEntry& fmpe,int /*column*/) const -{ - if(fmpe.mPostFlags & ForumModelPostEntry::FLAG_POST_IS_MISSING) - return QVariant(true); - else - return QVariant(false); -} - -QVariant RsGxsForumModel::toolTipRole(const ForumModelPostEntry& fmpe,int column) const -{ - if(column == COLUMN_THREAD_DISTRIBUTION) - switch(fmpe.mReputationWarningLevel) - { - case 3: return QVariant(tr("Information for this identity is currently missing.")) ; - case 2: return QVariant(tr("You have banned this ID. The message will not be\ndisplayed nor forwarded to your friends.")) ; - case 1: return QVariant(tr("You have not set an opinion for this person,\n and your friends do not vote positively: Spam regulation \nprevents the message to be forwarded to your friends.")) ; - case 0: return QVariant(tr("Message will be forwarded to your friends.")) ; - default: - return QVariant("[ERROR: missing reputation level information - contact the developers]"); - } - - if(column == COLUMN_THREAD_AUTHOR) - { - QString str,comment ; - QList icons; - - if(!GxsIdDetails::MakeIdDesc(fmpe.mAuthorId, true, str, icons, comment,GxsIdDetails::ICON_TYPE_AVATAR)) - return QVariant(); - - int S = QFontMetricsF(QApplication::font()).height(); - QImage pix( (*icons.begin()).pixmap(QSize(4*S,4*S)).toImage()); - - QString embeddedImage; - if(RsHtml::makeEmbeddedImage(pix.scaled(QSize(4*S,4*S), Qt::KeepAspectRatio, Qt::SmoothTransformation), embeddedImage, 8*S * 8*S)) - comment = "
" + embeddedImage + "" + comment + "
"; - - return comment; - } - - return QVariant(); -} - -QVariant RsGxsForumModel::pinnedRole(const ForumModelPostEntry& fmpe,int /*column*/) const -{ - if(fmpe.mPostFlags & ForumModelPostEntry::FLAG_POST_IS_PINNED) - return QVariant(true); - else - return QVariant(false); -} - -QVariant RsGxsForumModel::backgroundRole(const ForumModelPostEntry& fmpe,int /*column*/) const -{ - if(fmpe.mPostFlags & ForumModelPostEntry::FLAG_POST_IS_PINNED) - return QVariant(QBrush(QColor(255,200,180))); - - if(mFilteringEnabled && (fmpe.mPostFlags & ForumModelPostEntry::FLAG_POST_PASSES_FILTER)) - return QVariant(QBrush(QColor(255,240,210))); - - return QVariant(); -} -#endif - QVariant RsGxsChannelPostsModel::sizeHintRole(int col) const { float factor = QFontMetricsF(QApplication::font()).height()/14.0f ; return QVariant( QSize(factor * 170, factor*14 )); -#ifdef TODO - switch(col) - { - default: - case COLUMN_THREAD_TITLE: return QVariant( QSize(factor * 170, factor*14 )); - case COLUMN_THREAD_DATE: return QVariant( QSize(factor * 75 , factor*14 )); - case COLUMN_THREAD_AUTHOR: return QVariant( QSize(factor * 75 , factor*14 )); - case COLUMN_THREAD_DISTRIBUTION: return QVariant( QSize(factor * 15 , factor*14 )); - } -#endif } -#ifdef TODO -QVariant RsGxsForumModel::authorRole(const ForumModelPostEntry& fmpe,int column) const -{ - if(column == COLUMN_THREAD_DATA) - return QVariant(QString::fromStdString(fmpe.mAuthorId.toStdString())); - - return QVariant(); -} - -QVariant RsGxsForumModel::sortRole(const ForumModelPostEntry& fmpe,int column) const -{ - switch(column) - { - case COLUMN_THREAD_DATE: if(mSortMode == SORT_MODE_PUBLISH_TS) - return QVariant(QString::number(fmpe.mPublishTs)); // we should probably have leading zeroes here - else - return QVariant(QString::number(fmpe.mMostRecentTsInThread)); // we should probably have leading zeroes here - - case COLUMN_THREAD_READ: return QVariant((bool)IS_MSG_UNREAD(fmpe.mMsgStatus)); - case COLUMN_THREAD_DISTRIBUTION: return decorationRole(fmpe,column); - case COLUMN_THREAD_AUTHOR: - { - QString str,comment ; - QList icons; - GxsIdDetails::MakeIdDesc(fmpe.mAuthorId, false, str, icons, comment,GxsIdDetails::ICON_TYPE_NONE); - - return QVariant(str); - } - default: - return displayRole(fmpe,column); - } -} -#endif - QVariant RsGxsChannelPostsModel::displayRole(const RsGxsChannelPost& fmpe,int col) const { switch(col) { default: return QString::fromUtf8(fmpe.mMeta.mMsgName.c_str()); -#ifdef TODO - case COLUMN_THREAD_TITLE: if(fmpe.mPostFlags & ForumModelPostEntry::FLAG_POST_IS_REDACTED) - return QVariant(tr("[ ... Redacted message ... ]")); - else if(fmpe.mPostFlags & ForumModelPostEntry::FLAG_POST_IS_PINNED) - return QVariant(tr("[PINNED] ") + QString::fromUtf8(fmpe.mTitle.c_str())); - else - return QVariant(QString::fromUtf8(fmpe.mTitle.c_str())); - - case COLUMN_THREAD_READ:return QVariant(); - case COLUMN_THREAD_DATE:{ - if(fmpe.mPostFlags & ForumModelPostEntry::FLAG_POST_IS_MISSING) - return QVariant(QString()); - - QDateTime qtime; - qtime.setTime_t(fmpe.mPublishTs); - - return QVariant(DateTime::formatDateTime(qtime)); - } - - case COLUMN_THREAD_DISTRIBUTION: - case COLUMN_THREAD_AUTHOR:{ - QString name; - RsGxsId id = RsGxsId(fmpe.mAuthorId.toStdString()); - - if(id.isNull()) - return QVariant(tr("[Notification]")); - if(GxsIdTreeItemDelegate::computeName(id,name)) - return name; - return QVariant(tr("[Unknown]")); - } - case COLUMN_THREAD_MSGID: return QVariant(); -#endif -#ifdef TODO - if (filterColumn == COLUMN_THREAD_CONTENT) { - // need content for filter - QTextDocument doc; - doc.setHtml(QString::fromUtf8(msg.mMsg.c_str())); - item->setText(COLUMN_THREAD_CONTENT, doc.toPlainText().replace(QString("\n"), QString(" "))); - } -#endif } @@ -640,23 +333,6 @@ QVariant RsGxsChannelPostsModel::userRole(const RsGxsChannelPost& fmpe,int col) } } -#ifdef TODO -QVariant RsGxsForumModel::decorationRole(const ForumModelPostEntry& fmpe,int col) const -{ - bool exist=false; - switch(col) - { - case COLUMN_THREAD_DISTRIBUTION: - return QVariant(fmpe.mReputationWarningLevel); - case COLUMN_THREAD_READ: - return QVariant(fmpe.mMsgStatus); - case COLUMN_THREAD_AUTHOR://Return icon as place holder. - return FilesDefs::getIconFromGxsIdCache(RsGxsId(fmpe.mAuthorId.toStdString()),QIcon(), exist); - } - return QVariant(); -} -#endif - const RsGxsGroupId& RsGxsChannelPostsModel::currentGroupId() const { return mChannelGroup.mMeta.mGroupId; @@ -766,39 +442,13 @@ void RsGxsChannelPostsModel::update_posts(const RsGxsGroupId& group_id) }); } -//ChannelPostsModelIndex RsGxsChannelPostsModel::addEntry(std::vector& posts,const ChannelPostsModelPostEntry& entry) -//{ -// uint32_t N = posts.size(); -// posts.push_back(entry); -// -//#ifdef DEBUG_FORUMMODEL -// std::cerr << "Added new entry " << N << " children of " << parent << std::endl; -//#endif -// if(N == parent) -// std::cerr << "(EE) trying to add a post as its own parent!" << std::endl; -// -// return ChannelPostsModelIndex(N); -//} - -//void RsGxsChannelPostsModel::convertMsgToPostEntry(const RsGxsChannelGroup& mChannelGroup,const RsMsgMetaData& msg, bool /*useChildTS*/, ChannelPostsModelPostEntry& fentry) -//{ -// fentry.mTitle = msg.mMsgName; -// fentry.mMsgId = msg.mMsgId; -// fentry.mPublishTs = msg.mPublishTs; -// fentry.mPostFlags = 0; -// fentry.mMsgStatus = msg.mMsgStatus; -// -// // Early check for a message that should be hidden because its author -// // is flagged with a bad reputation -//} - static bool decreasing_time_comp(const std::pair& e1,const std::pair& e2) { return e2.first < e1.first ; } void RsGxsChannelPostsModel::createPostsArray(std::vector& posts) { // collect new versions of posts if any -#ifndef DEBUG_CHANNEL_MODEL +#ifdef DEBUG_CHANNEL_MODEL std::cerr << "Inserting channel posts" << std::endl; #endif @@ -808,7 +458,7 @@ void RsGxsChannelPostsModel::createPostsArray(std::vector& pos if(posts[i].mMeta.mOrigMsgId == posts[i].mMeta.mMsgId) posts[i].mMeta.mOrigMsgId.clear(); -#ifndef DEBUG_CHANNEL_MODEL +#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 @@ -900,7 +550,7 @@ void RsGxsChannelPostsModel::createPostsArray(std::vector& pos { if(!(*it).mMeta.mMsgId.isNull()) { -#ifndef DEBUG_CHANNEL_MODEL +#ifdef DEBUG_CHANNEL_MODEL std::cerr << " adding post \"" << (*it).mMeta.mMsgName << "\"" << std::endl; #endif mPosts.push_back(*it); @@ -929,77 +579,8 @@ void RsGxsChannelPostsModel::setMsgReadStatus(const QModelIndex& i,bool read_sta // bool has_unread_below, has_read_below; // recursSetMsgReadStatus(entry,read_status,with_children) ; // recursUpdateReadStatusAndTimes(0,has_unread_below,has_read_below); - } -#ifdef TODO -void RsGxsForumModel::recursSetMsgReadStatus(ForumModelIndex i,bool read_status,bool with_children) -{ - int newStatus = (read_status ? mPosts[i].mMsgStatus & ~static_cast(GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD) - : mPosts[i].mMsgStatus | static_cast(GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD)); - bool bChanged = (mPosts[i].mMsgStatus != newStatus); - mPosts[i].mMsgStatus = newStatus; - //Remove Unprocessed and New flags - mPosts[i].mMsgStatus &= ~(GXS_SERV::GXS_MSG_STATUS_UNPROCESSED | GXS_SERV::GXS_MSG_STATUS_GUI_NEW); - - if (bChanged) - { - //Don't recurs post versions as this should be done before, if no change. - uint32_t token; - auto s = getPostVersions(mPosts[i].mMsgId) ; - - if(!s.empty()) - for(auto it(s.begin());it!=s.end();++it) - { - rsGxsForums->setMessageReadStatus(token,std::make_pair( mForumGroup.mMeta.mGroupId, it->second ), read_status); - std::cerr << "Setting version " << it->second << " of post " << mPosts[i].mMsgId << " as read." << std::endl; - } - else - rsGxsForums->setMessageReadStatus(token,std::make_pair( mForumGroup.mMeta.mGroupId, mPosts[i].mMsgId ), read_status); - - QModelIndex itemIndex = createIndex(i - 1, 0, &mPosts[i]); - emit dataChanged(itemIndex, itemIndex); - } - - if(!with_children) - return; - - for(uint32_t j=0;j& entries,ForumModelIndex index,int depth) -{ - const ForumModelPostEntry& e(entries[index]); - - QDateTime qtime; - qtime.setTime_t(e.mPublishTs); - - std::cerr << std::string(depth*2,' ') << index << " : " << e.mAuthorId.toStdString() << " " - << QString("%1").arg((uint32_t)e.mPostFlags,8,16,QChar('0')).toStdString() << " " - << QString("%1").arg((uint32_t)e.mMsgStatus,8,16,QChar('0')).toStdString() << " " - << qtime.toString().toStdString() << " \"" << e.mTitle << "\"" << std::endl; - - for(uint32_t i=0;i= mPosts.size()) - return ; - - std::cerr << "Setting own opinion for author " << mPosts[entry].mAuthorId - << " to " << static_cast(op) << std::endl; - RsGxsId author_id = mPosts[entry].mAuthorId; - - rsReputations->setOwnOpinion(author_id,op) ; - - // update opinions and distribution flags. No need to re-load all posts. - - for(uint32_t i=0;ichannelPostFiles_TV->resizeColumnToContents(RsGxsChannelPostFilesModel::COLUMN_FILES_FILE); ui->channelPostFiles_TV->resizeColumnToContents(RsGxsChannelPostFilesModel::COLUMN_FILES_SIZE); ui->channelPostFiles_TV->resizeColumnToContents(RsGxsChannelPostFilesModel::COLUMN_FILES_NAME); + ui->channelPostFiles_TV->setAutoSelect(true); } void GxsChannelPostsWidgetWithModel::updateGroupData()