[Experience sharing] 我个人在这里记录一些使用deepin的小技巧(可忽略)[不定期更新]
Tofloor
poster avatar
穿西装的万斯在统亻言
deepin
Backbone of ecological co-construction group
2025-01-16 22:16
Author

1.直接复制文件,然后粘贴到文本框,可以把文件的完整路径粘贴出来。

文件管理器ctrl+L直接显示当前目录路径。

2.高频使用的软件/命令可以在控制中心-键盘和语言-快捷键添加快捷键,来快速打开,不用每次都手动点开,提高效率

image.png

3.在edge浏览器中输入网址之后按alt+enter会在新标签打开网址,直接按enter就会在当前标签页打开(覆盖原网址),按ctrl+enter则是新窗口打开

4.按alt+F8会自动把鼠标移动到窗口右下角并且是按压状态来调整窗口大小,而不用慢慢挪动鼠标到边缘对准这么麻烦,对于高分屏用户是非常方便

5.明明设置了ctrl+shift为什么还是经常切换输入法失灵?

ctrl先按ctrl和后按ctrl的顺序是有区别的

所以设置如下四个快捷键即可
image.png

  1. deepin系统里文件夹图标有个锁是什么意思?

在Deepin系统中,文件夹图标上的锁意味着您没有足够的权限来修改该文件夹或文件。您可以使用命令 sudo chmod -R 777 文件/文件夹路径 来解锁文件夹或文件

综上chmod +x 是将文件状态改为可执行,而chmod 777 是改变文件读写权限。

7.deb包可以把后缀改为.zip解压出来二进制可执行程序,大部分解压出来双击可执行程序即可运行

8.linux如何在命令行更新系统的时候不更新某个软件包?

您可以使用 apt-mark hold 命令来锁定某个软件包,这样在更新系统时就不会更新该软件包。例如,如果您想锁定名为 package_name 的软件包,可以使用以下命令:

sudo apt-mark hold package_name

在锁定软件包后,您可以像往常一样使用 sudo apt updatesudo apt upgrade 命令来更新系统,但被锁定的软件包将不会被更新。

如果您想取消锁定软件包并允许它再次更新,可以使用 apt-mark unhold 命令。例如,如果您想取消锁定名为 package_name 的软件包,可以使用以下命令:

sudo apt-mark unhold package_name

9.systemctl是什么?

是一个控制服务管理的命令行工具,你可以启动/停止/重启/查看服务等功能。(一般服务名称以.service结尾,e.g. ,NetworkManager-wait-online.service)

10.deepin官方内核地址:https://community-packages.deepin.com/deepin/beige/pool/main/l/linux-upstream/

11.如何使用grep查找文件中的字符串

#-r表示查找当前以及子目录 -nH表示列出所在行号,*号表示当前以前所有的目录都递归遍历
grep -nH -r "DPF_NAMESPACE::backtrace::installStackTraceHandler()" *.cpp *.h  *

12.按alt+~快捷键可以快速仅在当前程序切换窗口,例如文件管理器中打开的多个窗口:

image.png

13.删除文件管理器“磁盘”中的百度网盘快捷方式

删除 /usr/share/dde-file-manager/extensions/appEntry目录下的 .desktop 文件。

同样地,你可以可以复制对应的.desktop文件进去增加程序入口。

14.除了delete键可以删除,ctrl+d也可以删除到回收站

15.超快捷的随时随地的翻译方式

文字翻译:拖动要翻译的内容,按win+空格键,点击翻译。操作只需要8秒钟搞定。

录屏_选择区域_20250223125122.gif

图片翻译:截图-识别文字-拖选-win+空格键-翻译即可。

16.有时候莫名其妙启动器里面的软件打不开

有时候莫名其妙启动器里面的软件打不开,有可能是desktop 的文件名称中有空格,把空格改为_下划线即可。

17.按ctrl+H快捷键可以隐藏/显示 隐藏文件。‘

18.bilibili想用小窗观看但是又想看弹幕

可以设置为网页模式,然后把浏览器标签单独拎出来,按下alt+空格键选择 -总是最前 ,就可以不被遮挡了!

Reply Favorite View the author
All Replies
穿西装的万斯在统亻言
deepin
Backbone of ecological co-construction group
2025-01-16 22:18
#1
Reply View the author
jiandan0520
deepin
2025-01-27 15:06
#2

你好,我也是文件带锁,用了你的第六条建议,回复是某某文件的权限:只读文件系统,然后还是带锁的,并没有解决,求助下

Reply View the author
穿西装的万斯在统亻言
deepin
Backbone of ecological co-construction group
2025-01-27 22:20
#3
jiandan0520

你好,我也是文件带锁,用了你的第六条建议,回复是某某文件的权限:只读文件系统,然后还是带锁的,并没有解决,求助下

你的应该是deepin v25吧?你的是弄的系统文件吗?

Reply View the author
jiandan0520
deepin
2025-02-04 15:36
#4

本来23突然有一天带锁了,然后重装了25也是带锁,只有一个盘正常,其他几个盘都打不开

Reply View the author
穿西装的万斯在统亻言
deepin
Backbone of ecological co-construction group
2025-02-19 11:52
#5

记录一下FFmpegKit 的使用:

网址:https://github.com/arthenica/ffmpeg-kit

FFmpegKit for Linux

1. 特性

  • 提供基于 c++11C++ API
  • 包含 x86_64 架构
  • 构建共享原生库(.so)
  • 未发布预构建二进制文件

2. 构建

在项目根目录运行 linux.sh 脚本以构建 ffmpeg-kitffmpeg 共享库。

请注意,FFmpegKit 项目仓库仅包含 FFmpegKit 的源代码。linux.sh 需要网络连接和对 github.com 的互联网访问权限,以便下载 FFmpeg 和启用的外部库的源代码。

2.1 先决条件

linux.sh 需要以下软件包。

2.1.1 软件包

使用你的包管理器(apt、yum、dnf 等)安装以下软件包。

请注意,Linux 软件包的名称因发行版而异。下面给出的名称适用于 Debian/Ubuntu。如果你使用的是其他发行版,某些软件包的名称可能会不同。

  • 以下软件包是构建脚本所必需的。
    clang llvm lld libclang-14-dev libstdc++6 nasm autoconf automake libtool pkg-config curl git doxygen rapidjson-dev
  • 以下可选软件包仅在你需要构建相应的外部库时才需要安装。
    cmake libasound2-dev libass-dev libfontconfig1-dev libfreetype-dev libfribidi-dev libgmp-dev libgnutls28-dev libmp3lame-dev libopencore-amrnb-dev libopencore-amrwb-dev libopus-dev librubberband-dev libsdl2-dev libshine-dev libsnappy-dev libsoxr-dev libspeex-dev libtesseract-dev libtheora-dev libtwolame-dev libva-dev libvidstab-dev libvorbis-dev libvo-amrwbenc-dev libvpx-dev libv4l-dev libwebp-dev libxml2-dev libxvidcore-dev libx265-dev meson ocl-icd-opencl-dev opencl-headers tcl zlib1g-dev groff gtk-doc-tools libtasn1

2.2 选项

使用 --enable- 标志来支持额外的外部或系统库。

./linux.sh --enable-fontconfig运行 --help 查看所有可用的构建选项。

2.3 构建输出

linux.sh 创建的所有库都可以在 prebuilt 目录下找到。

  • Main 构建创建的头文件和库位于 bundle-linux 文件夹下。

3. 使用

3.1 C++ API

FFmpegKit 不发布任何预构建的 Linux 库,因此你需要手动构建并将 FFmpegKit 库导入到你的项目中。

然后,你可以使用以下 API 方法在你的应用程序中执行 FFmpegFFprobe 命令。

  1. 执行同步 FFmpeg 命令。
    c++ 复制

    #include 
    #include 
    
    using namespace ffmpegkit;
    
    auto session = FFmpegKit::execute("-i file1.mp4 -c:v mpeg4 file2.mp4");
    if (ReturnCode::isSuccess(session->getReturnCode())) {
    
        // 成功
    
    } else if (ReturnCode::isCancel(session->getReturnCode())) {
    
        // 取消
    
    } else {
    
        // 失败
        std::cout << "命令执行失败,状态为 " << FFmpegKitConfig::sessionStateToString(session->getState()) << ",返回码为 " << session->getReturnCode() << "." << session->getFailStackTrace() << std::endl;
    
    }
    
  2. 每次 execute 调用(同步或异步)都会创建一个新的会话。可以从创建的会话中访问有关执行的每个细节。
    c++ 复制

    #include 
    #include 
    
    using namespace ffmpegkit;
    
    auto session = FFmpegKit::execute("-i file1.mp4 -c:v mpeg4 file2.mp4");
    
    // 为此次执行创建的唯一会话 ID
    long sessionId = session->getSessionId();
    
    // 作为单个字符串的命令参数
    auto command = session->getCommand();
    
    // 命令参数
    auto arguments = session->getArguments();
    
    // 执行状态。显示执行是否仍在进行中或已完成
    SessionState state = session->getState();
    
    // 已完成会话的返回码。如果会话仍在进行中或以失败结束,则为 null
    auto returnCode = session->getReturnCode();
    
    auto startTime = session->getStartTime();
    auto endTime = session->getEndTime();
    long duration = session->getDuration();
    
    // 此次执行生成的控制台输出
    auto output = session->getOutput();
    
    // 如果 FFmpegKit 无法运行命令,则为堆栈跟踪
    auto failStackTrace = session->getFailStackTrace();
    
    // 为此执行生成的日志列表
    auto logs = session->getLogs();
    
    // 为此执行生成的统计信息列表
    auto statistics = session->getStatistics();
    
  3. 通过提供会话特定的 execute/log/session 回调来执行异步 FFmpeg 命令。
    c++ 复制

    #include 
    #include 
    
    using namespace ffmpegkit;
    
    FFmpegKit::executeAsync("-i file1.mp4 -c:v mpeg4 file2.mp4", [](auto session) {
        const auto state = session->getState();
        auto returnCode = session->getReturnCode();
    
        // 当会话执行时调用
    
        std::cout << "FFmpeg 进程以状态 " << FFmpegKitConfig::sessionStateToString(state) << " 和返回码 " << returnCode << " 退出。" << session->getFailStackTrace() << std::endl;
    }, [](auto log) {
    
        // 当会话打印日志时调用
    
    }, [](auto statistics) {
    
        // 当会话生成统计信息时调用
    
    });
    
  4. 执行 FFprobe 命令。

    • 同步

    c++ 复制

    #include 
    #include 
    
    using namespace ffmpegkit;
    
    auto session = FFprobeKit::execute(ffprobeCommand);
    
    if (!ReturnCode::isSuccess(session->getReturnCode())) {
        std::cout << "命令执行失败。请检查输出以获取详细信息。" << std::endl;
    }
    
    • 异步

    c++ 复制

    #include 
    #include 
    
    using namespace ffmpegkit;
    
    FFprobeKit::executeAsync(ffprobeCommand, [](auto session) {
    
        // 当会话执行时调用
    
    });
    
  5. 获取文件的媒体信息。
    c++ 复制

    #include 
    
    using namespace ffmpegkit;
    
    auto mediaInformation = FFprobeKit::getMediaInformation("");
    mediaInformation->getMediaInformation();
    
  6. 停止正在进行的 FFmpeg 操作。

    • 停止所有执行
      c++ 复制
      FFmpegKit::cancel();
      
    • 停止特定会话
      c++ 复制
      FFmpegKit::cancel(sessionId);
      
  7. 从会话历史中获取之前的 FFmpegFFprobe 会话。
    c++ 复制

    #include 
    
    using namespace ffmpegkit;
    
    auto sessions = FFmpegKitConfig::getSessions();
    int i = 0;
    std::for_each(sessions->begin(), sessions->end(), [](const auto session) {
        std::cout << "会话 " << i++ << " = id:" << session->getSessionId() << ", 开始时间:" << session->getStartTime() << ", 持续时间:" << session-> getDuration() << ", 状态:" << FFmpegKitConfig::sessionStateToString(session->getState()) << ", 返回码:" << session->getReturnCode() << "." << std::endl;
    });
    
  8. 启用全局回调。

    • 会话类型特定的完成回调,当异步会话完成时调用
      c++ 复制
      #include 
      
      using namespace ffmpegkit;
      
      FFmpegKitConfig::enableFFmpegSessionCompleteCallback([](auto session) {
      
      });
      
      FFmpegKitConfig::enableFFprobeSessionCompleteCallback([](auto session) {
      
      });
      
      FFmpegKitConfig::enableMediaInformationSessionCompleteCallback([](auto session) {
      
      });
      
    • 日志回调,当会话生成日志时调用
      c++ 复制
      #include 
      
      using namespace ffmpegkit;
      
      FFmpegKitConfig::enableLogCallback([](auto log) {
          ...
      });
      
    • 统计信息回调,当会话生成统计信息时调用
      c++ 复制
      #include 
      
      using namespace ffmpegkit;
      
      FFmpegKitConfig::enableStatisticsCallback([](auto statistics) {
          ...
      });
      
  9. 注册系统字体和自定义字体目录。
    c++ 复制

    #include 
    
    using namespace ffmpegkit;
    
    FFmpegKitConfig::setFontDirectoryList(std::list{"/usr/share/fonts"}, std::map());
    

4. 测试应用程序

你可以通过运行 FFmpegKit Test 项目下开发的 Linux 测试应用程序,查看 FFmpegKit 在应用程序中的使用方式。

Reply View the author
穿西装的万斯在统亻言
deepin
Backbone of ecological co-construction group
2025-03-13 23:32
#6

记录一下关于Deepin系统插件开发的帖子:
屏幕时间,右下角日期时间修改:https://bbs.deepin.org/post/284610

https://bbs.deepin.org/post/177748

https://github.com/linuxdeepin/dde-dock/blob/master/plugins/plugin-guide/plugins-developer-guide.md

image.png

https://bbs.deepin.org/post/271217

https://bbs.deepin.org/zh/post/195858

顶栏:https://bbs.deepin.org/zh/post/195128

网速插件:https://bbs.deepin.org/zh/post/179425

海天鹰Dock插件:https://bbs.deepin.org/post/156934

(https://bbs.deepin.org/post/269641)

歌词插件:https://bbs.deepin.org/zh/post/259131

https://bbs.deepin.org/post/262656

时间有点久远了:https://bbs.deepin.org/post/195623

仿制启动器:https://bbs.deepin.org/zh/post/261738

Reply View the author
穿西装的万斯在统亻言
deepin
Backbone of ecological co-construction group
2025-03-24 09:51
#7

记录一下关于Docker使用上的一些疑问:

引用内容:

本地时区和docker容器的时区都设置为'GMT+8:00‘。但是'docker logs -t‘仍然显示'GMT+0:00’的时间戳。

下图是'docker logs -t‘输出的一部分。左边的时间戳由docker打印,右边的时间戳由容器中的应用程序打印。

原文链接:

https://cloud.tencent.com/developer/ask/sof/1247326

经过一些研究,我发现 docker logs -t命令会打印出UTC格式的时间戳,并且没有配置来更改它。但是,您可以使用https://github.com/docker/cli/issues/604中引用的一个小脚本,其中只需通过管道传输输出并更改给定的时间戳。

https://stackoverflow.com/questions/55466370/how-to-set-timezone-of-docker-logs-t


UTC时间与本地时间

  • UTC时间是一种全球统一的时间标准,Docker容器默认使用UTC时间记录日志。
Reply View the author
穿西装的万斯在统亻言
deepin
Backbone of ecological co-construction group
2025-03-28 13:48
#8

比较火的四大中文论坛

v2ex

技术型老站,用户质量在4个论坛里面是最高的,巨佬最最多,是国内最大的技术型论坛
v2ex是反对一切的钻漏洞、破解、违反版权的行为,非常洁癖
很多开发者都在v2ex,虽然有一些不喜欢v2的声音,但其江湖地位几乎无法撼动

linuxdo

站长技术比较好,早些时候在v2ex推广,chatgpt的逆向做的很厉害,随着gpt的爆火,聚集了一群拥趸
因为破解逆向和v2ex不合,因此似乎与v2站长不合 ⇦ 如果我没记错
网站里有不少利用料卡c各种资源的帖子,比如GitHub\copilot\chatgpt
因为chatgpt是大众产品,因此注册用户不少,也有很多v2用户因为不满livid的管理选择搬迁到Linux.do
v2ex的门槛提升,也导致新用户更倾向于选择Linux.do

hostloc和nodeseek

我原先在loc,最近才来ns。从活跃度上看,这里的确远胜loc,朝气蓬勃。网站排名目前低于loc也是正常的,loc鼎盛时期比目前的ns还算要强的,有着十几年的积累;那个时候玩机器的硬核大佬很多,比如目前很多dd脚本都是在以前萌咖的脚本上改进扩展而来。
主机圈是一个相对独立的圈子,和综合的圈子不一样。把ns/loc和v2/linux比不怎么合理。

Reply View the author
穿西装的万斯在统亻言
deepin
Backbone of ecological co-construction group
2025-04-13 02:38
#9

编译打包V23适配的工作流代码yml:

name: Build and Release

on:
  push:
    tags:
      - 'v*' 
    branches:
      - '**'
   
  
jobs:
  build-and-release:
    runs-on: ubuntu-latest
  
    permissions:
      contents: write  # 需要写入Release的权限

    steps:
    - name: Checkout code
      uses: actions/checkout@v4
      with:
        fetch-depth: 0  # 获取完整提交历史用于版本检测
        repository: c61292558/WingHexExplorer2
        token: ${{ secrets.GITHUB_TOKEN }}  # 显式传递自动生成的令牌
        Workspace-tags: true

   
  
    - name: Generate version info
      id: version
      run: |
        # 尝试获取最近的tag,如果没有则生成基于commit的版本号
        if git describe --tags --abbrev=0 2>/dev/null; then
          VERSION=$(git describe --tags --abbrev=0)
        else
          VERSION="v0.0.0-$(git rev-parse --short HEAD)"
        fi
        echo "version=${VERSION}" >> $GITHUB_OUTPUT
        echo "Using version: ${VERSION}"
    
  
  
    - name: Checkout code submodules
      uses: actions/checkout@v4
      with:
        submodules: 'recursive'

    - name: List files
      run: ls -la
  
    - name: Setup Docker
      run: |
        sudo systemctl start docker
        sudo docker info

    - name: Build Docker container
      run: |
        sudo docker run -dit \
          --name qtbuilder \
          -v ${{ github.workspace }}:/workspace \
          linuxdeepin/deepin:23

      
  

    - name: Check CMakeLists.txt in container
      run: 
        sudo docker exec qtbuilder ls -la /workspace/CMakeLists.txt
  
    - name: Install dependencies
      run: |
        sudo docker exec qtbuilder bash -c "
        apt update -y && \
        apt install -y \
          xz-utils \
          cmake \
          build-essential \
          tree \
          git \
          ninja-build \
          wget \
          flex \
          bison \
          zlib1g-dev \
          libgmp-dev \
          libmpfr-dev \
          libmpc-dev \
          libgl1-mesa-dev \
          libx11-dev \
          libxcb1-dev \
          libxext-dev \
          libxfixes-dev \
          libxi-dev \
          libxrender-dev \
          libxkbcommon-dev \
          libwayland-dev \
          qt6-base-dev \
          qt6-base-private-dev \
          qt6-base-dev-tools \
          qt6-tools-dev \
          qt6-tools-dev-tools \
          qt6-svg-dev \
          && apt clean"
    
    - name: Check compiler version
      run: |
        sudo docker exec qtbuilder bash -c "g++ --version"
        sudo docker exec qtbuilder bash -c "gcc --version"

    - name: Compile project
      run: |
        sudo docker exec qtbuilder bash -c "cd /workspace && \
        mkdir -p build && \
        cd build && \
        cmake   .. && \   
        make "# 编译
        # 生成 Makefile  del -DCMAKE_CXX_STANDARD=20  cmake --debug-output  , make  VERBOSE=1

    # - name: List files2
    #   if: failure()  # 仅在失败时运行
    #   run:  cat ${{github.workspace}}/build/_build/qmsetup_build-Release.log 
    #   # cat ${{ github.workspace }}/build/CMakeFiles/CMakeOutput.log && ls -l ${{ github.workspace }} && cd ${{ github.workspace }}/build/CMakeFiles && ls -l 
  
    # - name: Upload build logs
    #   if: failure()  # 仅在失败时运行
    #   uses: actions/upload-artifact@v4
    #   with:
    #     name: qmsetup-build-log
    #     path: |
    #       ./qmsetup_build.log
    #     if-no-files-found: warn  # 如果文件不存在仅警告

    # - name: Print qmsetup build log on failure
    #   if: failure()
    #   run: cat /build/_build/qmsetup_build-Release.log
  
    - name: Debug Git Info # 在 Get version info 步骤之前添加
      run: |
        echo "--- Git Status ---"
        git status
        echo "--- Recent Commits ---"
        git log -n 5 --decorate --oneline
        echo "--- Available Tags ---"
        git tag -l
        echo "--- Trying git describe directly ---"
        git describe --tags --abbrev=0 || echo "Git describe failed here too!"

    
    # - name: Get version info
    #   id: version
    #   run: |
    #     # 提取最新的tag作为版本号
    #     VERSION=$(git describe --tags ---abbrev=0 2>/dev/null || echo "v0.0.0")
    #     echo "version=${VERSION}" >> $GITHUB_OUTPUT


    - name: chmod +x /opt/winghexexplorer2/run_winghexexplorer2
      run: |
        sudo chmod +x debian/opt/winghexexplorer2/run_winghexexplorer2
        sudo ls -l debian/opt/winghexexplorer2/run_winghexexplorer2
    
    
    - name: Compress build artifacts
      run: |
        zip -r build_artifacts.zip build

    - name: List files commp 
      run: ls -la && echo "-----------------这是编译完之后---------------------------"

    - name: Copy build artifacts to debian package directory
      run: |
        cp -r build/* debian/opt/winghexexplorer2/
  
    - name: Build DEB package
      run: |
        dpkg-deb -Zxz --build  debian "com.wingsummer.winghexexplorer_${{ steps.version.outputs.version }}_amd64.deb"

  
  
    - name: List files deb 
      run: ls -la && echo "-----------------这是打包完之后---------------------------"

    - name: Show debian directory structure
      run: |
        echo "Tree structure of debian directory:"
        tree debian

    - name: Create Release
      id: create_release
      uses: softprops/action-gh-release@v1
      with:
        token: ${{ secrets.GITHUB_TOKEN }}   # 添加此行
        tag_name: ${{ steps.version.outputs.version }}
        overwrite: true  # 关键!允许覆盖已有的 Release
        name: "Release ${{ steps.version.outputs.version }}"
        draft: false
        prerelease: false
        files: |
          build_artifacts.zip
          *.deb
          build/*.app    # 应用程序文件
          build/*.so     # 动态库文件
          build/*.dmg    # macOS安装包
          build/*.exe    # Windows可执行文件

Reply View the author
穿西装的万斯在统亻言
deepin
Backbone of ecological co-construction group
2025-05-04 11:11
#10

笔记:

关于DBus

系统总线(System Bus): 系统总线是一个持久的总线,在系统启动时就创建,供系统内核和后台进程使用,具有较高的安全性。只有Linux内核、Linux桌面环境和权限较高的程序才能向该总线写入消息,以此保障系统安全性,防止有恶意进程假冒Linux发送消息。系统总线最常用是发送系统消息,比如:插入一个新的存储设备、有新的网络连接等。

会话总线(Session Bus):会话总线是在某个用户登录后启动,属于某个用户私有,是某用户的应用程序用来通话的通道。在很多嵌入式系统中,只有一个用户ID登录运行,因此只有一个会话总线。

echo $DBUS_SESSION_BUS_ADDRESS
unix:path=/run/user/1000/bus

接口(Interface)

image.png
d-ffet工具下某个DBus对象的接口示意图

  每个对象都有一个或者多个接口,一个接口就是多个方法和信号的集合。dbus使用简单的命名空间字符串来表示接口,如图2中所示的一个对象路径下多个接口,包括org.freedesktop.DBus.Properties,org.freedesktop.DBus.Peer等。可以说dbus接口相当于C++中的纯虚类。

D-Bus 对象(包括其路径、接口和成员/功能)是由应用程序开发者在编写代码时定义和实现的。

正是如此。如果您在应用程序代码中没有定义和在 D-Bus 总线上注册一个对象,那么像 d-feet 这样的 D-Bus introspector 工具就无法发现并显示它。

3.7 方法(Method)和信号(Signal)

  每个对象都有一些成员,两种成员:方法(methods)和信号(signals),在对象中,方法可以被调用。信号会被广播,被定义为感兴趣的对象可以处理这个信号,同时信号中也可以带有相关的数据(payload)。


举例:

import dbus
import json


#连接到系统总线
bus=dbus.SystemBus()

upower=bus.get_object('org.freedesktop.UPower','/org/freedesktop/UPower')

display_device_path=upower.GetDisplayDevice(dbus_interface='org.freedesktop.UPower')
print("Display Device Path:", display_device_path)  # 输出如: /org/freedesktop/UPower/devices/DisplayDevice

# 进一步获取设备属性
device = bus.get_object('org.freedesktop.UPower', display_device_path)
props = device.GetAll('org.freedesktop.UPower.Device', dbus_interface='org.freedesktop.DBus.Properties')
# print(json.dumps(props,indent=4))

for key,value in props.items():
    print(f'{key}:{value}')

print("Battery Percentage:", props['Percentage'])  # 当前电量百分比
print("State:", props['State'])  # 充电(1)/放电(2)/充满(4)等状态码

输出结果:

Display Device Path: /org/freedesktop/UPower/devices/DisplayDevice
NativePath:
Vendor:
Model:
Serial:
UpdateTime:1746266888
Type:2
PowerSupply:1
HasHistory:0
HasStatistics:0
Online:0
Energy:31.1
EnergyEmpty:0.0
EnergyFull:31.11
EnergyFullDesign:0.0
EnergyRate:0.0
Voltage:0.0
ChargeCycles:0
Luminosity:0.0
TimeToEmpty:0
TimeToFull:0
Percentage:100.0
Temperature:0.0
IsPresent:1
State:4
IsRechargeable:0
Capacity:0.0
Technology:0
WarningLevel:1
BatteryLevel:1
IconName:battery-full-charged-symbolic
Battery Percentage: 100.0
State: 4

为什么需要中间路径?

  1. 统一接口:所有设备(包括显示设备)都通过同样的方式访问属性,比如电池 /devices/battery_BAT0 和显示器设备 /devices/DisplayDevice 都走“书架编号→书”的流程
  2. 动态更新:显示设备是虚拟的(比如综合多个电池的状态),直接返回属性的话,数据更新时会更复杂,而通过路径可以随时获取最新状态
  3. 节省资源:不是所有人都需要所有属性,分开获取能减少不必要的计算(比如你只想看电量,不需要电压温度)就像你要喝牛奶
  • 直接给你牛奶(属性)→ 方便,但下次想喝果汁得重新找。
  • 告诉你冰箱位置(路径)→ 以后牛奶、果汁都能自己拿,更灵活。

1. UPower管理的不只是电池

UPower的设计目标是统一管理所有与电源相关的设备,而不仅仅是电池。

UPower也要管理多种设备:

  • 电池(Battery)
  • 交流电源(AC)
  • UPS不间断电源
  • 外设(如无线鼠标、键盘的电池)
  • 虚拟显示设备(DisplayDevice)

2. 显示设备为什么属于电源管理?

这里的“显示设备”不是屏幕硬件,而是一个虚拟的聚合设备,专门用来给桌面环境(如GNOME/KDE)显示电源状态图标。它的作用相当于一个“电源信息总台”:

  • 功能:综合多个实际设备(如电池、UPS)的状态,生成统一的电量百分比、剩余时间等数据
  • 例子:如果电脑有2块电池,DisplayDevice会自动整合它们的电量,显示一个总百分比(比如电池1剩50%,电池2剩30%,显示设备可能显示总可用时间)。

3. 为什么要细分设备类型?

就像医院要分科室(内科、外科),UPower细分设备类型是为了精准管理不同电源特性

  • 电池需要监控充放电曲线
  • 交流电源只需判断是否插电
  • 鼠标电池可能只需低电量警告 如果所有设备都用同一个接口,会导致数据混乱(比如交流电显示“剩余时间”毫无意义)

4. 显示设备的实际意义

想象你正在用笔记本电脑:

  • 普通用户:只需要看右上角的电池图标(由DisplayDevice提供)
  • 开发者:如果需要详细数据(比如某块电池的电压),才去查具体设备路径(如 battery_BAT0

这种分层设计让系统更高效——桌面环境只需监听DisplayDevice的变化,而不用同时监控多个电池、UPS的复杂状态

总结

UPower像是一个电源管家,通过细分设备类型:

  • 为普通用户提供简洁的显示(通过DisplayDevice)
  • 为开发者提供详细控制(通过具体设备路径)
  • 为系统节省资源(按需获取数据)
Reply View the author
穿西装的万斯在统亻言
deepin
Backbone of ecological co-construction group
2025-06-12 16:19
#11

关于使用KVM

sudo apt install virt-manager
Reply View the author
穿西装的万斯在统亻言
deepin
Backbone of ecological co-construction group
2025-07-28 14:15
#12
Reply View the author