|
5 | 5 | ******************************************************************************/ |
6 | 6 |
|
7 | 7 | #include "Qt/QTMTabPage.hpp" |
| 8 | +#include "Qt/qt_utilities.hpp" |
8 | 9 | #include "base.hpp" |
9 | 10 | #include <QApplication> |
| 11 | +#include <QList> |
10 | 12 | #include <QMouseEvent> |
11 | 13 | #include <QtTest/QtTest> |
12 | 14 |
|
| 15 | +namespace { |
| 16 | +// 构造 carrier 列表:url 与显示标题可独立指定,模拟 SLOT_TAB_PAGES 喂给 |
| 17 | +// replaceTabPages 的输入(标题带尾部 ` *` 表示未保存)。 |
| 18 | +QList<QAction*>* |
| 19 | +makeCarrierList (const QList<QPair<QString, QString>>& urlTitlePairs) { |
| 20 | + auto* list= new QList<QAction*> (); |
| 21 | + for (const auto& p : urlTitlePairs) { |
| 22 | + auto* title = new QAction (p.second); |
| 23 | + auto* closeBtn= new QAction ("Close"); |
| 24 | + auto* tab= |
| 25 | + new QTMTabPage (url (from_qstring (p.first)), title, closeBtn, false); |
| 26 | + list->append (new QTMTabPageAction (tab)); |
| 27 | + } |
| 28 | + return list; |
| 29 | +} |
| 30 | +} // namespace |
| 31 | + |
13 | 32 | class TestQTMTabPage : public QObject { |
14 | 33 | Q_OBJECT |
15 | 34 |
|
@@ -58,6 +77,69 @@ private slots: |
58 | 77 | QCOMPARE (tab.text (), QString::fromUtf8 ("clean-file.tm")); |
59 | 78 | QVERIFY (!tab.isDirty ()); |
60 | 79 | } |
| 80 | + |
| 81 | + // 回归:replaceTabPages 复用既有 tab 时,dirty 状态必须随标题刷新。 |
| 82 | + // 0350 把 `*` 从标题尾部移到关闭按钮位置,m_isDirty 只在构造时解析一次; |
| 83 | + // 2014 把全量重建改成增量复用后,复用路径只 setText 不更新 m_isDirty, |
| 84 | + // 导致编辑标脏/保存去脏都不反映到 `*` 显示。syncDisplay 是该路径的修复点。 |
| 85 | + void test_sync_display_updates_dirty_state () { |
| 86 | + QAction titleAction ("doc.tm", nullptr); // 构造时干净 |
| 87 | + QAction closeAction ("Close", nullptr); |
| 88 | + QTMTabPage tab (url ("file:///tmp/doc.tm"), &titleAction, &closeAction, |
| 89 | + false); |
| 90 | + tab.resize (220, 32); |
| 91 | + tab.show (); |
| 92 | + QVERIFY (QTest::qWaitForWindowExposed (&tab)); |
| 93 | + QVERIFY (!tab.isDirty ()); |
| 94 | + QCOMPARE (tab.text (), QString::fromUtf8 ("doc.tm")); |
| 95 | + |
| 96 | + // 模拟 replaceTabPages 复用:srcTab 已解析过尾部 `*`,传入干净标题 + |
| 97 | + // dirty。 |
| 98 | + tab.syncDisplay (QString::fromUtf8 ("doc.tm"), true); |
| 99 | + QVERIFY (tab.isDirty ()); |
| 100 | + QCOMPARE (tab.text (), QString::fromUtf8 ("doc.tm")); |
| 101 | + |
| 102 | + // 保存去脏:dirty 翻回 false。 |
| 103 | + tab.syncDisplay (QString::fromUtf8 ("doc.tm"), false); |
| 104 | + QVERIFY (!tab.isDirty ()); |
| 105 | + } |
| 106 | + |
| 107 | + // 端到端:replaceTabPages 复用 tab 时,新标题的尾部 `*` 必须刷新到既有 |
| 108 | + // tab 的 dirty 状态(而非停留在构造时解析的旧值)。这正是 0350+2014 回归 |
| 109 | + // bug 的真实触发路径:编辑标脏后上层重发带 `*` 的标题,复用分支需把 dirty |
| 110 | + // 同步过去,关闭按钮位置才会画 `*`。 |
| 111 | + // debug_findTab 仅 LIII_DEBUG 下存在,release 构建跳过。 |
| 112 | + void test_replaceTabPages_refreshes_dirty_on_reuse () { |
| 113 | + QWidget host; |
| 114 | + QTMTabPageContainer container (&host); |
| 115 | + container.setRowHeight (32); |
| 116 | + host.resize (400, 40); |
| 117 | + host.show (); |
| 118 | + QVERIFY (QTest::qWaitForWindowExposed (&host)); |
| 119 | + |
| 120 | + // 首次:干净标题,tab 构造时 dirty=false。 |
| 121 | + container.replaceTabPages (makeCarrierList ({{"tmfs://view/1", "doc.tm"}})); |
| 122 | +#ifndef LIII_DEBUG |
| 123 | + QSKIP ("debug_findTab 仅 LIII_DEBUG 构建可用"); |
| 124 | +#else |
| 125 | + QTMTabPage* tab= container.debug_findTab (url ("tmfs://view/1")); |
| 126 | + QVERIFY (tab != nullptr); |
| 127 | + QVERIFY (!tab->isDirty ()); |
| 128 | + |
| 129 | + // 同一 url 再次喂入,但标题改为带 ` *`(模拟编辑标脏后上层重发)。 |
| 130 | + // 必须复用同一 tab 对象,且其 dirty 翻为 true。 |
| 131 | + container.replaceTabPages ( |
| 132 | + makeCarrierList ({{"tmfs://view/1", "doc.tm *"}})); |
| 133 | + QTMTabPage* reused= container.debug_findTab (url ("tmfs://view/1")); |
| 134 | + QCOMPARE (reused, tab); // 指针不变 => 复用而非重建 |
| 135 | + QVERIFY (reused->isDirty ()); |
| 136 | + QCOMPARE (reused->text (), QString::fromUtf8 ("doc.tm")); |
| 137 | + |
| 138 | + // 第三次:标题去掉 `*`(模拟保存去脏),dirty 翻回 false。 |
| 139 | + container.replaceTabPages (makeCarrierList ({{"tmfs://view/1", "doc.tm"}})); |
| 140 | + QVERIFY (!container.debug_findTab (url ("tmfs://view/1"))->isDirty ()); |
| 141 | +#endif |
| 142 | + } |
61 | 143 | }; |
62 | 144 |
|
63 | 145 | QTEST_MAIN (TestQTMTabPage) |
|
0 commit comments