レイアウト状態の永続化
優れたソフトウェアは機能性だけでなく、ユーザーインターフェースの一貫性が重要です。アプリケーション終了時にUI状態を保存し、次回起動時に復元する「レイアウト記憶」機能は、ユーザビリティ向上に不可欠です。
実装概要
レイアウト記憶機能は次の流れで実装します:
- 終了時: UI状態をシリアライズして保存
- 起動時: 保存データをデシリアライズして復元
主要コンポーネント
ウィンドウ管理
複数ウィンドウの生成・破棄を一元管理します。各ウィンドウは独立したコンポーネントとして動作します。
タブ制御
タブシステムでは:
- 同時に選択可能なタブは1つのみ
- ドラッグによるタブ再配置をサポート
サブパネル
各タブに対応するコンテンツ領域です。内部に複数のツールウィンドウを保持します。
記憶対象情報
- コンポーネントウィンドウの数と階層構造
- ウィンドウ位置・サイズ
- ツールバーの表示状態
- タブの順序・選択状態
- サブパネル上のツールウィンドウ配置
シリアライズ処理
基本フロー
void LayoutManager::serializeLayout()
{
QFile file("layout.dat");
if (file.open(QIODevice::WriteOnly)) {
QDataStream stream(&file);
// ウィンドウ数保存
stream << m_windows.size();
// 各ウィンドウ情報保存
for (auto* window : m_windows) {
window->saveState(stream);
stream << "WINDOW_END";
}
}
}
タブ情報保存
void TabContainer::saveState(QDataStream &stream)
{
stream << m_tabs.size(); // タブ数
// タブ情報保存
for (int i = 0; i < m_tabs.size(); ++i) {
stream << m_tabs[i].title();
if (m_tabs[i].isActive()) {
stream << i; // 選択インデックス
}
}
}
ツールウィンドウ保存
void ToolWidget::saveState(QDataStream &stream)
{
stream << m_title;
stream << m_position;
stream << m_size;
stream << static_cast<int>(m_type);
}
デシリアライズ処理
基本フロー
void LayoutManager::deserializeLayout()
{
QFile file("layout.dat");
if (file.open(QIODevice::ReadOnly)) {
QDataStream stream(&file);
int windowCount;
stream >> windowCount;
for (int i = 0; i < windowCount; ++i) {
auto* window = createWindow();
window->restoreState(stream);
QString marker;
stream >> marker;
Q_ASSERT(marker == "WINDOW_END");
}
}
}
タブ情報復元
void TabContainer::restoreState(QDataStream &stream)
{
int tabCount;
stream >> tabCount;
for (int i = 0; i < tabCount; ++i) {
QString title;
stream >> title;
addTab(title);
}
int activeIndex;
stream >> activeIndex;
setActiveTab(activeIndex);
}
ツールウィンドウ復元
void ToolWidget::restoreState(QDataStream &stream)
{
stream >> m_title;
stream >> m_position;
stream >> m_size;
int typeValue;
stream >> typeValue;
m_type = static_cast<ToolType>(typeValue);
// 位置・サイズ適用
move(m_position);
resize(m_size);
}
実装上の注意点
- シリアライズ/デシリアライズ順序の一貫性保持
- データ境界マーカーの活用
- 型安全なenumの取り扱い
- エラー処理の適切な実装