forked from qt-creator/qt-creator
Terminal: Improve link copy
* Show link if control key is pressed (without mouse move) * Copy link on Control+Shift+Click * Add Copy Link Action to Right click menu Change-Id: Ide4ff4e77c03e015117c67f09c9d60dedd14dfcb Reviewed-by: Cristian Adam <cristian.adam@qt.io>
This commit is contained in:
@@ -20,6 +20,7 @@ namespace Terminal {
|
||||
|
||||
constexpr char COPY[] = "Terminal.Copy";
|
||||
constexpr char PASTE[] = "Terminal.Paste";
|
||||
constexpr char COPY_LINK[] = "Terminal.CopyLink";
|
||||
constexpr char CLEARSELECTION[] = "Terminal.ClearSelection";
|
||||
constexpr char MOVECURSORWORDLEFT[] = "Terminal.MoveCursorWordLeft";
|
||||
constexpr char MOVECURSORWORDRIGHT[] = "Terminal.MoveCursorWordRight";
|
||||
@@ -59,6 +60,7 @@ void TerminalCommands::initWidgetActions()
|
||||
{
|
||||
m_widgetActions.copy.setText(Tr::tr("Copy"));
|
||||
m_widgetActions.paste.setText(Tr::tr("Paste"));
|
||||
m_widgetActions.copyLink.setText(Tr::tr("Copy Link"));
|
||||
m_widgetActions.clearSelection.setText(Tr::tr("Clear Selection"));
|
||||
m_widgetActions.clearTerminal.setText(Tr::tr("Clear Terminal"));
|
||||
m_widgetActions.moveCursorWordLeft.setText(Tr::tr("Move Cursor Word Left"));
|
||||
@@ -76,6 +78,8 @@ void TerminalCommands::initWidgetActions()
|
||||
{QKeySequence(HostOsInfo::isMacHost() ? QLatin1String("Ctrl+V")
|
||||
: QLatin1String("Ctrl+Shift+V"))});
|
||||
|
||||
registerAction(m_widgetActions.copyLink, COPY_LINK);
|
||||
|
||||
registerAction(m_widgetActions.clearSelection, CLEARSELECTION);
|
||||
|
||||
registerAction(m_widgetActions.moveCursorWordLeft,
|
||||
|
@@ -22,6 +22,7 @@ struct WidgetActions
|
||||
{
|
||||
QAction copy;
|
||||
QAction paste;
|
||||
QAction copyLink;
|
||||
QAction clearSelection;
|
||||
QAction clearTerminal;
|
||||
QAction moveCursorWordLeft;
|
||||
|
@@ -262,6 +262,7 @@ void TerminalWidget::setupActions()
|
||||
// clang-format off
|
||||
connect(&a.copy, &QAction::triggered, this, ifHasFocus(&TerminalWidget::copyToClipboard));
|
||||
connect(&a.paste, &QAction::triggered, this, ifHasFocus(&TerminalWidget::pasteFromClipboard));
|
||||
connect(&a.copyLink, &QAction::triggered, this, ifHasFocus(&TerminalWidget::copyLinkToClipboard));
|
||||
connect(&a.clearSelection, &QAction::triggered, this, ifHasFocus(&TerminalWidget::clearSelection));
|
||||
connect(&a.clearTerminal, &QAction::triggered, this, ifHasFocus(&TerminalWidget::clearContents));
|
||||
connect(&a.moveCursorWordLeft, &QAction::triggered, this, ifHasFocus(&TerminalWidget::moveCursorWordLeft));
|
||||
@@ -390,6 +391,7 @@ void TerminalWidget::updateCopyState()
|
||||
return;
|
||||
|
||||
TerminalCommands::widgetActions().copy.setEnabled(m_selection.has_value());
|
||||
TerminalCommands::widgetActions().copyLink.setEnabled(m_linkSelection.has_value());
|
||||
}
|
||||
|
||||
void TerminalWidget::setFont(const QFont &font)
|
||||
@@ -436,6 +438,12 @@ void TerminalWidget::pasteFromClipboard()
|
||||
m_surface->pasteFromClipboard(clipboardText);
|
||||
}
|
||||
|
||||
void TerminalWidget::copyLinkToClipboard()
|
||||
{
|
||||
if (m_linkSelection)
|
||||
setClipboardAndSelection(m_linkSelection->link.targetFilePath.toUserOutput());
|
||||
}
|
||||
|
||||
void TerminalWidget::clearSelection()
|
||||
{
|
||||
setSelection(std::nullopt);
|
||||
@@ -1086,11 +1094,27 @@ void TerminalWidget::keyPressEvent(QKeyEvent *event)
|
||||
return;
|
||||
}
|
||||
|
||||
if (event->key() == Qt::Key_Control) {
|
||||
if (!m_linkSelection.has_value() && checkLinkAt(mapFromGlobal(QCursor::pos()))) {
|
||||
setCursor(Qt::PointingHandCursor);
|
||||
}
|
||||
}
|
||||
|
||||
event->accept();
|
||||
|
||||
m_surface->sendKey(event);
|
||||
}
|
||||
|
||||
void TerminalWidget::keyReleaseEvent(QKeyEvent *event)
|
||||
{
|
||||
if (event->key() == Qt::Key_Control && m_linkSelection.has_value()) {
|
||||
m_linkSelection.reset();
|
||||
updateCopyState();
|
||||
setCursor(Qt::IBeamCursor);
|
||||
updateViewport();
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalWidget::applySizeChange()
|
||||
{
|
||||
QSize newLiveSize = {
|
||||
@@ -1198,8 +1222,13 @@ void TerminalWidget::mousePressEvent(QMouseEvent *event)
|
||||
|
||||
m_activeMouseSelect.start = viewportToGlobal(event->pos());
|
||||
|
||||
if (event->button() == Qt::LeftButton && event->modifiers() == Qt::ControlModifier) {
|
||||
if (event->button() == Qt::LeftButton && event->modifiers() & Qt::ControlModifier) {
|
||||
if (m_linkSelection) {
|
||||
if (event->modifiers() & Qt::ShiftModifier) {
|
||||
copyLinkToClipboard();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_linkSelection->link.targetFilePath.scheme().toString().startsWith("http")) {
|
||||
QDesktopServices::openUrl(m_linkSelection->link.targetFilePath.toUrl());
|
||||
return;
|
||||
@@ -1231,10 +1260,11 @@ void TerminalWidget::mousePressEvent(QMouseEvent *event)
|
||||
event->accept();
|
||||
updateViewport();
|
||||
} else if (event->button() == Qt::RightButton) {
|
||||
if (event->modifiers() == Qt::ShiftModifier) {
|
||||
if (event->modifiers() & Qt::ShiftModifier) {
|
||||
QMenu *contextMenu = new QMenu(this);
|
||||
contextMenu->addAction(&TerminalCommands::widgetActions().copy);
|
||||
contextMenu->addAction(&TerminalCommands::widgetActions().paste);
|
||||
contextMenu->addAction(&TerminalCommands::widgetActions().copyLink);
|
||||
contextMenu->addSeparator();
|
||||
contextMenu->addAction(&TerminalCommands::widgetActions().clearTerminal);
|
||||
contextMenu->addSeparator();
|
||||
@@ -1303,10 +1333,11 @@ void TerminalWidget::mouseMoveEvent(QMouseEvent *event)
|
||||
}
|
||||
|
||||
setSelection(newSelection);
|
||||
} else if (event->modifiers() == Qt::ControlModifier) {
|
||||
} else if (event->modifiers() & Qt::ControlModifier) {
|
||||
checkLinkAt(event->pos());
|
||||
} else if (m_linkSelection) {
|
||||
m_linkSelection.reset();
|
||||
updateCopyState();
|
||||
updateViewport();
|
||||
}
|
||||
|
||||
@@ -1317,7 +1348,7 @@ void TerminalWidget::mouseMoveEvent(QMouseEvent *event)
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalWidget::checkLinkAt(const QPoint &pos)
|
||||
bool TerminalWidget::checkLinkAt(const QPoint &pos)
|
||||
{
|
||||
const TextAndOffsets hit = textAt(pos);
|
||||
|
||||
@@ -1325,34 +1356,35 @@ void TerminalWidget::checkLinkAt(const QPoint &pos)
|
||||
QString t = QString::fromUcs4(hit.text.c_str(), hit.text.size()).trimmed();
|
||||
t = chopIfEndsWith(t, ':');
|
||||
|
||||
if (t.isEmpty())
|
||||
return;
|
||||
if (!t.isEmpty()) {
|
||||
if (t.startsWith("~/"))
|
||||
t = QDir::homePath() + t.mid(1);
|
||||
|
||||
if (t.startsWith("~/")) {
|
||||
t = QDir::homePath() + t.mid(1);
|
||||
}
|
||||
Link link = Link::fromString(t, true);
|
||||
|
||||
Link link = Link::fromString(t, true);
|
||||
if (!link.targetFilePath.isAbsolutePath())
|
||||
link.targetFilePath = m_cwd.pathAppended(link.targetFilePath.path());
|
||||
|
||||
if (!link.targetFilePath.isAbsolutePath())
|
||||
link.targetFilePath = m_cwd.pathAppended(link.targetFilePath.path());
|
||||
|
||||
if (link.hasValidTarget()
|
||||
&& (link.targetFilePath.scheme().toString().startsWith("http")
|
||||
|| link.targetFilePath.exists())) {
|
||||
const LinkSelection newSelection = LinkSelection{{hit.start, hit.end}, link};
|
||||
if (!m_linkSelection || *m_linkSelection != newSelection) {
|
||||
m_linkSelection = newSelection;
|
||||
updateViewport();
|
||||
if (link.hasValidTarget()
|
||||
&& (link.targetFilePath.scheme().toString().startsWith("http")
|
||||
|| link.targetFilePath.exists())) {
|
||||
const LinkSelection newSelection = LinkSelection{{hit.start, hit.end}, link};
|
||||
if (!m_linkSelection || *m_linkSelection != newSelection) {
|
||||
m_linkSelection = newSelection;
|
||||
updateViewport();
|
||||
updateCopyState();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_linkSelection) {
|
||||
m_linkSelection.reset();
|
||||
updateCopyState();
|
||||
updateViewport();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TerminalWidget::mouseReleaseEvent(QMouseEvent *event)
|
||||
|
@@ -35,6 +35,7 @@ public:
|
||||
|
||||
void copyToClipboard();
|
||||
void pasteFromClipboard();
|
||||
void copyLinkToClipboard();
|
||||
|
||||
void clearSelection();
|
||||
|
||||
@@ -90,6 +91,7 @@ signals:
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void keyPressEvent(QKeyEvent *event) override;
|
||||
void keyReleaseEvent(QKeyEvent *event) override;
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
void wheelEvent(QWheelEvent *event) override;
|
||||
void focusInEvent(QFocusEvent *event) override;
|
||||
@@ -148,7 +150,7 @@ protected:
|
||||
std::optional<QTextLayout::FormatRange> selectionToFormatRange(
|
||||
TerminalWidget::Selection selection, const QTextLayout &layout, int rowOffset) const;
|
||||
|
||||
void checkLinkAt(const QPoint &pos);
|
||||
bool checkLinkAt(const QPoint &pos);
|
||||
|
||||
struct TextAndOffsets
|
||||
{
|
||||
|
Reference in New Issue
Block a user