From 9da8a8a14a39bffe74403001978a13cc8b130138 Mon Sep 17 00:00:00 2001 From: Manuel Nickschas Date: Mon, 26 Apr 2010 21:11:29 +0200 Subject: [PATCH] Improve marker line behavior; allow manual setting (Ctrl+R) The marker line will now be set to the bottom of the current chatview rather than to the very bottom of the chatview when it makes sense. So if you didn't scroll all the way down, and switch channels, you can start off where you left reading. Also there's now an option to disable the automatic setting of the marker line completely. Using Ctrl+R, you can manually set the marker line to the bottom of the ChatView. This requires a recent core (older cores will still work, but only show the old behavior). --- src/client/client.cpp | 10 +++- src/client/client.h | 4 +- src/client/networkmodel.cpp | 4 +- src/client/networkmodel.h | 4 +- src/common/buffersyncer.cpp | 3 + src/common/buffersyncer.h | 2 +- src/qtui/bufferwidget.cpp | 59 ++++++++++++++++++- src/qtui/bufferwidget.h | 9 +++ .../settingspages/chatviewsettingspage.cpp | 8 +++ .../settingspages/chatviewsettingspage.ui | 25 +++++++- src/uisupport/abstractbuffercontainer.cpp | 2 - src/uisupport/abstractbuffercontainer.h | 5 +- 12 files changed, 123 insertions(+), 12 deletions(-) diff --git a/src/client/client.cpp b/src/client/client.cpp index 228d4df3..21beda08 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -322,7 +322,7 @@ void Client::setSyncedToCore() { connect(bufferSyncer(), SIGNAL(buffersPermanentlyMerged(BufferId, BufferId)), this, SLOT(buffersPermanentlyMerged(BufferId, BufferId))); connect(bufferSyncer(), SIGNAL(buffersPermanentlyMerged(BufferId, BufferId)), _messageModel, SLOT(buffersPermanentlyMerged(BufferId, BufferId))); connect(bufferSyncer(), SIGNAL(bufferMarkedAsRead(BufferId)), SIGNAL(bufferMarkedAsRead(BufferId))); - connect(networkModel(), SIGNAL(setLastSeenMsg(BufferId, MsgId)), bufferSyncer(), SLOT(requestSetLastSeenMsg(BufferId, const MsgId &))); + connect(networkModel(), SIGNAL(requestSetLastSeenMsg(BufferId, MsgId)), bufferSyncer(), SLOT(requestSetLastSeenMsg(BufferId, const MsgId &))); signalProxy()->synchronize(bufferSyncer()); // create a new BufferViewManager @@ -470,11 +470,17 @@ void Client::setBufferLastSeenMsg(BufferId id, const MsgId &msgId) { bufferSyncer()->requestSetLastSeenMsg(id, msgId); } -void Client::setBufferMarkerLine(BufferId id, const MsgId &msgId) { +void Client::setMarkerLine(BufferId id, const MsgId &msgId) { if(bufferSyncer()) bufferSyncer()->requestSetMarkerLine(id, msgId); } +MsgId Client::markerLine(BufferId id) { + if(id.isValid() && networkModel()) + return networkModel()->markerLineMsgId(id); + return MsgId(); +} + void Client::removeBuffer(BufferId id) { if(!bufferSyncer()) return; bufferSyncer()->requestRemoveBuffer(id); diff --git a/src/client/client.h b/src/client/client.h index ab413b80..cc3803bc 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -127,7 +127,9 @@ public: static void userInput(const BufferInfo &bufferInfo, const QString &message); static void setBufferLastSeenMsg(BufferId id, const MsgId &msgId); // this is synced to core and other clients - static void setBufferMarkerLine(BufferId id, const MsgId &msgId); // this is synced to core and other clients + static void setMarkerLine(BufferId id, const MsgId &msgId); // this is synced to core and other clients + static MsgId markerLine(BufferId id); + static void removeBuffer(BufferId id); static void renameBuffer(BufferId bufferId, const QString &newName); static void mergeBuffersPermanently(BufferId bufferId1, BufferId bufferId2); diff --git a/src/client/networkmodel.cpp b/src/client/networkmodel.cpp index d7454316..f44c87d7 100644 --- a/src/client/networkmodel.cpp +++ b/src/client/networkmodel.cpp @@ -1022,6 +1022,7 @@ void NetworkModel::setLastSeenMsgId(const BufferId &bufferId, const MsgId &msgId return; } bufferItem->setLastSeenMsgId(msgId); + emit lastSeenMsgSet(bufferId, msgId); } void NetworkModel::setMarkerLineMsgId(const BufferId &bufferId, const MsgId &msgId) { @@ -1032,6 +1033,7 @@ void NetworkModel::setMarkerLineMsgId(const BufferId &bufferId, const MsgId &msg return; } bufferItem->setMarkerLineMsgId(msgId); + emit markerLineSet(bufferId, msgId); } void NetworkModel::updateBufferActivity(Message &msg) { @@ -1087,7 +1089,7 @@ void NetworkModel::updateBufferActivity(BufferItem *bufferItem, const Message &m bufferItem->updateActivityLevel(msg); if(bufferItem->isCurrentBuffer()) - emit setLastSeenMsg(bufferItem->bufferId(), msg.msgId()); + emit requestSetLastSeenMsg(bufferItem->bufferId(), msg.msgId()); } void NetworkModel::setBufferActivity(const BufferId &bufferId, BufferInfo::ActivityLevel level) { diff --git a/src/client/networkmodel.h b/src/client/networkmodel.h index 52b49eb0..daf82435 100644 --- a/src/client/networkmodel.h +++ b/src/client/networkmodel.h @@ -340,7 +340,9 @@ public slots: void networkRemoved(const NetworkId &networkId); signals: - void setLastSeenMsg(BufferId bufferId, MsgId msgId); + void requestSetLastSeenMsg(BufferId buffer, MsgId msg); + void lastSeenMsgSet(BufferId buffer, MsgId msg); + void markerLineSet(BufferId buffer, MsgId msg); private slots: void checkForRemovedBuffers(const QModelIndex &parent, int start, int end); diff --git a/src/common/buffersyncer.cpp b/src/common/buffersyncer.cpp index 4987429a..222f65bc 100644 --- a/src/common/buffersyncer.cpp +++ b/src/common/buffersyncer.cpp @@ -59,6 +59,9 @@ bool BufferSyncer::setMarkerLine(BufferId buffer, const MsgId &msgId) { if(!msgId.isValid()) return false; + if(_markerLines.value(buffer) == msgId) + return false; + _markerLines[buffer] = msgId; SYNC(ARG(buffer), ARG(msgId)) emit markerLineSet(buffer, msgId); diff --git a/src/common/buffersyncer.h b/src/common/buffersyncer.h index 3de31db7..716178a7 100644 --- a/src/common/buffersyncer.h +++ b/src/common/buffersyncer.h @@ -45,7 +45,7 @@ public slots: void initSetMarkerLines(const QVariantList &); virtual inline void requestSetLastSeenMsg(BufferId buffer, const MsgId &msgId) { REQUEST(ARG(buffer), ARG(msgId)) } - virtual inline void requestSetMarkerLine(BufferId buffer, const MsgId &msgId) { REQUEST(ARG(buffer), ARG(msgId)) } + virtual inline void requestSetMarkerLine(BufferId buffer, const MsgId &msgId) { REQUEST(ARG(buffer), ARG(msgId)) setMarkerLine(buffer, msgId); } virtual inline void requestRemoveBuffer(BufferId buffer) { REQUEST(ARG(buffer)) } virtual void removeBuffer(BufferId buffer); diff --git a/src/qtui/bufferwidget.cpp b/src/qtui/bufferwidget.cpp index ecfdceb9..ab068997 100644 --- a/src/qtui/bufferwidget.cpp +++ b/src/qtui/bufferwidget.cpp @@ -26,9 +26,11 @@ #include "action.h" #include "actioncollection.h" #include "bufferwidget.h" +#include "chatline.h" #include "chatview.h" #include "chatviewsearchbar.h" #include "chatviewsearchcontroller.h" +#include "chatviewsettings.h" #include "client.h" #include "iconloader.h" #include "multilineedit.h" @@ -38,7 +40,8 @@ BufferWidget::BufferWidget(QWidget *parent) : AbstractBufferContainer(parent), - _chatViewSearchController(new ChatViewSearchController(this)) + _chatViewSearchController(new ChatViewSearchController(this)), + _autoMarkerLine(true) { ui.setupUi(this); layout()->setContentsMargins(0, 0, 0, 0); @@ -86,6 +89,13 @@ BufferWidget::BufferWidget(QWidget *parent) zoomOriginalChatview->setIcon(SmallIcon("zoom-original")); zoomOriginalChatview->setText(tr("Actual Size")); //zoomOriginalChatview->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_0)); // used for RTS switching + + Action *setMarkerLine = coll->add("SetMarkerLineToBottom", this, SLOT(setMarkerLine())); + setMarkerLine->setText(tr("Set Marker Line")); + setMarkerLine->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_R)); + + ChatViewSettings s; + s.initAndNotify("AutoMarkerLine", this, SLOT(setAutoMarkerLine(QVariant)), true); } BufferWidget::~BufferWidget() { @@ -93,6 +103,10 @@ BufferWidget::~BufferWidget() { _chatViewSearchController = 0; } +void BufferWidget::setAutoMarkerLine(const QVariant &v) { + _autoMarkerLine = v.toBool(); +} + AbstractChatView *BufferWidget::createChatView(BufferId id) { ChatView *chatView; chatView = new ChatView(id, this); @@ -129,7 +143,6 @@ void BufferWidget::scrollToHighlight(QGraphicsItem *highlightItem) { } } - void BufferWidget::zoomIn() { ChatView *view = qobject_cast(ui.stackedWidget->currentWidget()); if(view) @@ -194,3 +207,45 @@ bool BufferWidget::eventFilter(QObject *watched, QEvent *event) { return false; } } + +void BufferWidget::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) { + ChatView *prevView = qobject_cast(ui.stackedWidget->currentWidget()); + + AbstractBufferContainer::currentChanged(current, previous); // switch first to avoid a redraw + + // we need to hide the marker line if it's already/still at the bottom of the view (and not scrolled up) + ChatView *curView = qobject_cast(ui.stackedWidget->currentWidget()); + if(curView) { + BufferId curBufferId = current.data(NetworkModel::BufferIdRole).value(); + if(curBufferId.isValid()) { + MsgId markerMsgId = Client::networkModel()->markerLineMsgId(curBufferId); + if(markerMsgId == curView->lastMsgId() && markerMsgId == curView->lastVisibleMsgId()) + curView->setMarkerLineVisible(false); + else + curView->setMarkerLineVisible(true); + } + } + + if(prevView && autoMarkerLine()) + setMarkerLine(prevView, false); +} + +void BufferWidget::setMarkerLine(ChatView *view, bool allowGoingBack) { + if(!view) + view = qobject_cast(ui.stackedWidget->currentWidget()); + if(!view) + return; + + ChatLine *lastLine = view->lastVisibleChatLine(); + if(lastLine) { + if(!allowGoingBack) { + QModelIndex idx = lastLine->index(); + BufferId bufId = view->scene()->singleBufferId(); + MsgId msgId = idx.data(MessageModel::MsgIdRole).value(); + MsgId oldMsgId = Client::markerLine(bufId); + if(oldMsgId.isValid() && msgId <= oldMsgId) + return; + } + view->setMarkedLine(lastLine); + } +} diff --git a/src/qtui/bufferwidget.h b/src/qtui/bufferwidget.h index 3efb87a6..dc8b8236 100644 --- a/src/qtui/bufferwidget.h +++ b/src/qtui/bufferwidget.h @@ -26,6 +26,7 @@ #include "abstractbuffercontainer.h" class QGraphicsItem; +class ChatView; class ChatViewSearchBar; class ChatViewSearchController; @@ -44,9 +45,13 @@ public: protected: virtual AbstractChatView *createChatView(BufferId); virtual void removeChatView(BufferId); + virtual inline bool autoMarkerLine() const { return _autoMarkerLine; } protected slots: + virtual void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); virtual void showChatView(BufferId); +public slots: + virtual void setMarkerLine(ChatView *view = 0, bool allowGoingBack = true); private slots: void scrollToHighlight(QGraphicsItem *highlightItem); @@ -54,11 +59,15 @@ private slots: void zoomOut(); void zoomOriginal(); + void setAutoMarkerLine(const QVariant &); + private: Ui::BufferWidget ui; QHash _chatViews; ChatViewSearchController *_chatViewSearchController; + + bool _autoMarkerLine; }; #endif diff --git a/src/qtui/settingspages/chatviewsettingspage.cpp b/src/qtui/settingspages/chatviewsettingspage.cpp index 76780b15..fd59024e 100644 --- a/src/qtui/settingspages/chatviewsettingspage.cpp +++ b/src/qtui/settingspages/chatviewsettingspage.cpp @@ -19,6 +19,7 @@ ***************************************************************************/ #include "chatviewsettingspage.h" +#include "client.h" #include "colorbutton.h" #include "qtui.h" #include "qtuistyle.h" @@ -33,6 +34,13 @@ ChatViewSettingsPage::ChatViewSettingsPage(QWidget *parent) ui.showWebPreview->setEnabled(false); #endif + // FIXME remove with protocol v11 + if(!(Client::coreFeatures() & Quassel::SynchronizedMarkerLine)) { + ui.autoMarkerLine->setEnabled(false); + ui.autoMarkerLine->setChecked(true); + ui.autoMarkerLine->setToolTip(tr("You need at 0.6 quasselcore to use this feature")); + } + initAutoWidgets(); } diff --git a/src/qtui/settingspages/chatviewsettingspage.ui b/src/qtui/settingspages/chatviewsettingspage.ui index 378c6513..5bc64ce8 100644 --- a/src/qtui/settingspages/chatviewsettingspage.ui +++ b/src/qtui/settingspages/chatviewsettingspage.ui @@ -7,7 +7,7 @@ 0 0 486 - 475 + 492 @@ -88,6 +88,9 @@ + + Show colored text in the chat window + Allow colored text (mIRC color codes) @@ -121,6 +124,25 @@ + + + + Set the marker line to the bottom of the current chat window when selecting another channel + + + Set marker line automatically when switching chats + + + true + + + AutoMarkerLine + + + true + + + @@ -766,6 +788,7 @@ customChatViewFont allowMircColors showWebPreview + autoMarkerLine useCustomColors actionMsgColor channelMsgColor diff --git a/src/uisupport/abstractbuffercontainer.cpp b/src/uisupport/abstractbuffercontainer.cpp index 4691c944..65377fe3 100644 --- a/src/uisupport/abstractbuffercontainer.cpp +++ b/src/uisupport/abstractbuffercontainer.cpp @@ -97,8 +97,6 @@ void AbstractBufferContainer::setCurrentBuffer(BufferId bufferId) { if(prevBufferId.isValid() && _chatViews.contains(prevBufferId)) { MsgId msgId = _chatViews.value(prevBufferId)->lastMsgId(); Client::setBufferLastSeenMsg(prevBufferId, msgId); - if(autoSetMarkerLine()) - Client::setBufferMarkerLine(prevBufferId, msgId); } if(!bufferId.isValid()) { diff --git a/src/uisupport/abstractbuffercontainer.h b/src/uisupport/abstractbuffercontainer.h index cc77efda..474e10a4 100644 --- a/src/uisupport/abstractbuffercontainer.h +++ b/src/uisupport/abstractbuffercontainer.h @@ -52,7 +52,10 @@ protected: */ virtual void removeChatView(BufferId) = 0; - virtual inline bool autoSetMarkerLine() const { return true; } + //! If true, the marker line will be set automatically on buffer switch + /** \return Whether the marker line should be set on buffer switch + */ + virtual inline bool autoMarkerLine() const { return true; } protected slots: virtual void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); -- 2.20.1