From bb818010b42a3d6fcdc4a057f0afd2e7b7a85b9f Mon Sep 17 00:00:00 2001 From: Jekyll Wu Date: Wed, 25 Apr 2012 12:08:40 +0800 Subject: [PATCH] Add two profile options for the copy & paste behavior of mouse * support "automatially copy selected text into clipboard" * mouse middle button can be customized to paste from selectio or clipboard The first feature might look like a unnecessary duplicate of the "synchronize selection and clipboard" feature of Klipper. However, that klipper feature is generally problematic, while doing it only in Konsole is generally useful and harmless. FEATURE: 183490 FIXED-IN: 4.9.0 REVIEW: 103861 DIGEST: --- src/EditProfileDialog.cpp | 65 +++++++--- src/EditProfileDialog.h | 13 +- src/EditProfileDialog.ui | 258 ++++++++++++++++++++++++-------------- src/Enumeration.h | 8 ++ src/Profile.cpp | 8 ++ src/Profile.h | 16 +++ src/SessionController.cpp | 8 +- src/SessionController.h | 2 +- src/TerminalDisplay.cpp | 74 ++++++++--- src/TerminalDisplay.h | 23 ++-- src/ViewManager.cpp | 7 ++ 11 files changed, 341 insertions(+), 141 deletions(-) diff --git a/src/EditProfileDialog.cpp b/src/EditProfileDialog.cpp index 1c0a462e3..21aa09734 100644 --- a/src/EditProfileDialog.cpp +++ b/src/EditProfileDialog.cpp @@ -213,6 +213,8 @@ void EditProfileDialog::preparePage(int page) setupScrollingPage(profile); else if (pageWidget == _ui->keyboardTab) setupKeyboardPage(profile); + else if (pageWidget == _ui->mouseTab) + setupMousePage(profile); else if (pageWidget == _ui->advancedTab) setupAdvancedPage(profile); else @@ -978,6 +980,41 @@ void EditProfileDialog::showScrollBarRight() { updateTempProfileProperty(Profile::ScrollBarPosition, Enum::ScrollBarRight); } +void EditProfileDialog::setupMousePage(const Profile::Ptr profile) +{ + BooleanOption options[] = { { + _ui->underlineLinksButton , Profile::UnderlineLinksEnabled, + SLOT(toggleUnderlineLinks(bool)) + }, + { + _ui->copyTextToClipboardButton , Profile::AutoCopySelectedText, + SLOT(toggleCopyTextToClipboard(bool)) + }, + { 0 , Profile::Property(0) , 0 } + }; + setupCheckBoxes(options , profile); + + // setup middle click paste mode + const int middleClickPasteMode = profile->property(Profile::MiddleClickPasteMode); + RadioOption pasteModes[] = { + {_ui->pasteFromX11SelectionButton, Enum::PasteFromX11Selection, SLOT(pasteFromX11Selection())}, + {_ui->pasteFromClipboardButton, Enum::PasteFromClipboard, SLOT(pasteFromClipboard())}, + {0, 0, 0} + }; + setupRadio(pasteModes , middleClickPasteMode); + + // interaction options + _ui->wordCharacterEdit->setText(profile->wordCharacters()); + + connect(_ui->wordCharacterEdit, SIGNAL(textChanged(QString)), this, + SLOT(wordCharactersChanged(QString))); + + int tripleClickMode = profile->property(Profile::TripleClickMode); + _ui->tripleClickModeCombo->setCurrentIndex(tripleClickMode); + + connect(_ui->tripleClickModeCombo, SIGNAL(activated(int)), this, + SLOT(TripleClickModeChanged(int))); +} void EditProfileDialog::setupAdvancedPage(const Profile::Ptr profile) { BooleanOption options[] = { { @@ -992,10 +1029,6 @@ void EditProfileDialog::setupAdvancedPage(const Profile::Ptr profile) _ui->enableBlinkingCursorButton , Profile::BlinkingCursorEnabled , SLOT(toggleBlinkingCursor(bool)) }, - { - _ui->underlineLinksButton , Profile::UnderlineLinksEnabled, - SLOT(toggleUnderlineLinks(bool)) - }, { _ui->enableBidiRenderingButton , Profile::BidiRenderingEnabled , SLOT(togglebidiRendering(bool)) @@ -1004,18 +1037,6 @@ void EditProfileDialog::setupAdvancedPage(const Profile::Ptr profile) }; setupCheckBoxes(options , profile); - // interaction options - _ui->wordCharacterEdit->setText(profile->wordCharacters()); - - connect(_ui->wordCharacterEdit, SIGNAL(textChanged(QString)), this, - SLOT(wordCharactersChanged(QString))); - - int tripleClickMode = profile->property(Profile::TripleClickMode); - _ui->tripleClickModeCombo->setCurrentIndex(tripleClickMode); - - connect(_ui->tripleClickModeCombo, SIGNAL(activated(int)), this, - SLOT(TripleClickModeChanged(int))); - // cursor options if (profile->useCustomCursorColor()) _ui->customCursorColorButton->setChecked(true); @@ -1084,6 +1105,18 @@ void EditProfileDialog::toggleUnderlineLinks(bool enable) { updateTempProfileProperty(Profile::UnderlineLinksEnabled, enable); } +void EditProfileDialog::toggleCopyTextToClipboard(bool enable) +{ + updateTempProfileProperty(Profile::AutoCopySelectedText, enable); +} +void EditProfileDialog::pasteFromX11Selection() +{ + updateTempProfileProperty(Profile::MiddleClickPasteMode, Enum::PasteFromX11Selection); +} +void EditProfileDialog::pasteFromClipboard() +{ + updateTempProfileProperty(Profile::MiddleClickPasteMode, Enum::PasteFromClipboard); +} void EditProfileDialog::TripleClickModeChanged(int newValue) { updateTempProfileProperty(Profile::TripleClickMode, newValue); diff --git a/src/EditProfileDialog.h b/src/EditProfileDialog.h index c330fc68f..682db9124 100644 --- a/src/EditProfileDialog.h +++ b/src/EditProfileDialog.h @@ -149,19 +149,25 @@ private slots: void keyBindingSelected(); void removeKeyBinding(); + // mouse page + void toggleUnderlineLinks(bool); + void toggleCopyTextToClipboard(bool); + void pasteFromX11Selection(); + void pasteFromClipboard(); + + void TripleClickModeChanged(int); + void wordCharactersChanged(const QString&); + // advanced page void toggleBlinkingText(bool); void toggleFlowControl(bool); void togglebidiRendering(bool); void toggleBlinkingCursor(bool); - void TripleClickModeChanged(int); - void toggleUnderlineLinks(bool); void setCursorShape(int); void autoCursorColor(); void customCursorColor(); void customCursorColorChanged(const QColor&); - void wordCharactersChanged(const QString&); void setDefaultCodec(QTextCodec*); // apply the first previewed changes stored up by delayedPreview() @@ -175,6 +181,7 @@ private: void setupKeyboardPage(const Profile::Ptr profile); void setupScrollingPage(const Profile::Ptr profile); void setupAdvancedPage(const Profile::Ptr profile); + void setupMousePage(const Profile::Ptr info); void updateColorSchemeList(bool selectCurrentScheme = false); void updateColorSchemeButtons(); diff --git a/src/EditProfileDialog.ui b/src/EditProfileDialog.ui index 707c20a12..29c082887 100644 --- a/src/EditProfileDialog.ui +++ b/src/EditProfileDialog.ui @@ -6,7 +6,7 @@ 0 0 - 441 + 594 551 @@ -267,7 +267,7 @@ - + @@ -532,8 +532,7 @@ - - + @@ -615,7 +614,7 @@ - Input + Keyboard @@ -695,6 +694,168 @@ + + + Mouse + + + + + + Select Text + + + true + + + + + + + + Characters considered part of a word when double clicking: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + true + + + + + + + Characters which are considered part of a word when double-clicking to select whole words in the terminal + + + + + + + + + + + Triple-click select: + + + + + + + Which part of current line should be selected with triple click . + + + + The whole current line + + + + + From mouse position to the end of line + + + + + + + + + + + + + Copy && Paste + + + true + + + + + + Automatically copy selected text into clipboard + + + Copy on select + + + + + + + Qt::Horizontal + + + + 561 + 5 + + + + + + + + Mouse middle button: + + + + + + + Paste from selection + + + + + + + Paste from clipboard + + + + + + + + + + Miscellaneous + + + true + + + + + + Text recognized as a link or an email address will be underlined when hovered by the mouse pointer. + + + Underline links + + + + + + + + + + Qt::Vertical + + + + 20 + 328 + + + + + + Advanced @@ -760,93 +921,6 @@ - - - - Mouse Interaction - - - true - - - - - - - - Characters considered part of a word when double clicking: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - true - - - - - - - Characters which are considered part of a word when double-clicking to select whole words in the terminal - - - - - - - - - - - Triple-click select: - - - - - - - Which part of current line should be selected with triple click . - - - - The whole current line - - - - - From mouse position to the end of line - - - - - - - - Qt::Horizontal - - - - 0 - 0 - - - - - - - - - - Text recognized as a link or an email address will be underlined when hovered by the mouse pointer. - - - Underline links - - - - - - diff --git a/src/Enumeration.h b/src/Enumeration.h index 8fe227770..99919f1ce 100644 --- a/src/Enumeration.h +++ b/src/Enumeration.h @@ -88,6 +88,14 @@ public: SelectForwardsFromCursor = 1 }; + /** This enum describes the source from which mouse middle click pastes data . */ + enum MiddleClickPasteModeEnum { + /** Paste from X11 Selection. */ + PasteFromX11Selection = 0, + /** Paste from Clipboard. */ + PasteFromClipboard = 1 + }; + /** * This enum describes the different types of sounds and visual effects which * can be used to alert the user when a 'bell' occurs in the terminal diff --git a/src/Profile.cpp b/src/Profile.cpp index 198640ecc..dfea34203 100644 --- a/src/Profile.cpp +++ b/src/Profile.cpp @@ -102,6 +102,10 @@ const Profile::PropertyInfo Profile::DefaultPropertyNames[] = { , { WordCharacters , "WordCharacters" , INTERACTION_GROUP , QVariant::String } , { TripleClickMode , "TripleClickMode" , INTERACTION_GROUP , QVariant::Int } , { UnderlineLinksEnabled , "UnderlineLinksEnabled" , INTERACTION_GROUP , QVariant::Bool } + , { AutoCopySelectedText , "AutoCopySelectedText" , INTERACTION_GROUP , QVariant::Bool } + , { PasteFromSelectionEnabled , "PasteFromSelectionEnabled" , INTERACTION_GROUP , QVariant::Bool } + , { PasteFromClipboardEnabled , "PasteFromClipboardEnabled" , INTERACTION_GROUP , QVariant::Bool } + , { MiddleClickPasteMode, "MiddleClickPasteMode" , INTERACTION_GROUP , QVariant::Int } // Encoding , { DefaultEncoding , "DefaultEncoding" , ENCODING_GROUP , QVariant::String } @@ -161,6 +165,10 @@ FallbackProfile::FallbackProfile() setProperty(FlowControlEnabled, true); setProperty(BlinkingTextEnabled, true); setProperty(UnderlineLinksEnabled, true); + setProperty(AutoCopySelectedText, false); + setProperty(PasteFromSelectionEnabled, true); + setProperty(PasteFromClipboardEnabled, false); + setProperty(MiddleClickPasteMode, Enum::PasteFromX11Selection); setProperty(TripleClickMode, Enum::SelectWholeLine); setProperty(BlinkingCursorEnabled, false); diff --git a/src/Profile.h b/src/Profile.h index 78e95cffc..acc344639 100644 --- a/src/Profile.h +++ b/src/Profile.h @@ -196,6 +196,18 @@ public: * underlined when hovered by the mouse pointer. */ UnderlineLinksEnabled, + /** (bool) If true, automatically copy selected text into the clipboard */ + AutoCopySelectedText, + /** (bool) If true, middle mouse button pastes from X Selection */ + PasteFromSelectionEnabled, + /** (bool) If true, middle mouse button pastes from Clipboard */ + PasteFromClipboardEnabled, + /** (MiddleClickPasteModeEnum) Specifies the source from which mouse + * middle click pastes data. + * + * See Enum::MiddleClickPasteModeEnum + */ + MiddleClickPasteMode, /** (String) Default text codec */ DefaultEncoding, /** (bool) Whether fonts should be aliased or not */ @@ -421,6 +433,10 @@ public: return property(Profile::UnderlineLinksEnabled); } + bool autoCopySelectedText() const { + return property(Profile::AutoCopySelectedText); + } + /** Convenience method for property(Profile::DefaultEncoding) */ QString defaultEncoding() const { return property(Profile::DefaultEncoding); diff --git a/src/SessionController.cpp b/src/SessionController.cpp index 0404f1f04..0c912958a 100644 --- a/src/SessionController.cpp +++ b/src/SessionController.cpp @@ -543,7 +543,7 @@ void SessionController::setupCommonActions() pasteShortcut.setAlternate(QKeySequence(Qt::SHIFT + Qt::Key_Insert)); action->setShortcut(pasteShortcut); - action = collection->addAction("paste-selection", this, SLOT(pasteFromXSelection())); + action = collection->addAction("paste-selection", this, SLOT(pasteFromX11Selection())); action->setText(i18n("Paste Selection")); action->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Insert)); @@ -833,15 +833,15 @@ void SessionController::paste() { _view->pasteFromClipboard(); } -void SessionController::pasteFromXSelection() +void SessionController::pasteFromX11Selection() { - _view->pasteFromXSelection(); + _view->pasteFromX11Selection(); } void SessionController::selectAll() { ScreenWindow * screenWindow = _view->screenWindow(); screenWindow->setSelectionByLineRange(0, _session->emulation()->lineCount()); - TerminalDisplay::setXSelection(screenWindow->selectedText(true)); + _view->copyToX11Selection(); } static const KXmlGuiWindow* findWindow(const QObject* object) { diff --git a/src/SessionController.h b/src/SessionController.h index 85dbdbbeb..cd5a9ff1b 100644 --- a/src/SessionController.h +++ b/src/SessionController.h @@ -218,7 +218,7 @@ private slots: void copy(); void paste(); void selectAll(); - void pasteFromXSelection(); // shortcut only + void pasteFromX11Selection(); // shortcut only void copyInputActionsTriggered(QAction* action); void copyInputToAllTabs(); void copyInputToSelectedTabs(); diff --git a/src/TerminalDisplay.cpp b/src/TerminalDisplay.cpp index 195942b5f..32e09d9be 100644 --- a/src/TerminalDisplay.cpp +++ b/src/TerminalDisplay.cpp @@ -63,6 +63,8 @@ #include "WindowSystemInfo.h" #include "ExtendedCharTable.h" #include "TerminalDisplayAccessible.h" +#include "SessionManager.h" +#include "Session.h" using namespace Konsole; @@ -304,6 +306,8 @@ TerminalDisplay::TerminalDisplay(QWidget* parent) , _lineSelectionMode(false) , _preserveLineBreaks(false) , _columnSelectionMode(false) + , _autoCopySelectedText(false) + , _middleClickPasteMode(Enum::PasteFromX11Selection) , _scrollbarLocation(Enum::ScrollBarRight) , _wordCharacters(":@-./_~") , _bellMode(Enum::NotifyBell) @@ -1793,10 +1797,21 @@ void TerminalDisplay::mousePressEvent(QMouseEvent* ev) } } } else if (ev->button() == Qt::MidButton) { - if (_mouseMarks || (ev->modifiers() & Qt::ShiftModifier)) - doPaste(true, ev->modifiers() & Qt::ControlModifier); - else + if (_mouseMarks || (ev->modifiers() & Qt::ShiftModifier)) { + + const bool appendEnter = ev->modifiers() & Qt::ControlModifier; + + if ( _middleClickPasteMode == Enum::PasteFromX11Selection ) { + pasteFromX11Selection(appendEnter); + } else if ( _middleClickPasteMode == Enum::PasteFromClipboard ) { + pasteFromClipboard(appendEnter); + } else { + Q_ASSERT(false); + } + + } else { emit mouseSignal(1, charColumn + 1, charLine + 1 + _scrollBar->value() - _scrollBar->maximum() , 0); + } } else if (ev->button() == Qt::RightButton) { if (_mouseMarks || (ev->modifiers() & Qt::ShiftModifier)) emit configureRequest(ev->pos()); @@ -2134,7 +2149,7 @@ void TerminalDisplay::mouseReleaseEvent(QMouseEvent* ev) _screenWindow->clearSelection(); } else { if (_actSel > 1) { - setXSelection(_screenWindow->selectedText(_preserveLineBreaks)); + copyToX11Selection(); } _actSel = 0; @@ -2269,7 +2284,7 @@ void TerminalDisplay::mouseDoubleClickEvent(QMouseEvent* ev) _screenWindow->setSelectionEnd(endSel.x() , endSel.y()); - setXSelection(_screenWindow->selectedText(_preserveLineBreaks)); + copyToX11Selection(); } _possibleTripleClick = true; @@ -2390,7 +2405,7 @@ void TerminalDisplay::mouseTripleClickEvent(QMouseEvent* ev) _screenWindow->setSelectionEnd(_columns - 1 , _iPntSel.y()); - setXSelection(_screenWindow->selectedText(_preserveLineBreaks)); + copyToX11Selection(); _iPntSel.ry() += _scrollBar->value(); } @@ -2455,28 +2470,47 @@ bool TerminalDisplay::usesMouse() const /* */ /* ------------------------------------------------------------------------- */ -void TerminalDisplay::doPaste(bool useXselection, bool appendReturn) +void TerminalDisplay::doPaste(QString text, bool appendReturn) { if (!_screenWindow) return; - // Paste Clipboard by simulating keypress events - QString text = QApplication::clipboard()->text(useXselection ? QClipboard::Selection : - QClipboard::Clipboard); if (appendReturn) text.append("\r"); + if (! text.isEmpty()) { text.replace('\n', '\r'); + // perform paste by simulating keypress events QKeyEvent e(QEvent::KeyPress, 0, Qt::NoModifier, text); - emit keyPressedSignal(&e); // expose as a big fat keypress event + emit keyPressedSignal(&e); _screenWindow->clearSelection(); } } -void TerminalDisplay::setXSelection(const QString& text) +void TerminalDisplay::setAutoCopySelectedText(bool enabled) { + _autoCopySelectedText = enabled; +} + +void TerminalDisplay::setMiddleClickPasteMode(Enum::MiddleClickPasteModeEnum mode) +{ + _middleClickPasteMode = mode; +} + +void TerminalDisplay::copyToX11Selection() +{ + if (!_screenWindow) + return; + + QString text = _screenWindow->selectedText(_preserveLineBreaks); + if (text.isEmpty()) + return; + QApplication::clipboard()->setText(text, QClipboard::Selection); + + if (_autoCopySelectedText) + QApplication::clipboard()->setText(text, QClipboard::Clipboard); } void TerminalDisplay::copyToClipboard() @@ -2485,18 +2519,22 @@ void TerminalDisplay::copyToClipboard() return; QString text = _screenWindow->selectedText(_preserveLineBreaks); - if (!text.isEmpty()) - QApplication::clipboard()->setText(text); + if (text.isEmpty()) + return; + + QApplication::clipboard()->setText(text, QClipboard::Clipboard); } -void TerminalDisplay::pasteFromClipboard() +void TerminalDisplay::pasteFromClipboard(bool appendEnter) { - doPaste(false, false); + QString text = QApplication::clipboard()->text(QClipboard::Clipboard); + doPaste(text, appendEnter); } -void TerminalDisplay::pasteFromXSelection() +void TerminalDisplay::pasteFromX11Selection(bool appendEnter) { - doPaste(true, false); + QString text = QApplication::clipboard()->text(QClipboard::Selection); + doPaste(text, appendEnter); } /* ------------------------------------------------------------------------- */ diff --git a/src/TerminalDisplay.h b/src/TerminalDisplay.h index 5b067cd72..40168be30 100644 --- a/src/TerminalDisplay.h +++ b/src/TerminalDisplay.h @@ -404,8 +404,6 @@ public: /** Returns the terminal screen section which is displayed in this widget. See setScreenWindow() */ ScreenWindow* screenWindow() const; - static void setXSelection(const QString& text); - public slots: /** * Scrolls current ScreenWindow @@ -425,18 +423,26 @@ public slots: */ void updateLineProperties(); - /** Copies the selected text to the clipboard. */ + void setAutoCopySelectedText(bool enabled); + + void setMiddleClickPasteMode(Enum::MiddleClickPasteModeEnum mode); + + /** Copies the selected text to the X11 Selection. */ + void copyToX11Selection(); + + /** Copies the selected text to the system clipboard. */ void copyToClipboard(); + /** * Pastes the content of the clipboard into the * display. */ - void pasteFromClipboard(); + void pasteFromClipboard(bool appendEnter=false); /** - * Pastes the content of the X selection into the + * Pastes the content of the X11 selection into the * display. */ - void pasteFromXSelection(); + void pasteFromX11Selection(bool appendEnter=false); /** * Changes whether the flow control warning box should be shown when the flow control @@ -685,7 +691,7 @@ private: bool handleShortcutOverrideEvent(QKeyEvent* event); - void doPaste(bool useXselection, bool appendReturn); + void doPaste(QString text, bool appendReturn); // the window onto the terminal screen which this display // is currently showing. @@ -740,6 +746,9 @@ private: bool _preserveLineBreaks; bool _columnSelectionMode; + bool _autoCopySelectedText; + Enum::MiddleClickPasteModeEnum _middleClickPasteMode; + QScrollBar* _scrollBar; Enum::ScrollBarPositionEnum _scrollbarLocation; QString _wordCharacters; diff --git a/src/ViewManager.cpp b/src/ViewManager.cpp index c654ace2a..4885c8683 100644 --- a/src/ViewManager.cpp +++ b/src/ViewManager.cpp @@ -804,9 +804,16 @@ void ViewManager::applyProfileToView(TerminalDisplay* view , const Profile::Ptr int tripleClickMode = profile->property(Profile::TripleClickMode); view->setTripleClickMode(Enum::TripleClickModeEnum(tripleClickMode)); + view->setAutoCopySelectedText(profile->autoCopySelectedText()); view->setUnderlineLinks(profile->underlineLinksEnabled()); view->setBidiEnabled(profile->bidiRenderingEnabled()); + int middleClickPasteMode = profile->property(Profile::MiddleClickPasteMode); + if (middleClickPasteMode == Enum::PasteFromX11Selection) + view->setMiddleClickPasteMode(Enum::PasteFromX11Selection); + else if (middleClickPasteMode == Enum::PasteFromClipboard) + view->setMiddleClickPasteMode(Enum::PasteFromClipboard); + // cursor shape int cursorShape = profile->property(Profile::CursorShape);