【Delphi】Quality Central ブラウザを作った話

# はじめに

Quality Central へのレポートを閲覧するブラウザを作りました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/fb78c3e5-7532-da7f-437f-a303d2603b02.png)

その経緯についてです。

# 背景

Quality Central ブラウザを作る事になった背景です。

## Borland / Inprise / Codegear / Embarcadero のバグトラッキングシステム

Borland / Inprise / Codegear / Embarcadero のバグトラッキングシステムは代替わりしているので、いくつか種類があります。まずはこれを説明する必要があります。

### ■ Quality Central

最初のバグトラッキングシステムです。要 BDN/CDN/EDN アカウントですが、見るだけならアカウント不要でした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/49ff216a-172e-9ba7-c67f-339252bdb08c.png)

 - [Quality Central (Borland)](http://qc.borland.com/)
 - [Quality Central (Codegear)](http://qc.codegear.com/)
 - [Quality Central (Embarcadero)](http://qc.embarcadero.com/)

ベータテスト用の報告も可能で、通常アカウントでは見る事ができない **青 QC** というものがありました。なので、報告すると「重複している」と言われる事も。

Windows 用の `Qualitycentral.exe` というクライアントアプリも存在し、一部の開発製品には同梱されていました。Java 製のクライアントもありました。

:::note
廃止予告が 2014 年に出され、2017/06 頃にシャットダウンされました (Web サービスを含めた完全シャットダウンの時期は不明)。

現在は閲覧できません。
:::

**See also:**

 - [Quality Keeps Moving Forward ([Internet Archive] community.embarcadero.com)](https://web.archive.org/web/20170721061737/https://community.embarcadero.com/blogs/entry/quality-keeps-moving-forward)
 - [Embarcadero QualityCentral is dead; man-decades of customer work down the drain (wiert.me)](https://wiert.me/2017/12/21/qcscraper-clientdataset-xml-dump-results-archive-of-qc-embarcadero-com/)
 - [Quality Central についての基礎知識 (ht-deko.com)](https://ht-deko.com/tech016.html)
 - [Quality Central についての補足事項 (ht-deko.com)](https://ht-deko.com/tech017.html)

### ■ Quality Portal (オンプレミス)

先代のバグトラッキングシステムです。要 EDN アカウント。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/26d7bfab-4188-6b78-4bc3-9351d5973a8f.png)

 - [Embarcadero Quality Portal (Embarcadero)](https://quality.embarcadero.com/secure/Dashboard.jspa)

Quality Central のレポートは内部的 (Internal Tracking) には移行されていますが、一般的には見る事ができません。なので、報告すると「重複している」と言われる事も。

Atlassian がオンプレミスのバグトラッキングシステムを提供しなくなったため、『Quality Portal (クラウド)』へ移行する事になったのですが、この時期、Embarcadero のサイトが全般に不調で、そのためか移行が遅れ、オンプレミスの Quality Portal が読み取り専用になった後でクラウドの Quality Portal が運用開始になりました。つまり、バグ報告できない期間がありました。

:::note
現在は読み取り専用となっています。
:::

**See also:**

 - [Embarcadero Quality Portal Migration (Embarcadero Blog)](https://blogs.embarcadero.com/embarcadero-quality-portal-migration/)

### ■ Quality Portal (クラウド)

現行のバグトラッキングシステムです。2024/04 運用開始。要 EDN アカウント。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/742cd583-a228-3953-bde6-c0ceea4ee050.png)

 - [Embarcadero Quality Portal (Embarcadero)](https://embt.atlassian.net/servicedesk/customer/portals)
 - [すべてのリクエスト - Embarcadero Quality Portal (Embarcadero)](https://embt.atlassian.net/servicedesk/customer/user/requests?page=1&reporter=all)

Quality Portal (オンプレミス) のレポートは内部的 (Internal Tracking) には移行されていますが、一般的には見る事ができません。なので、報告すると「重複している」と言われる事も。

:::note
「個人的には」と前置きしておきますが、過去一で使いにくいです。自分の投稿はすぐに探せるのですが、他にどのような問題が投稿されているのかを[このページ](https://embt.atlassian.net/servicedesk/customer/portals)からは探せません。検索窓のように見えるのは問題を探すためのものではありません。

:::

**See also:**

 - [新しいEmbarcadero Quality Portal 運用開始のお知らせ (Embarcadero Blog)](https://blogs.embarcadero.com/ja/the-new-quality-portal-is-live-here-are-the-details-ja/)

## Quality Central について

Quality Central はログインなしで閲覧可能だったため、結構な数のページが Internet Archive に捕捉されています。Quality Central に対して張られたリンクは Internet Archive 経由で読めるものが多いです。

### Quality Central の重要性

古い Delphi のバグと関連情報が載っています。つまり、古い Delphi で書かれたコードをメンテナンスする場合や、そのコードをマイグレーションする際に役立ちます。

Workaround やコメント欄には解決方法が載っていて、一種のナレッジベースとしても機能していました。

今では Web 検索に引っ掛からないような情報もあります。ChatGPT 先生は何も教えてはくれません。

### Internet Archive (Wayback machine)
で、先日 Internet Archive が DDoS 攻撃によりダウンしました。

 - [Internet Archive、ダウンは続くも「データは破損していない」 (ITmedia)](https://www.itmedia.co.jp/news/articles/2410/11/news105.html)
 - [「Internet Archive」がDDoS攻撃でダウン--3100万件のアカウント情報が漏えい (ZDNET Japan)](https://www.itmedia.co.jp/news/articles/2410/11/news105.html)

これには困りました。Internet Archive 依存はダメで、<font color="Crimson">本当に重要なデータは自分で管理しなければならない</font>と悟りました。明日の事なんて誰にもわかりませんしね。

こうして重い腰を上げて **「Quality Central ブラウザを作ろう！」** と思い立ったのでした。

### QCScraper
遡って QC がシャットダウンされた頃、Uwe Raabe 氏が QC の情報をローカルにダウンロードする **QCScraper** を公開しました。

 - [How to save QualityCentral (The Art of Delphi Programming)](https://www.uweraabe.de/Blog/2017/06/09/how-to-save-qualitycentral/)

これを使えば添付ファイルを除いた、Quality Central の情報を丸ごとダウンロードできるものでした。ダウンロードされた XML は TClientDataSet に直接読み込む事ができます。

 - [TClientDataSet (DocWiki)](https://docwiki.embarcadero.com/Libraries/ja/Datasnap.DBClient.TClientDataSet)

ただ、日本語環境ではそのままだと文字化けが発生していました。

```pascal:uQCScraper.pas
function TByteDynArrayHelper.DecodeAndUnCompress: string;
var
  bytes: TBytes;
  fWorkStream: TMemoryStream;
  fEncodedStream: TMemoryStream;
  fStreamDeCompressor: TDeCompressionStream;
  Enc: TEncoding; // ADD
begin
  fEncodedStream := TMemoryStream.create;
  try
    fWorkStream := TMemoryStream.Create;
    try
      fWorkStream.Write(Self[0], Length(Self));
      fWorkStream.Position := 0;
      TNetEncoding.Base64.Decode(fWorkStream, fEncodedStream);
    finally
      fWorkStream.Free;
    end;
    fEncodedStream.position := 0;
    fWorkStream := TMemoryStream.create;
    try
      fStreamDeCompressor := TDeCompressionStream.create(fEncodedStream);
      try
        fWorkStream.CopyFrom(fStreamDeCompressor, 0);
      finally
        FreeAndNil(fStreamDeCompressor);
      end;
      fWorkStream.position := 0;
      SetLength(bytes, fWorkStream.size);
      fWorkStream.Read(bytes, fWorkStream.size);
    finally
      fWorkStream.Free;
    end;
  finally
    FreeAndnil(fEncodedStream);
  end;

//  Result := TEncoding.ANSI.GetString(bytes); // MOD
  Enc := TEncoding.GetEncoding(1252);
  try
    Result := Enc.GetString(bytes);
  finally
    Enc.Free;
  end;
end;
```

Quality Central からのダウンロードに数時間掛かったため、あまり利用される事はなかったように思います。

:::note
Quality Central の Web サービスがシャットダウンされているため、QCScraper は現在利用できません。
:::

### QCScraper のデータ
私も QCScraper が吐いたデータを持っていたのですが、どのストレージに置いたのか失念してしまいました。自分のアカウントで作ったデータなので、青 QC が含まれていて、どのみち公開はできないシロモノでした。

そして、少し時間が経った頃、Jeroen W. Pluimers 氏が QCScraper のデータを公開しました。

 - [QCScraper ClientDataSet XML dump results – archive of qc.embarcadero.com (wiert.me)](https://wiert.me/2017/12/21/qcscraper-clientdataset-xml-dump-results-archive-of-qc-embarcadero-com/)

公開されたデータは 4 種類あります。

| ファイル | 説明 |
|:---|:---|
| QCScraper.Anonymous.cds.xml | ログインしない状態で取得された QC データ |
| QCScraper.Anonymous.cds.tidy.xml | ↑ を整形したデータ |
| QCScraper.Regular.cds.xml | 新規 EDN アカウントでログインして取得された QC データ |
| QCScraper.Regular.cds.tidy.xml | ↑ を整形したデータ |

 - `tidy` と付くものは TClientDataSet に読み込ませようとするとエラーになります
 - `QCScraper.Anonymous.cds.xml` は未ログインで閲覧可能だったデータのみです
 - 自分で使うなら件数の多い `QCScraper.Regular.cds.xml` がオススメです

これを Quality Central ブラウザのデータとして使う事にしました。

# Quality Central Browser

サクッと作って X (Twitter) でバイナリを公開した後、プロジェクト一式を整理して GitHub で公開しました。

 - [Quality Central Browser (GitHub)](https://github.com/ht-deko/Quality-Central-Browser)

Delphi 12.0 で作っていますので、無償版の Community Edition でビルドできます。

 - [Delphi Community Edition (Embarcadero)](https://www.embarcadero.com/jp/products/delphi/starter)

標準のコンポーネントしか使っていませんが、比較的新しい Delphi でないとビルドできないと思います。

そのままビルドするとデータのない `QCBrowser.exe` ができてしまいます。ビルド前に `QCScraper.Regular.cds.xml` を TClientDataSet に読み込ませてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/08ac19c8-3cd0-965e-ad2d-36269dac2da5.png)

正しく読み込ませてビルドすると 80MB 程度の実行ファイルが出来上がると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/695951c4-4c03-b9e7-39d4-63cce66300f4.png)

実行時に XML を読み込ませたいのであれば、ソースコードをいじってみてください。

:::note
余談ですが、何故こんなにも小さいプログラムでフォームとデータモジュールを分離しているのかというと、QCScraper の XML データが DFM に格納されてしまうためです。

メインフォームに XML データが格納されると (大きなデータを格納すると)、フォームをいじった際に履歴として残ってしまい、`__history` フォルダが簡単に数 GB に膨れ上がります。

フォームデザイナの動作も緩慢になり DFM の破損にもつながるため、一度貼ったらコード以外ほぼ触らないデータモジュールはとても都合がいいのです。
:::

## Quality Central Browser の使い方
`QCBrowser.exe` を起動します。表示は Web 版の Quality Central に寄せています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/06f9ebda-f398-cfc2-ddcc-6afd1c7874ed.png)

### タブ

データが存在しないタブのアイコンはグレーアウトします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/096068ac-7cc5-778a-2618-6f7b17214498.png)

タブは次のようになっています。

| 名称 | 説明 |
|:---|:---|
| Description | この報告の詳細な説明です |
| Steps | この報告がバグであれば、その再現方法です |
| Workaround | この報告がバグであれば、その回避方法です  |
| Attachment | 添付ファイルです (取得はできません) |
| Comments | この報告に寄せられたコメントです。他ユーザーからの回避方法が書かれている事があります |

### 検索
QC 番号が判っているのなら、上の虫眼鏡アイコンのボタンを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/adff5fba-1c6b-1f90-5808-c7b028fca7a8.png)

`Go to Report` ダイアログが出るので、QC 番号を入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/9a80e37f-306a-84a4-725e-57a9920af23e.png)

:::note
最新版では `Report #:` の所に直接入力でも検索できます。
:::

### 各部のショートカット
ショートカットキーは次のようになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/87931d88-baa6-1299-f0fd-a92e397c9846.png)

### フィルター (高度な検索)

下部にあるフィルターでレコードを絞り込む事ができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/807a7644-2bc9-241b-47aa-59e0e9eb8249.png)

フィールド名は検索したい箇所のラベルやタブをダブルクリックすると挿入されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/c5b71477-c80e-6780-9250-d9e6d0457f43.png)

ただ、星印の箇所はルックアップフィールドなので、元のコードで検索する必要があります。例えば `STATUS` は次のようになっています。

| Code | Name |
|:---|:---|
| 10 | Open |
| 20 | Resolved |
| 30 | Closed |
| 40 | Reported  |
| 50 | Withdrawn |
| 60 | Automated Report |
| 70 | Pending |

:::note
`元のコード` は[ソースコードに付属の XML](https://github.com/ht-deko/Quality-Central-Browser/tree/main/xml) で確認できます。
:::

フィルタ式の文法については DocWiki を参照してください。

 - [Filter (DocWiki)](https://docwiki.embarcadero.com/Libraries/ja/Data.DB.TDataSet.Filter)

### レコードの選択と移動 

絞り込んだレコードは右下のナビゲーションボタンで移動できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/b793131d-388a-c987-ee51-4482380b9c15.png)

ナビゲーションボタンの横のボタンを押すと一覧が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/c9955f77-b7d0-35f4-add7-187d6b8dbf06.png)

### QCWIN: プロトコル
管理者権限で次のコマンドを実行すると `QCBrowser.exe` が `QCWIN:` プロトコルに関連付けられます。

```
QCBrowser.exe /RegisterProtocol
```

関連付けがうまく行くと、画像のようなリンクをクリックすると QCBrowser.exe が起動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/81a7928e-7e44-e243-62e2-9257a9e09893.png)

こちらのページで試してみてください。

 - [RTL のバグによる文字コード関連の問題を回避するには？ (ht-deko.com)](https://ht-deko.com/tech051.html)

`[ファイル名を指定して実行]` からも使えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/0bbf8215-f0ec-5ca2-0dff-e8be382e8374.png)


関連付けの解除は次のようにします (要管理者権限)。

```
QCBrowser.exe /UnregisterProtocol
```

:::note
`QCWIN:` プロトコルは元々 `QualityCentral.exe` で使われていました。古い Delphi / C++Builder をインストールしている場合、ひょっとすると関連付けが残っているかもしれませんね。
:::


### DeepL 翻訳
`QCBrowser.exe` と同じ場所に、必要な項目を埋めた `QCBrowser.env` を置くと、

```
[TranslateAPI]
APIType=1                                     // 1=DeepL
Enabled=0                                     // 1 で有効
URL=https://api-free.deepl.com                // URL (無償版)
;URL=https://api.deepl.com                    // URL (有償版)
ContentType=application/x-www-form-urlencoded // コンテンツタイプ
Resource=/v2/translate                        // リソース
AuthKey=********                              // 取得した DeepL の API キー
Language=JA                                   // 翻訳先の言語
```

フォーム下部にあるタブ内のメモフィールドを `〔Ctrl〕+〔T〕`で **DeepL** 翻訳できます (トグル)。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/31092f5d-7033-f523-32ba-74a1022de41e.png)

`[Comments]` タブのコメントはネストされたレコードなので、ポップアップで翻訳されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/263b3ec7-e2c0-ace3-5356-4a22513fffc5.png)

※うまく翻訳されない時は文字列を選択してから`〔Ctrl〕+〔T〕`を押してみてください。選択範囲を部分的に翻訳します。

:::note
DeepL の API キーを取得するには、無償版であってもクレジットカードの登録が必要です。
:::

**See also:**

 - [DeepL API (DeepL)](https://www.deepl.com/ja/pro-api)
 - [DeepL API Free (DeepL Support)](https://support.deepl.com/hc/ja/articles/360021200939-DeepL-API-Free)
 - [Translate text (developers.deepl.com)](https://developers.deepl.com/docs/ja/api-reference/translate)

### Google 翻訳 (Google Cloud Translation API)

翻訳に **Google Cloud Translation (Basic)** を使う事もできます。

```
[TranslateAPI]
APIType=2                                     // 2=Google Cloud Translation
Enabled=0                                     // 1 で有効
URL=https://translation.googleapis.com        // URL
ContentType=application/json; charset=UTF-8   // コンテンツタイプ
Resource=/language/translate/v2               // リソース (BASIC)
AuthKey=********                              // 取得した Google の API キー
Language=ja                                   // 翻訳先の言語
```

**See also:**

 - [Cloud Translation ドキュメント (cloud.google.com)](https://cloud.google.com/translate/docs?hl=ja)
 - [Method: translate (cloud.google.com)](https://cloud.google.com/translate/docs/reference/rest/v2/translate)
 - [Use API keys to access APIs (cloud.google.com)](https://cloud.google.com/docs/authentication/api-keys-use)

:::note
Google Cloud Translation を利用するには、無償の範囲であってもクレジットカードの登録が必要です。
:::

### ヘッダ
EDN のページヘッダを模したヘッダがあり、次の機能があります。

 - GitHub リポジトリへのリンク
 - X へのシェア
 - Internet Archive での閲覧 (表示されている QC)
 - Embarcadero Quality Portal へのリンク

デフォルトでオフですが `QCBrowser.env` に次の記述を行うと起動時に表示されるようになります。

```
[SYSTEM]
ShowHeader=1
```

ヘッダは`〔Ctrl〕+〔H〕`で表示をトグルします。

# おわりに
**Workaround** (回避方法) タブと **Comments** タブの内容が Quality Central の真骨頂です！

今更ですが、高橋さんありがとうございました (謎)。