From: Manuel Nickschas Date: Mon, 17 Nov 2008 00:50:52 +0000 (+0100) Subject: Sanitizing clipboard handling X-Git-Tag: 0.4.0~426 X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=commitdiff_plain;h=b2c1179d290dc97f2c8497db9ed0c8adcc679ed7 Sanitizing clipboard handling Quassel now respects the difference between the clipboard and the X11 selection, and won't put stuff into the clipboard without a) Ctrl+C or b) the new shiny context menu in ChatView. This means that just selecting stuff won't overwrite your clipboard on Win and Mac, and on X11 only if your system is configured that way. Oh, and we have a context menu now, and Ctrl+C works ;-) --- diff --git a/src/qtui/bufferwidget.cpp b/src/qtui/bufferwidget.cpp index 6fc0287d..86f791b6 100644 --- a/src/qtui/bufferwidget.cpp +++ b/src/qtui/bufferwidget.cpp @@ -18,20 +18,21 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ +#include +#include +#include + +#include "action.h" +#include "actioncollection.h" #include "bufferwidget.h" #include "chatview.h" #include "chatviewsearchbar.h" #include "chatviewsearchcontroller.h" -#include "settings.h" #include "client.h" - -#include "action.h" -#include "actioncollection.h" +#include "inputline.h" #include "qtui.h" +#include "settings.h" -#include -#include -#include BufferWidget::BufferWidget(QWidget *parent) : AbstractBufferContainer(parent), @@ -64,7 +65,7 @@ BufferWidget::BufferWidget(QWidget *parent) connect(_chatViewSearchController, SIGNAL(newCurrentHighlight(QGraphicsItem *)), this, SLOT(scrollToHighlight(QGraphicsItem *))); - + ActionCollection *coll = QtUi::actionCollection(); Action *zoomChatview = coll->add("ZoomChatView"); @@ -149,6 +150,19 @@ bool BufferWidget::eventFilter(QObject *watched, QEvent *event) { QKeyEvent *keyEvent = static_cast(event); + // Intercept copy key presses + if(keyEvent == QKeySequence::Copy) { + InputLine *inputLine = qobject_cast(watched); + if(!inputLine) + return false; + if(inputLine->hasSelectedText()) + return false; + ChatView *view = qobject_cast(ui.stackedWidget->currentWidget()); + if(view) + view->scene()->selectionToClipboard(); + return true; + } + int direction = 1; switch(keyEvent->key()) { case Qt::Key_PageUp: diff --git a/src/qtui/chatitem.cpp b/src/qtui/chatitem.cpp index ed24bbaf..9e7e1eb6 100644 --- a/src/qtui/chatitem.cpp +++ b/src/qtui/chatitem.cpp @@ -289,9 +289,7 @@ void ChatItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { void ChatItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { if(_selectionMode != NoSelection && !event->buttons() & Qt::LeftButton) { - QString selection - = data(MessageModel::DisplayRole).toString().mid(qMin(_selectionStart, _selectionEnd), qAbs(_selectionStart - _selectionEnd)); - chatScene()->putToClipboard(selection); + chatScene()->selectionToClipboard(QClipboard::Selection); event->accept(); } else event->ignore(); @@ -559,6 +557,7 @@ void ContentsChatItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { event->accept(); } +/* void ContentsChatItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { qint16 idx = posToCursor(event->pos()); for(int i = 0; i < privateData()->clickables.count(); i++) { @@ -581,6 +580,7 @@ void ContentsChatItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { } } } +*/ void ContentsChatItem::showWebPreview(const Clickable &click) { #ifndef HAVE_WEBKIT diff --git a/src/qtui/chatitem.h b/src/qtui/chatitem.h index 3cb9c3d7..a3927eb5 100644 --- a/src/qtui/chatitem.h +++ b/src/qtui/chatitem.h @@ -187,7 +187,7 @@ protected: virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event); - virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event); + //virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event); virtual void handleClick(const QPointF &pos, ChatScene::ClickMode clickMode); diff --git a/src/qtui/chatscene.cpp b/src/qtui/chatscene.cpp index dc388543..9d1e04a2 100644 --- a/src/qtui/chatscene.cpp +++ b/src/qtui/chatscene.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -32,6 +33,7 @@ #include "client.h" #include "clientbacklogmanager.h" #include "columnhandleitem.h" +#include "iconloader.h" #include "messagefilter.h" #include "qtui.h" #include "qtuistyle.h" @@ -571,6 +573,19 @@ bool ChatScene::isScrollingAllowed() const { /******** MOUSE HANDLING **************************************************************************/ +void ChatScene::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { + QPointF pos = event->scenePos(); + QMenu menu; + + if(isPosOverSelection(pos)) + menu.addAction(SmallIcon("edit-copy"), tr("Copy Selection"), + this, SLOT(selectionToClipboard()), + QKeySequence::Copy); + + menu.exec(event->screenPos()); + +} + void ChatScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { if(event->buttons() == Qt::LeftButton) { if(!_clickHandled && (event->scenePos() - _clickPos).toPoint().manhattanLength() >= QApplication::startDragDistance()) { @@ -635,7 +650,7 @@ void ChatScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { } else { // no click -> drag or selection move if(isGloballySelecting()) { - putToClipboard(selection()); + selectionToClipboard(QClipboard::Selection); _isSelecting = false; event->accept(); return; @@ -660,9 +675,6 @@ void ChatScene::handleClick(Qt::MouseButton button, const QPointF &scenePos) { chatItem->handleClick(chatItem->mapFromScene(scenePos), _clickMode); } _clickHandled = true; - } else if(button == Qt::RightButton) { - // TODO: context menu - } } @@ -677,14 +689,21 @@ void ChatScene::initiateDrag(QWidget *source) { /******** SELECTIONS ******************************************************************************/ -void ChatScene::putToClipboard(const QString &selection) { - // TODO Configure clipboards -# ifdef Q_WS_X11 - QApplication::clipboard()->setText(selection, QClipboard::Selection); -# endif -//# else - QApplication::clipboard()->setText(selection); -//# endif +void ChatScene::selectionToClipboard(QClipboard::Mode mode) { + if(!hasSelection()) + return; + + switch(mode) { + case QClipboard::Clipboard: + QApplication::clipboard()->setText(selection()); + break; + case QClipboard::Selection: + if(QApplication::clipboard()->supportsSelection()) + QApplication::clipboard()->setText(selection(), QClipboard::Selection); + break; + default: + break; + }; } //!\brief Convert current selection to human-readable string. @@ -711,6 +730,18 @@ QString ChatScene::selection() const { return QString(); } +bool ChatScene::hasSelection() const { + return hasGlobalSelection() || (selectingItem() && selectingItem()->hasSelection()); +} + +bool ChatScene::hasGlobalSelection() const { + return _selectionStart >= 0; +} + +bool ChatScene::isGloballySelecting() const { + return _isSelecting; +} + void ChatScene::clearGlobalSelection() { if(hasGlobalSelection()) { for(int l = qMin(_selectionStart, _selectionEnd); l <= qMax(_selectionStart, _selectionEnd); l++) diff --git a/src/qtui/chatscene.h b/src/qtui/chatscene.h index 3349d2f4..1c641093 100644 --- a/src/qtui/chatscene.h +++ b/src/qtui/chatscene.h @@ -22,6 +22,7 @@ #define CHATSCENE_H_ #include +#include #include #include #include @@ -92,9 +93,10 @@ public: inline void setSenderCutoffMode(CutoffMode mode) { _cutoffMode = mode; } QString selection() const; - inline bool hasGlobalSelection() const { return _selectionStart >= 0; } - inline bool isGloballySelecting() const { return _isSelecting; } + bool hasSelection() const; + bool hasGlobalSelection() const; bool isPosOverSelection(const QPointF &) const; + bool isGloballySelecting() const; void initiateDrag(QWidget *source); bool isScrollingAllowed() const; @@ -111,8 +113,7 @@ public: void startGlobalSelection(ChatItem *item, const QPointF &itemPos); void clearGlobalSelection(); void clearSelection(); - - void putToClipboard(const QString &); + void selectionToClipboard(QClipboard::Mode = QClipboard::Clipboard); void requestBacklog(); @@ -125,6 +126,7 @@ signals: void mouseMoveWhileSelecting(const QPointF &scenePos); protected: + virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *contextMenuEvent); virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent); virtual void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent); virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent); diff --git a/src/uisupport/inputline.cpp b/src/uisupport/inputline.cpp index b48c053d..b74e10ec 100644 --- a/src/uisupport/inputline.cpp +++ b/src/uisupport/inputline.cpp @@ -19,7 +19,6 @@ ***************************************************************************/ #include "inputline.h" - #include "tabcompleter.h" InputLine::InputLine(QWidget *parent) @@ -40,19 +39,19 @@ void InputLine::keyPressEvent(QKeyEvent * event) { event->accept(); addToHistory(text(), true); - + if(idx > 0) { idx--; showHistoryEntry(); } break; - + case Qt::Key_Down: event->accept(); addToHistory(text(), true); - + if(idx < history.count()) { idx++; if(idx < history.count() || tempHistory.contains(idx)) // tempHistory might have an entry for idx == history.count() + 1 @@ -65,7 +64,7 @@ void InputLine::keyPressEvent(QKeyEvent * event) { } break; - + case Qt::Key_Select: // for Qtopia emit returnPressed(); @@ -79,7 +78,7 @@ bool InputLine::addToHistory(const QString &text, bool temporary) { return false; Q_ASSERT(0 <= idx && idx <= history.count()); - + if(history.isEmpty() || text != history[idx - (int)(idx == history.count())]) { // if an entry of the history is changed, we remember it and show it again at this // position until a line was actually sent @@ -107,7 +106,7 @@ void InputLine::on_textChanged(QString newText) { lineSeperators << QString("\r\n") << QString('\n') << QString('\r'); - + QString lineSep; foreach(QString seperator, lineSeperators) { if(newText.contains(seperator)) { @@ -118,7 +117,7 @@ void InputLine::on_textChanged(QString newText) { if(lineSep.isEmpty()) return; - + if(newText.contains(lineSep)) { clear(); QString line = newText.section(lineSep, 0, 0); diff --git a/src/uisupport/inputline.h b/src/uisupport/inputline.h index 88d60620..ff6091d4 100644 --- a/src/uisupport/inputline.h +++ b/src/uisupport/inputline.h @@ -31,7 +31,7 @@ class InputLine : public QLineEdit { public: InputLine(QWidget *parent = 0); ~InputLine(); - + protected: // virtual bool event(QEvent *); virtual void keyPressEvent(QKeyEvent * event);