- 应用安全
- 桌面应用
- 开发工具
【免费下载链接】cutter
Free and Open Source Reverse Engineering Platform powered by rizin
View(视图)菜单是 Cutter 逆向工程平台中负责界面组织与状态管理的核心菜单,它串联了内容刷新、布局保存/加载/重置、面板锁定、标签位置切换以及图形/反汇编/十六进制视图的缩放控制等能力。本文基于官方文档 view-menu.rst 并结合仓库源码(MainWindow.cpp、CutterLayout.h 等)逐项剖析每个菜单项的行为与底层实现,帮助你在实际逆向分析会话中高效组织工作区、管理多套视图布局,并理解 Cutter 界面状态持久化的完整机制。
Layout Manager 对话框
View 菜单结构总览
从界面定义文件 MainWindow.ui 可以还原 View 菜单的完整组织结构,它自上而下依次为:
- Refresh Contents(刷新内容)
- 分隔线
- Reset to Default Layout(重置为默认布局)
- Reset Settings(重置为默认设置)
- 分隔线
- Unlock Panels(解锁面板)
- Show Tabs at the Top(顶部显示标签)
- Grouped Dock Dragging(分组停靠拖动)
- 分隔线
- Zoom子菜单(Zoom In / Zoom Out / Reset)
- 分隔线
- Manage Layouts(管理布局)
- Save Layout(保存布局)
- Layouts子菜单(已保存布局的动态列表)
其中 Zoom 子菜单内还包含一个分隔线,将 Zoom In、Zoom Out 与 Reset 分开,便于区分"逐步缩放"与"一键复位"两类操作。下面按功能类别逐一展开。
刷新内容(Refresh Contents)
功能说明:在某些情况下,Cutter 各个面板(Widget)上显示的信息并非总是最新的。典型场景是——你在 Cutter 内置的 Rizin 控制台(Console)中手动执行了命令,例如新定义了一个函数(af系列命令)或修改了标志、注释,此时各面板仍停留在旧数据上。执行View → Refresh Contents后,Cutter 会从当前会话中重新拉取最新数据,并同步更新所有打开的视图。
操作路径:View -> Refresh Contents
源码级调用链:该菜单项的信号连接定义在 MainWindow.cpp,触发后依次调用:
ui->actionRefreshContents (triggered) └─> MainWindow::onActionRefreshContentsTriggered() [MainWindow.cpp#L1703-L1706] └─> MainWindow::refreshAll() [MainWindow.cpp#L899-L902] └─> CutterCore::triggerRefreshAll() [Cutter.cpp#L1241-L1244] └─> emit refreshAll() [Cutter.h#L996]refreshAll()信号会被所有需要实时更新的面板订阅,从而完成一次全量刷新。值得一提的是,这一刷新机制同样被大量内部流程复用:例如分析任务完成(AnalysisTask::finished)、切换调试视图、运行初始化脚本等场景都会调用refreshAll(),确保界面与底层 rizin 会话状态保持一致(见 MainWindow.cpp 与 Cutter.cpp)。
快捷键支持:该菜单项已接入 Cutter 的快捷键系统,对应配置键为General.refreshContents(见 MainWindow.cpp),你可以通过Options → Preferences → Shortcuts自行绑定习惯的快捷键。
已知限制(官方说明):原文档明确标注,未来 Cutter 将实现对底层变更的自动感知并自动更新所有视图,目前该能力仍在开发中(work-in-progress)。因此在自动更新机制落地之前,遇到面板数据陈旧时,手动刷新是最可靠的同步手段。
重置布局与重置设置
View 菜单中并列提供了两个"重置"入口,它们作用域完全不同,容易混淆:
Reset to Default Layout(重置为默认布局)
功能说明:将当前布局恢复为 Cutter 出厂自带的默认布局(即Default内置布局)。默认布局由MainWindow::restoreDocks()(MainWindow.cpp)构建:左侧为函数列表(Functions),中央主区域以标签页(tabify)形式堆叠 Dashboard、入口点、标志、字符串、重定位、导入、导出、类型、搜索、头文件、符号、全局变量、类、资源、虚表、Sdb、内存映射、断点、调用图等多个面板,下方为 Console 与 Sections/Segments/Comments 区域,右侧垂直堆叠 Stack、Registers、Backtrace、Threads 等调试相关面板。
操作路径:View -> Reset to default layout
实现细节:恢复默认布局时,setViewLayout(getViewLayout(layoutDefault))会先关闭所有现有 Dock 组件,然后依据内置布局创建 Disassembly(反汇编)、Graph(图形)、Hexdump(十六进制)与 Decompiler(反编译器)等核心视图,最后调用showZenDocks()(普通模式)或showDebugDocks()(调试模式)显式展示相应面板集(见 MainWindow.cpp)。
Reset Settings(重置为默认设置)
功能说明:将 Cutter 的全部当前设置恢复为出厂默认值。与"重置布局"只影响面板排布不同,此项会清除所有配置,包括外观主题、反汇编选项、快捷键、插件偏好等。
操作路径:View -> Reset Settings
安全确认机制:为避免误操作,源码中在执行前会弹出确认对话框,提示"Do you really want to clear all settings?",用户确认(Ok)后才调用Config()->resetAll()真正清除设置(见 MainWindow.cpp)。
锁定与解锁面板(Lock / Unlock Panels)
功能说明:控制各面板(Dock Widget)是否允许被移动或关闭。取消勾选该选项可防止在分析过程中意外拖动、关闭面板而破坏当前精心排布的工作区布局。
操作路径:View -> Unlock Panels
源码级原理:菜单项为复选状态(actionUnlock)。当面板处于锁定状态时,MainWindow::lockDocks(true)会遍历主窗口下所有QDockWidget,将其特性设置为QDockWidget::NoDockWidgetFeatures,即完全禁止移动、关闭与浮动;解锁后则恢复为DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable三项特性(见 MainWindow.cpp)。
持久化:该状态会随设置保存,写入QSettings键panelLock(值取!ui->actionUnlock->isChecked()),下次启动时通过readSettings()恢复(见 MainWindow.cpp)。
标签位置与分组拖动
这两个选项都用于微调多面板停靠(Dock)的交互体验:
Show Tabs at the Top(顶部显示标签)
功能说明:切换标签栏(Tab Bar)的显示位置——勾选后标签显示在顶部,取消则显示在底部。
操作路径:View -> Show Tabs at the Top
实现细节:MainWindow::setTabLocation()根据tabsOnTop标志调用setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::North)(顶部)或QTabWidget::South(底部),并同步勾选状态(见 MainWindow.cpp)。该设置持久化到QSettings键tabsOnTop。
Grouped Dock Dragging(分组停靠拖动)
功能说明:启用后,拖动某个面板时,与其处于同一停靠组的其他面板会被一并拖动;若只想从一组中单独拖出某个面板,应从该面板的标签页(Tab)本身拖动,而非其标题栏。禁用此选项后,每次拖动都只作用于单个面板。
操作路径:View -> Grouped dock dragging
实现细节:该选项依赖 Qt 5.7 及以上版本的QDockWidget::GroupedDragging特性,通过dockWidget->setDockOptions(...)动态开关(见 MainWindow.cpp)。其开关状态持久化到QSettings键docksGroupedDragging(默认值为false,见 MainWindow.cpp)。
缩放控制(Zoom In / Zoom Out / Reset)
功能说明:对图形视图(Graph)、反汇编视图(Disassembly)、十六进制视图(Hexdump)等多种需要缩放的面板提供统一的缩放控制。
操作路径与快捷键:
| 菜单项 | 操作路径 | 默认快捷键 |
|---|---|---|
| Zoom In | View -> Zoom -> Zoom In | Ctrl++ |
| Zoom Out | View -> Zoom -> Zoom Out | Ctrl+- |
| Reset Zoom | View -> Zoom -> Reset | Ctrl+= |
源码级原理:缩放并非由各面板独立实现,而是统一作用于全局配置项zoomFactor。三个槽函数分别为(见 MainWindow.cpp):
void MainWindow::onZoomIn() { Config()->setZoomFactor(Config()->getZoomFactor() + 0.1); } void MainWindow::onZoomOut() { Config()->setZoomFactor(Config()->getZoomFactor() - 0.1); } void MainWindow::onZoomReset(){ Config()->setZoomFactor(1.0); }即每次 Zoom In / Zoom Out 以0.1 为步长调整缩放因子,Reset 则将缩放因子恢复为1.0(100% 原始大小)。由于缩放因子存放在全局Config中,Graph、Disassembly、Hexdump 等面板都会响应这一变化,实现了跨面板一致的缩放体验。
布局管理:保存、加载与管理
布局(Layout)是 Cutter 工作区状态的核心抽象。根据官方文档 layout.rst 的定义:布局 = 当前打开的面板集合 + 它们的位置 + 部分面板属性。Cutter 会在每次退出时自动恢复上次的布局状态,且正常模式与调试模式的最近布局会分开存储。
数据模型:CutterLayout
布局在源码中以Cutter::CutterLayout结构体表示(见 CutterLayout.h):
struct CutterLayout { QByteArray geometry; // 主窗口几何信息 QByteArray state; // 各 Dock 的状态(由 QMainWindow::saveState 生成) QMap<QString, QVariantMap> viewProperties; // 每个面板的个性化属性 };geometry:主窗口的位置与尺寸;state:所有 Dock 的停靠位置、可见性等状态;viewProperties:按面板对象名(objectName)索引的属性表,例如某个反汇编视图当前的偏移地址、某个图形视图的缩放与滚动位置等,由各面板通过serializeViewProperties/deserializeViewProperties读写。
内置布局与命名布局
仓库定义了仅有的两个内置布局名(见 CutterLayout.h 与 CutterLayout.cpp):
Default:正常模式布局;Debug:调试模式布局。
isBuiltinLayoutName()用于区分内置布局与用户命名布局——内置布局不能出现在"保存布局"的名称选项中,也不会出现在 Layouts 子菜单里。
关键行为约定(来自官方文档):命名布局永远不会被自动修改。当你加载一个命名布局后,Cutter 不会自动把当前改动写回该布局;若要更新某个已保存的布局,必须在Save Layout对话框中选择列表中已有的布局名(而非输入新名称)来完成覆盖保存。
Save Layout(保存布局)
功能说明:将当前布局(打开的面板集合、位置及相关属性)以指定名称保存。
操作路径:View -> Save Layout,在弹出对话框中输入布局名称。
实现细节:MainWindow::saveNamedLayout()(MainWindow.cpp)会弹出可编辑下拉输入框(QInputDialog::getItem),候选列表为除两个内置布局外的所有已保存布局名。输入的名称会经过校验:不允许为空,也不允许与内置布局名Default/Debug重名,否则弹出 "Save layout error" 警告并要求重新输入。保存成功后立即刷新 Layouts 子菜单并持久化设置。
Manage Layouts(管理布局)
功能说明:对已保存的命名布局进行重命名和删除操作。
操作路径:View -> Manage layouts,选择布局后执行对应命令。
实现细节:该功能由独立的 LayoutManager 对话框实现,MainWindow::manageLayouts()构造LayoutManager并以模态方式执行(见 MainWindow.cpp)。关闭对话框后同样会刷新 Layouts 子菜单,保证列表与当前存储一致。
Layouts 子菜单(加载布局)
功能说明:将所选布局的设置应用到当前工作区。加载布局不会导致该布局被自动修改——要固化改动必须使用上述 "Save Layout" 命令。
操作路径:View -> Layouts -> 布局名称
实现细节:MainWindow::updateLayoutsMenu()(MainWindow.cpp)会动态清空并重建 Layouts 子菜单:遍历所有已保存布局,跳过内置布局(Default/Debug),为每个命名布局创建一个QAction,点击后调用setViewLayout(getViewLayout(name))执行加载。
布局加载的底层流程
MainWindow::setViewLayout(const CutterLayout &layout)(MainWindow.cpp)是加载布局的核心函数,其工作流程如下:
- 关闭并移除当前所有 Dock 组件,并确保其不再浮动;
- 判断目标布局是否为空(
state或geometry为空则视为默认布局); - 若为默认布局,则按需创建 Disassembly、Graph、Hexdump、Decompiler 四个核心视图;否则根据
viewProperties中的对象名列表按需重建各面板(通过widgetTypeToConstructorMap工厂映射); - 调用
restoreDocks()重建默认停靠骨架; - 对每个面板调用
deserializeViewProperties()恢复其个性化属性(没有记录属性的面板以空属性重置,并作为"新面板"后续显式展示); - 非默认布局调用
restoreState(layout.state)恢复停靠状态,新面板通过dockOnMainArea()智能放置——该函数会优先选择面积最大的已有面板进行 tabify 合并(见 MainWindow.cpp),随后显示新面板(这样有助于发现新版本引入的面板或新安装插件提供的面板); - 默认布局则根据是否处于调试模式调用
showZenDocks()或showDebugDocks()展示面板集。
设置持久化:布局与选项如何被记住
Cutter 通过QSettings持久化所有界面状态。MainWindow::saveSettings()(MainWindow.cpp)在退出时写入以下键:
| QSettings 键 | 含义 |
|---|---|
panelLock | 面板是否锁定(锁定后禁止移动/关闭) |
tabsOnTop | 标签栏是否显示在顶部 |
docksGroupedDragging | 是否启用分组停靠拖动 |
geometry | 主窗口几何信息 |
布局数据(经saveLayouts) | 全部命名布局 + 最近一次正常/调试布局 |
其中当前布局会按调试状态写入layouts[layoutDebug]或layouts[layoutDefault](见 MainWindow.cpp),下次启动时由readSettings()自动恢复——这正是"Cutter 会自动恢复上次布局"的实现依据。
总结与操作速查
View 菜单承载了 Cutter 工作区管理的全部核心操作,将上文内容汇总为一张速查表:
| 功能 | 操作路径 | 快捷键 | 底层机制 |
|---|---|---|---|
| 刷新内容 | View → Refresh Contents | 可绑定(General.refreshContents) | 触发refreshAll信号全量更新 |
| 重置默认布局 | View → Reset to default layout | — | 关闭所有面板并重建默认布局 |
| 重置默认设置 | View → Reset Settings | — | 确认后Config()->resetAll() |
| 锁定/解锁面板 | View → Unlock Panels | — | 切换QDockWidgetFeatures |
| 标签位置 | View → Show Tabs at the Top | — | 切换QTabWidget::North/South |
| 分组拖动 | View → Grouped dock dragging | — | Qt 5.7+GroupedDragging |
| 放大 | View → Zoom → Zoom In | Ctrl + + | zoomFactor += 0.1 |
| 缩小 | View → Zoom → Zoom Out | Ctrl + - | zoomFactor -= 0.1 |
| 复位缩放 | View → Zoom → Reset | Ctrl + = | zoomFactor = 1.0 |
| 保存布局 | View → Save Layout | — | 写入CutterLayout并持久化 |
| 管理布局 | View → Manage layouts | — | LayoutManager对话框 |
| 加载布局 | View → Layouts → 布局名 | — | setViewLayout(getViewLayout(name)) |
掌握这些菜单项及其背后的持久化机制后,你可以为不同的分析场景(静态分析、动态调试、图形化浏览)分别保存专属布局,并通过 Layouts 子菜单一键切换;在 Rizin 控制台手工修改数据后及时刷新面板;以及在精细调整面板排布时先锁定面板防止误操作。相关源码可进一步参阅 MainWindow.cpp、CutterLayout.h、LayoutManager 与布局偏好文档 layout.rst。
- 应用安全
- 桌面应用
- 开发工具
【免费下载链接】cutter
Free and Open Source Reverse Engineering Platform powered by rizin
相关推荐
Cutter 图形视图(Graph View)右键菜单实战指南:高亮标记、图谱导出与布局算法配置
Cutter 图形视图(Graph View)右键菜单实战指南:高亮标记、图谱导出与布局算法配置 Cutter(基于 rizin 的自由开源逆向工程平台)的图形
应用安全桌面应用开发工具PrimeNG Splitter 组件完全指南:可拖拽缩放面板布局的实现与配置
PrimeNG Splitter 组件完全指南:可拖拽缩放面板布局的实现与配置 Splitter 是 PrimeNG(The Most Complete Ang
前端UI组件Ruby on Rails 中的 Action View 完全指南:模板、局部模板与布局
Ruby on Rails 中的 Action View 完全指南:模板、局部模板与布局 Action View 是 Ruby on Rails 中 MVC 架
Web框架后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考