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).
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
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);
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);
return;
}
bufferItem->setLastSeenMsgId(msgId);
+ emit lastSeenMsgSet(bufferId, msgId);
}
void NetworkModel::setMarkerLineMsgId(const BufferId &bufferId, const MsgId &msgId) {
return;
}
bufferItem->setMarkerLineMsgId(msgId);
+ emit markerLineSet(bufferId, msgId);
}
void NetworkModel::updateBufferActivity(Message &msg) {
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) {
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);
if(!msgId.isValid())
return false;
+ if(_markerLines.value(buffer) == msgId)
+ return false;
+
_markerLines[buffer] = msgId;
SYNC(ARG(buffer), ARG(msgId))
emit markerLineSet(buffer, msgId);
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);
#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"
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);
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<Action>("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() {
_chatViewSearchController = 0;
}
+void BufferWidget::setAutoMarkerLine(const QVariant &v) {
+ _autoMarkerLine = v.toBool();
+}
+
AbstractChatView *BufferWidget::createChatView(BufferId id) {
ChatView *chatView;
chatView = new ChatView(id, this);
}
}
-
void BufferWidget::zoomIn() {
ChatView *view = qobject_cast<ChatView *>(ui.stackedWidget->currentWidget());
if(view)
return false;
}
}
+
+void BufferWidget::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) {
+ ChatView *prevView = qobject_cast<ChatView *>(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<ChatView *>(ui.stackedWidget->currentWidget());
+ if(curView) {
+ BufferId curBufferId = current.data(NetworkModel::BufferIdRole).value<BufferId>();
+ 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<ChatView *>(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>();
+ MsgId oldMsgId = Client::markerLine(bufId);
+ if(oldMsgId.isValid() && msgId <= oldMsgId)
+ return;
+ }
+ view->setMarkedLine(lastLine);
+ }
+}
#include "abstractbuffercontainer.h"
class QGraphicsItem;
+class ChatView;
class ChatViewSearchBar;
class ChatViewSearchController;
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);
void zoomOut();
void zoomOriginal();
+ void setAutoMarkerLine(const QVariant &);
+
private:
Ui::BufferWidget ui;
QHash<BufferId, QWidget *> _chatViews;
ChatViewSearchController *_chatViewSearchController;
+
+ bool _autoMarkerLine;
};
#endif
***************************************************************************/
#include "chatviewsettingspage.h"
+#include "client.h"
#include "colorbutton.h"
#include "qtui.h"
#include "qtuistyle.h"
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();
}
<x>0</x>
<y>0</y>
<width>486</width>
- <height>475</height>
+ <height>492</height>
</rect>
</property>
<property name="windowTitle">
</item>
<item>
<widget class="QCheckBox" name="allowMircColors">
+ <property name="toolTip">
+ <string>Show colored text in the chat window</string>
+ </property>
<property name="text">
<string>Allow colored text (mIRC color codes)</string>
</property>
</property>
</widget>
</item>
+ <item>
+ <widget class="QCheckBox" name="autoMarkerLine">
+ <property name="toolTip">
+ <string>Set the marker line to the bottom of the current chat window when selecting another channel</string>
+ </property>
+ <property name="text">
+ <string>Set marker line automatically when switching chats</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="settingsKey" stdset="0">
+ <string notr="true">AutoMarkerLine</string>
+ </property>
+ <property name="defaultValue" stdset="0">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
<item>
<widget class="QGroupBox" name="useCustomColors">
<property name="title">
<tabstop>customChatViewFont</tabstop>
<tabstop>allowMircColors</tabstop>
<tabstop>showWebPreview</tabstop>
+ <tabstop>autoMarkerLine</tabstop>
<tabstop>useCustomColors</tabstop>
<tabstop>actionMsgColor</tabstop>
<tabstop>channelMsgColor</tabstop>
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()) {
*/
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);