复制粘贴——QT实现原理
复制粘贴——QT实现原理
QT 剪贴板相关类
QClipboard
对外通用的剪贴板类,一般通过QGuiApplication::clipboard() 来获取对应的剪贴板实例。
// qtbase/src/gui/kernel/qclipboard.h
class Q_GUI_EXPORT QClipboard : public QObject
{Q_OBJECT
private:explicit QClipboard(QObject *parent);~QClipboard();public:enum Mode { Clipboard, Selection, FindBuffer, LastMode = FindBuffer };void clear(Mode mode = Clipboard);bool supportsSelection() const;bool supportsFindBuffer() const;bool ownsSelection() const;bool ownsClipboard() const;bool ownsFindBuffer() const;QString text(Mode mode = Clipboard) const;QString text(QString& subtype, Mode mode = Clipboard) const;void setText(const QString &, Mode mode = Clipboard);const QMimeData *mimeData(Mode mode = Clipboard ) const;void setMimeData(QMimeData *data, Mode mode = Clipboard);QImage image(Mode mode = Clipboard) const;QPixmap pixmap(Mode mode = Clipboard) const;void setImage(const QImage &, Mode mode = Clipboard);void setPixmap(const QPixmap &, Mode mode = Clipboard);Q_SIGNALS:void changed(QClipboard::Mode mode);void selectionChanged();void findBufferChanged();void dataChanged();protected:friend class QApplication;friend class QApplicationPrivate;friend class QGuiApplication;friend class QBaseApplication;friend class QDragManager;friend class QPlatformClipboard;private:Q_DISABLE_COPY(QClipboard)bool supportsMode(Mode mode) const;bool ownsMode(Mode mode) const;void emitChanged(Mode mode);
};
QPlatformClipboard
系统剪切板平台接口类,各种桌面平台(Windows,X11,Wayland等)通过这个类提供统一的剪贴板操作接口。
// qtbase/src/gui/kernel/qplatformclipboard.h
class Q_GUI_EXPORT QPlatformClipboard
{
public:virtual ~QPlatformClipboard();virtual QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard);virtual void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard);virtual bool supportsMode(QClipboard::Mode mode) const;virtual bool ownsMode(QClipboard::Mode mode) const;void emitChanged(QClipboard::Mode mode);
};
QXcbClipboard
X11平台实现的剪贴板接口类,继承自QPlatformClipboard,它主要实现了基类的大部分接口,除了emitChanged 这个接口。
// qtbase/src/plugins/platforms/xcb/qxcbclipboard.h
class QXcbClipboard : public QXcbObject, public QPlatformClipboard
{
public:QXcbClipboard(QXcbConnection *connection);~QXcbClipboard();QMimeData *mimeData(QClipboard::Mode mode) override;void setMimeData(QMimeData *data, QClipboard::Mode mode) override;bool supportsMode(QClipboard::Mode mode) const override;bool ownsMode(QClipboard::Mode mode) const override;
...
};
QWindowsClipboard
Windows平台下的剪贴板接口类,继承自QPlatformClipboard 。
// qtbase/src/plugins/platforms/windows/qwindowsclipboard.h
class QWindowsClipboard : public QPlatformClipboard
{
public:QWindowsClipboard();~QWindowsClipboard();void registerViewer(); // Call in initialization, when context is up.void cleanup();QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard) override;void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard) override;bool supportsMode(QClipboard::Mode mode) const override;bool ownsMode(QClipboard::Mode mode) const override;
...
}
可以看出,同一目录下还有其他各种平台的实现接口:

QWaylandClipboard
Wayland平台实现的剪贴板接口.
// qtwayland/src/client/qwaylandclipboard_p.h
class Q_WAYLAND_CLIENT_EXPORT QWaylandClipboard : public QPlatformClipboard
{
public:QWaylandClipboard(QWaylandDisplay *display);~QWaylandClipboard() override;QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard) override;void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard) override;bool supportsMode(QClipboard::Mode mode) const override;bool ownsMode(QClipboard::Mode mode) const override;private:QWaylandDisplay *mDisplay = nullptr;QMimeData m_emptyData;
};
QT 剪贴板相关接口
通过查看QClipboard 类的定义,我们比较关心的接口有:
const QMimeData *mimeData(Mode mode = Clipboard ) const;void setMimeData(QMimeData *data, Mode mode = Clipboard);
Q_SIGNALS:void changed(QClipboard::Mode mode);void selectionChanged();void findBufferChanged();void dataChanged();
获取剪贴板最基础的应该是mimeData 这个接口:
const QMimeData* QClipboard::mimeData(Mode mode) const
{// 获取一个QPlatformClipboard对象,根据不同平台返回的应该是不同的子类,比如x11下就返回的是QXcbClipboardQPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard();if (!clipboard->supportsMode(mode)) return 0;return clipboard->mimeData(mode);
}
可以看出,最终是通过X11接口拿到的。
另外,我们关系剪贴板变化的信号在什么情况下发出来,从实现可以看出,基本是在emitChanged 里发出来的。
/*!\internalEmits the appropriate changed signal for \a mode.
*/
void QClipboard::emitChanged(Mode mode)
{switch (mode) {case Clipboard:emit dataChanged();break;case Selection:emit selectionChanged();break;case FindBuffer:emit findBufferChanged();break;default:break;}emit changed(mode);
}
还有一个地方会通过emitChanged发出变化的信号:
void QPlatformClipboard::emitChanged(QClipboard::Mode mode)
{if (!QGuiApplicationPrivate::is_app_closing) // QTBUG-39317, prevent emission when closing down.QGuiApplication::clipboard()->emitChanged(mode);
}
可以再往下看下谁会调用emitChanged ,可以发现是QPlatformClipboard 的子类QXcbClipboard :
// qtbase/src/plugins/platforms/xcb/qxcbclipboard.cpp
void QXcbClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode)
{if (mode > QClipboard::Selection)return;QXcbClipboardMime *xClipboard = 0;// verify if there is data to be cleared on global X Clipboard.if (!data) {xClipboard = qobject_cast<QXcbClipboardMime *>(mimeData(mode));if (xClipboard) {if (xClipboard->isEmpty())return;}}if (!xClipboard && (m_clientClipboard[mode] == data))return;xcb_atom_t modeAtom = atomForMode(mode);xcb_window_t newOwner = XCB_NONE;if (m_clientClipboard[mode]) {if (m_clientClipboard[QClipboard::Clipboard] != m_clientClipboard[QClipboard::Selection])delete m_clientClipboard[mode];m_clientClipboard[mode] = 0;m_timestamp[mode] = XCB_CURRENT_TIME;}if (connection()->time() == XCB_CURRENT_TIME)connection()->setTime(connection()->getTimestamp());if (data) {newOwner = owner();m_clientClipboard[mode] = data;m_timestamp[mode] = connection()->time();}xcb_set_selection_owner(xcb_connection(), newOwner, modeAtom, connection()->time());if (getSelectionOwner(modeAtom) != newOwner) {qWarning("QXcbClipboard::setMimeData: Cannot set X11 selection owner");}emitChanged(mode);
}void QXcbClipboard::handleXFixesSelectionRequest(xcb_xfixes_selection_notify_event_t *event)
{QClipboard::Mode mode = modeForAtom(event->selection);if (mode > QClipboard::Selection)return;// Note1: Here we care only about the xfixes events that come from other processes.// Note2: If the QClipboard::clear() is issued, event->owner is XCB_NONE,// so we check selection_timestamp to not handle our own QClipboard::clear().if (event->owner != owner() && event->selection_timestamp > m_timestamp[mode]) {if (!m_xClipboard[mode]) {m_xClipboard[mode].reset(new QXcbClipboardMime(mode, this));} else {m_xClipboard[mode]->reset();}emitChanged(mode);} else if (event->subtype == XCB_XFIXES_SELECTION_EVENT_SELECTION_CLIENT_CLOSE ||event->subtype == XCB_XFIXES_SELECTION_EVENT_SELECTION_WINDOW_DESTROY)emitChanged(mode);
}
至此,我们可以知道QClipboard是如何发出剪贴板内容变化的信号了:
- QClipboard设置剪贴板内容(setMimeData),QXcbClipboard设置完剪贴板内容,emitChanged通知内容变化
- QXcbClipboard收到X11剪贴板变化的事件,主动emitChanged通知QClipboard剪贴板变化
总结
qt的剪贴板底层是由各个平台的剪贴板接口驱动的,如果是X11平台,那么整个剪贴板就是X11接口驱动的。关于如何使用X11原生剪贴板接口,参考:https://stackoverflow.com/questions/27378318/c-get-string-from-clipboard-on-linux
相关文章:
复制粘贴——QT实现原理
复制粘贴——QT实现原理 QT 剪贴板相关类 QClipboard 对外通用的剪贴板类,一般通过QGuiApplication::clipboard() 来获取对应的剪贴板实例。 // qtbase/src/gui/kernel/qclipboard.h class Q_GUI_EXPORT QClipboard : public QObject {Q_OBJECT private:explici…...
(一)五种最新算法(SWO、COA、LSO、GRO、LO)求解无人机路径规划MATLAB
一、五种算法(SWO、COA、LSO、GRO、LO)简介 1、蜘蛛蜂优化算法SWO 蜘蛛蜂优化算法(Spider wasp optimizer,SWO)由Mohamed Abdel-Basset等人于2023年提出,该算法模型雌性蜘蛛蜂的狩猎、筑巢和交配行为&…...
LED透镜粘接UV胶是一种特殊的UV固化胶,用于固定和粘合LED透镜。
LED透镜粘接UV胶是一种特殊的UV固化胶,用于固定和粘合LED透镜。 它具有以下特点: 1. 高透明度:LED透镜粘接UV胶具有高透明度,可以确保光线的透过性,不影响LED的亮度和效果。 2. 快速固化:经过UV紫外线照射…...
C语言 题目
1.写一个函数算一个数的二进制(补码)表示中有几个1 #include<stdio.h>//统计二进制数中有几个1 //如13:1101 //需要考虑负数情况 如-1 结果应该是32// n 1101 //n-1 1100 //n 1100 //n-1 1011 //n 1000 //n-1 0111 //n 0000 //看n的变化 int funca(int c){int co…...
CDN 内容分发网络
CDN常见问题 什么是 CDN ? CDN 全称是 Content Delivery Network/Content Distribution Network,翻译过的意思是 内容分发网络 。 我们可以将内容分发网络拆开来看: 内容:指的是静态资源比如图片、视频、文档、JS、CSS、HTML。…...
Android : Xui- RecyclerView+BannerLayout 轮播图简单应用
实例图: 1.引用XUI http://t.csdnimg.cn/Wb4KR 2.创建显示图片布局 banner_item.xml <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"…...
Java网络通信-第21章
Java网络通信-第21章 1.网络程序设计基础 网络程序设计基础涵盖了许多方面,包括网络协议、Web开发、数据库连接、安全性等。 1.1局域网与互联网 局域网(LAN)与互联网(Internet)是两个不同的概念,它们分…...
Leetcode 345. Reverse Vowels of a String
Problem Given a string s, reverse only all the vowels in the string and return it. The vowels are ‘a’, ‘e’, ‘i’, ‘o’, and ‘u’, and they can appear in both lower and upper cases, more than once. Algorithm Collect all the vowels and reverse the…...
[linux] 用命令行wget下载google drive的大文件
使用wget命令下载Google drive上的文件_ubuntu上wget下载谷歌云盘文件-CSDN博客 如何用命令行下载Google Drive上的共享文件?-腾讯云开发者社区-腾讯云 举例:https://drive.google.com/drive/folders/1vKj3VvJEKgS_o-uOSmz3I0-GomECpql3 1、在网页上&…...
Docker Network(网络)——8
目录: Docker 为什么需要网络管理Docker 网络架构简介 CNMLibnetwork驱动常见网络类型 bridge 网络host 网络container 网络none 网络overlay 网络docker 网络管理命令 docker network createdocker network inspectdocker network connectdocker network disconne…...
网页设计--第6次课后作业
试用Vue相关指令完成对以下json数据的显示。显示效果如下: 其中:gender1 显示为女,gender2显示为男。价格超过30元,显示“有点小贵”。价格少于等于30元,则显示“价格亲民”。 data: {books: [{"id": "…...
R语言学习
Part1阶段1:入门基础 1安装R和RStudio: 下载并安装R:https://cran.r-project.org/ 下载并安装RStudio:https://www.rstudio.com/products/rstudio/download/ 2Hello World: 学习如何在R中输出"Hello, World!"…...
基于Unity3D 低多边形地形模型纹理贴图
在线工具推荐: 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 当谈到游戏角色的3D模型风格时,有几种不同的风格…...
vue预览pdf,放大缩小拖动,dialog拖动,父页面滚动
公共组件部分代码 main.js import draggable from /directive/drag/index Vue.use(draggable) pdf组件部分代码...
泽攸科技二维材料转移台的应用场景及优势
随着二维材料的广泛研究和各种潜在应用的开发,对于二维材料样品的精密操控与转移的需求日益增加。特别是一些新型二维材料的制备和器件集成制备中,需要在显微镜下对样品进行观察与定位,并能够在微米甚至纳米量级上精确移動和转移样品。 传统…...
JavaScript——基本使用HelloWrold
1. 内部标签 html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><!--script标签内:写js代码 也可以写在body标签内--><script>alert(hello,world)&l…...
关于DNS服务器地址总是127.0.0.1且无法解析域名地址
问题 笔者尝试nslookup解释域名时,出现服务器变成本地环回口地址,导致无法解析域名 C:\Users\Zsy>nslookup www.baidu.com 服务器: UnKnown Address: 127.0.0.1*** UnKnown 找不到 www.baidu.com: Server failed排查思路 尝试关闭虚拟网卡&#…...
制作一个RISC-V的操作系统四-嵌入式开发介绍
文章目录 什么是嵌入式开发交叉编译查看一些GCC文件夹 调试器GDB相关语法命令 模拟器QEMUQEMU的安装和使用项目构造工具MakeMakeFile的构成make的运行 练习4-1练习4-2练习4-3 什么是嵌入式开发 程序跑到开发板上,或者说运行到硬件上 交叉编译 简单理解交叉编译来说…...
Python爬虫-实现批量抓取王者荣耀皮肤图片并保存到本地
前言 本文是该专栏的第12篇,后面会持续分享python爬虫案例干货,记得关注。 本文以王者荣耀的英雄皮肤为例,用python实现批量抓取“全部英雄”的皮肤图片,并将图片“批量保存”到本地。具体实现思路和详细逻辑,笔者将在正文结合完整代码进行详细介绍。注意,这里抓取的图片…...
04-详解Eureka注册中心的作用,具体配置,服务注册和服务发现
Eureka注册中心的作用 Eureka架构 远程调用的两个问题 服务的ip地址和端口号写死: 生产环境中服务的地址可能会随时发生变化,如果写死每次都需要重新修改代码多实例问题: 在高并发的情况下一个服务可以有多个实例形成一个集群,此时如果采用硬编码的方式只能访问服务的一个实…...
手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...
el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
LOOI机器人的技术实现解析:从手势识别到边缘检测
LOOI机器人作为一款创新的AI硬件产品,通过将智能手机转变为具有情感交互能力的桌面机器人,展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家,我将全面解析LOOI的技术实现架构,特别是其手势识别、物体识别和环境…...
