aboutdlg.h
bufferwidget.h
channellistdlg.h
+ chatitem.h
chatlinemodel.h
chatmonitorfilter.h
chatmonitorview.h
verticaldock.h)
set(HEADERS
- chatitem.h
chatline.h
chatlinemodelitem.h
chatviewsettings.h
#include "chatviewsearchbar.h"
#include "chatviewsearchcontroller.h"
#include "client.h"
+#include "iconloader.h"
#include "inputline.h"
#include "qtui.h"
#include "settings.h"
ActionCollection *coll = QtUi::actionCollection();
- Action *zoomChatview = coll->add<Action>("ZoomChatView");
- connect(zoomChatview, SIGNAL(triggered()), SLOT(zoomIn()));
- zoomChatview->setText(tr("Enlarge Chat View"));
- zoomChatview->setShortcut(tr("Ctrl++"));
+ Action *zoomInChatview = coll->add<Action>("ZoomInChatView", this, SLOT(zoomIn()));
+ zoomInChatview->setText(tr("Zoom In"));
+ zoomInChatview->setIcon(SmallIcon("zoom-in"));
+ zoomInChatview->setShortcut(QKeySequence::ZoomIn);
- Action *zoomOutChatview = coll->add<Action>("ZoomOutChatView");
- connect(zoomOutChatview, SIGNAL(triggered()), SLOT(zoomOut()));
- zoomOutChatview->setText(tr("Demagnify Chat View"));
- zoomOutChatview->setShortcut(tr("Ctrl+-"));
+ Action *zoomOutChatview = coll->add<Action>("ZoomOutChatView", this, SLOT(zoomOut()));
+ zoomOutChatview->setIcon(SmallIcon("zoom-out"));
+ zoomOutChatview->setText(tr("Zoom Out"));
+ zoomOutChatview->setShortcut(QKeySequence::ZoomOut);
- Action *zoomNormalChatview = coll->add<Action>("ZoomNormalChatView");
- connect(zoomNormalChatview, SIGNAL(triggered()), SLOT(zoomNormal()));
- zoomNormalChatview->setText(tr("Normalize zoom of Chat View"));
- zoomNormalChatview->setShortcut(tr("Ctrl+0"));
+ Action *zoomOriginalChatview = coll->add<Action>("ZoomOriginalChatView", this, SLOT(zoomOriginal()));
+ zoomOriginalChatview->setIcon(SmallIcon("zoom-original"));
+ zoomOriginalChatview->setText(tr("Zoom Original"));
+ zoomOriginalChatview->setShortcut(tr("Ctrl+0"));
}
BufferWidget::~BufferWidget() {
AbstractChatView *BufferWidget::createChatView(BufferId id) {
ChatView *chatView;
chatView = new ChatView(id, this);
+ chatView->setBufferContainer(this);
_chatViews[id] = chatView;
ui.stackedWidget->addWidget(chatView);
chatView->setFocusProxy(this);
void BufferWidget::zoomIn() {
ChatView *view = qobject_cast<ChatView *>(ui.stackedWidget->currentWidget());
- if(!view) return;
- view->zoomIn();
+ if(view)
+ view->zoomIn();
}
void BufferWidget::zoomOut() {
ChatView *view = qobject_cast<ChatView *>(ui.stackedWidget->currentWidget());
- if(!view) return;
- view->zoomOut();
+ if(view)
+ view->zoomOut();
}
-void BufferWidget::zoomNormal() {
+void BufferWidget::zoomOriginal() {
ChatView *view = qobject_cast<ChatView *>(ui.stackedWidget->currentWidget());
- if(!view) return;
- view->zoomNormal();
+ if(view)
+ view->zoomOriginal();
+}
+
+void BufferWidget::addActionsToMenu(QMenu *menu) {
+ ActionCollection *coll = QtUi::actionCollection();
+ menu->addSeparator();
+ menu->addAction(coll->action("ZoomInChatView"));
+ menu->addAction(coll->action("ZoomOutChatView"));
+ menu->addAction(coll->action("ZoomOriginalChatView"));
+
}
bool BufferWidget::eventFilter(QObject *watched, QEvent *event) {
- Q_UNUSED(watched);
if(event->type() != QEvent::KeyPress)
return false;
virtual bool eventFilter(QObject *watched, QEvent *event);
inline ChatViewSearchBar *searchBar() const { return ui.searchBar; }
+ void addActionsToMenu(QMenu *);
protected:
virtual AbstractChatView *createChatView(BufferId);
void scrollToHighlight(QGraphicsItem *highlightItem);
void zoomIn();
void zoomOut();
- void zoomNormal();
+ void zoomOriginal();
private:
Ui::BufferWidget ui;
event->ignore();
}
+void ChatItem::addActionsToMenu(QMenu *menu, const QPointF &pos) {
+ Q_UNUSED(menu);
+ Q_UNUSED(pos);
+
+}
+
// ************************************************************
// SenderChatItem
// ************************************************************
// ************************************************************
// ContentsChatItem
// ************************************************************
+
+ContentsChatItem::ActionProxy ContentsChatItem::_actionProxy;
+
ContentsChatItem::ContentsChatItem(const qreal &width, const QPointF &pos, QGraphicsItem *parent)
: ChatItem(0, 0, pos, parent)
{
event->accept();
}
-/*
-void ContentsChatItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
- qint16 idx = posToCursor(event->pos());
- for(int i = 0; i < privateData()->clickables.count(); i++) {
- Clickable click = privateData()->clickables.at(i);
- if(idx >= click.start && idx < click.start + click.length) {
- if(click.type == Clickable::Url) {
- QMenu menu;
- QAction *copyToClipboard = menu.addAction(QObject::tr("Copy to Clipboard"));
- QAction *selected = menu.exec(event->screenPos());
- if(selected == copyToClipboard) {
- QString url = data(ChatLineModel::DisplayRole).toString().mid(click.start, click.length);
-# ifdef Q_WS_X11
- QApplication::clipboard()->setText(url, QClipboard::Selection);
-# endif
-//# else
- QApplication::clipboard()->setText(url);
-//# endif
- }
- }
+void ContentsChatItem::addActionsToMenu(QMenu *menu, const QPointF &pos) {
+ Q_UNUSED(pos); // we assume that the current mouse cursor pos is the point of invocation
+
+ if(privateData()->currentClickable.isValid()) {
+ switch(privateData()->currentClickable.type) {
+ case Clickable::Url:
+ privateData()->activeClickable = privateData()->currentClickable;
+ menu->addAction(tr("Copy Link Address"), &_actionProxy, SLOT(copyLinkToClipboard()))->setData(QVariant::fromValue<void *>(this));
+ break;
+
+ default:
+ break;
}
}
}
-*/
+
+void ContentsChatItem::copyLinkToClipboard() {
+ Clickable click = privateData()->activeClickable;
+ if(click.isValid() && click.type == Clickable::Url) {
+ QString url = data(ChatLineModel::DisplayRole).toString().mid(click.start, click.length);
+ if(!url.contains("://"))
+ url = "http://" + url;
+ chatScene()->stringToClipboard(url);
+ }
+}
+
+/******** WEB PREVIEW *****************************************************************************/
void ContentsChatItem::showWebPreview(const Clickable &click) {
#ifndef HAVE_WEBKIT
return -1;
}
+/*************************************************************************************************/
+
#ifndef CHATITEM_H_
#define CHATITEM_H_
+#include <QAction>
#include <QGraphicsItem>
#include <QObject>
QList<QRectF> findWords(const QString &searchWord, Qt::CaseSensitivity caseSensitive);
+ virtual void addActionsToMenu(QMenu *menu, const QPointF &itemPos);
virtual void handleClick(const QPointF &pos, ChatScene::ClickMode);
protected:
struct ChatItemPrivate {
QTextLayout *layout;
ChatItemPrivate(QTextLayout *l) : layout(l) {}
- ~ChatItemPrivate() {
+ virtual ~ChatItemPrivate() {
delete layout;
}
};
//! A ChatItem for the contents column
class ContentsChatItem : public ChatItem {
+ Q_DECLARE_TR_FUNCTIONS(ContentsChatItem);
+
public:
ContentsChatItem(const qreal &width, const QPointF &pos, QGraphicsItem *parent);
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
- //virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
-
virtual void handleClick(const QPointF &pos, ChatScene::ClickMode clickMode);
+ virtual void addActionsToMenu(QMenu *menu, const QPointF &itemPos);
+ virtual void copyLinkToClipboard();
+
virtual QVector<QTextLayout::FormatRange> additionalFormats() const;
virtual void doLayout();
private:
struct Clickable;
+ class ActionProxy;
class WrapColumnFinder;
inline ContentsChatItemPrivate *privateData() const;
friend struct ContentsChatItemPrivate;
QFontMetricsF *_fontMetrics;
+
+ // we need a receiver for Action signals
+ static ActionProxy _actionProxy;
};
struct ContentsChatItem::Clickable {
ContentsChatItem *contentsItem;
QList<ContentsChatItem::Clickable> clickables;
ContentsChatItem::Clickable currentClickable;
+ ContentsChatItem::Clickable activeClickable;
ContentsChatItemPrivate(QTextLayout *l, const QList<ContentsChatItem::Clickable> &c, ContentsChatItem *parent)
: ChatItemPrivate(l), contentsItem(parent), clickables(c) {}
qreal choppedTrailing;
};
+//! Acts as a proxy for Action signals targetted at a ContentsChatItem
+/** Since a ChatItem is not a QObject, hence cannot receive signals, we use a static ActionProxy
+ * as a receiver instead. This avoids having to handle ChatItem actions (e.g. context menu entries)
+ * outside the ChatItem.
+ */
+class ContentsChatItem::ActionProxy : public QObject {
+ Q_OBJECT
+
+public slots:
+ inline void copyLinkToClipboard() { item()->copyLinkToClipboard(); }
+
+private:
+ /// Returns the ContentsChatItem that should receive the action event.
+ /** For efficiency reasons, values are not checked for validity. You gotta make sure that you set the data() member
+ * in the Action correctly.
+ * @return The ChatItem from which the sending Action originated
+ */
+ inline ContentsChatItem *item() const {
+ return static_cast<ContentsChatItem *>(qobject_cast<QAction *>(sender())->data().value<void *>());
+ }
+};
+
/*************************************************************************************************/
// Avoid circular include deps
#include "chatline.h"
#include "chatlinemodelitem.h"
#include "chatscene.h"
+#include "chatview.h"
#include "client.h"
#include "clientbacklogmanager.h"
#include "columnhandleitem.h"
QPointF pos = event->scenePos();
QMenu menu;
+ // zoom actions and similar
+ chatView()->addActionsToMenu(&menu);
+
if(isPosOverSelection(pos))
menu.addAction(SmallIcon("edit-copy"), tr("Copy Selection"),
this, SLOT(selectionToClipboard()),
QKeySequence::Copy);
+ // item-specific options (select link etc)
+ ChatItem *item = chatItemAt(pos);
+ if(item)
+ item->addActionsToMenu(&menu, item->mapFromScene(pos));
+
menu.exec(event->screenPos());
}
if(!hasSelection())
return;
+ stringToClipboard(selection(), mode);
+}
+
+void ChatScene::stringToClipboard(const QString &str, QClipboard::Mode mode) {
switch(mode) {
case QClipboard::Clipboard:
- QApplication::clipboard()->setText(selection());
+ QApplication::clipboard()->setText(str);
break;
case QClipboard::Selection:
if(QApplication::clipboard()->supportsSelection())
- QApplication::clipboard()->setText(selection(), QClipboard::Selection);
+ QApplication::clipboard()->setText(str, QClipboard::Selection);
break;
default:
break;
void clearGlobalSelection();
void clearSelection();
void selectionToClipboard(QClipboard::Mode = QClipboard::Clipboard);
+ void stringToClipboard(const QString &str, QClipboard::Mode = QClipboard::Clipboard);
void requestBacklog();
***************************************************************************/
#include <QGraphicsTextItem>
+#include <QMenu>
#include <QScrollBar>
+#include "bufferwidget.h"
#include "chatlinemodelitem.h"
#include "chatscene.h"
#include "chatview.h"
ChatView::ChatView(BufferId bufferId, QWidget *parent)
: QGraphicsView(parent),
AbstractChatView(),
+ _bufferContainer(0),
_currentScaleFactor(1)
{
QList<BufferId> filterList;
return model->data(model->index(model->rowCount() - 1, 0), MessageModel::MsgIdRole).value<MsgId>();
}
+void ChatView::addActionsToMenu(QMenu *menu) {
+ // zoom actions
+ BufferWidget *bw = qobject_cast<BufferWidget *>(bufferContainer());
+ if(bw) {
+ bw->addActionsToMenu(menu);
+ menu->addSeparator();
+ }
+}
+
void ChatView::zoomIn() {
_currentScaleFactor *= 1.2;
scale(1.2, 1.2);
scene()->setWidth(viewport()->width() / _currentScaleFactor - 2);
}
-void ChatView::zoomNormal() {
+void ChatView::zoomOriginal() {
scale(1/_currentScaleFactor, 1/_currentScaleFactor);
_currentScaleFactor = 1;
scene()->setWidth(viewport()->width() - 2);
#include "abstractbuffercontainer.h"
+class AbstractBufferContainer;
class AbstractUiMsg;
class Buffer;
class ChatLine;
class ChatScene;
class MessageFilter;
+class QMenu;
class ChatView : public QGraphicsView, public AbstractChatView {
Q_OBJECT
ChatView(BufferId bufferId, QWidget *parent = 0);
virtual MsgId lastMsgId() const;
+ inline AbstractBufferContainer *bufferContainer() const { return _bufferContainer; }
+ inline void setBufferContainer(AbstractBufferContainer *c) { _bufferContainer = c; }
+
inline ChatScene *scene() const { return _scene; }
+ void addActionsToMenu(QMenu *);
+
public slots:
inline virtual void clear() {}
void zoomIn();
void zoomOut();
- void zoomNormal();
+ void zoomOriginal();
protected:
virtual void resizeEvent(QResizeEvent *event);
private:
void init(MessageFilter *filter);
+ AbstractBufferContainer *_bufferContainer;
ChatScene *_scene;
int _lastScrollbarPos;
qreal _currentScaleFactor;