研究開発日誌

CG研究・開発のちょっとしたメモ書き

Log Browser

2014-12-24 Qt Utility

Qtで開発したシンプルなLog Browser.

プログラムを開発している時にLogを基本垂れ流しにしていましたが後から見づらいということはよくあると思います. そこで,後から見やすいようにカテゴリ毎にログを出力し, 確認できるLog Browserを作成しました.UIはQtを使って開発しました.

#include <QWidget>
#include <QMap>

class QTreeView;
class QStandardItemModel;
class QStandardItem;
class QTextEdit;
class QStackedLayout;

//! LogBrowser implementation.
class LogBrowser : public QWidget
{
    Q_OBJECT
public :
    typedef QMap < QString, QTextEdit* > DebugWindowMap;

    //! Constructor.
    LogBrowser();

    //! Destructor.
    virtual ~LogBrowser(){}

    //! Log debug information with the specified categoryPath, label, message.
    void debug(const QString& categoryPath, const QString& label, const QString& message);

signals:
    void categorySelected(const QString& category);

private:
    void createUI();

    void setCategory(const QString& categoryPath);

    QStandardItem* findCategoryItem(const QString& categoryPath, QStandardItem* parentItem);

    const QString categoryTreeToPath(const QStringList& categoryTree, int level);

private slots:
    // Selection slot for _categoryView.
    void selectCategory(const QModelIndex & modelIndex);

private:
    QTreeView*      _categoryView;
    QStandardItemModel* _categoryModel;
    DebugWindowMap      _debugWindowMap;
    QStackedLayout*     _stackedLayout;
};

QStandardItemModelでdebug関数から送られてくるカテゴリのツリー構造を管理します. QTreeViewでそのツリー構造を表示しています. カテゴリツリーの各ノードは,”TextureGroup/textureIDs”のようにパス文字列と関連づけられていて, パス文字を利用してカテゴリ専用のDebugWindow(今回は単なるQTextEditで実装)に出力します. QStackedLayoutは,各DebugWindowをカテゴリツリーの選択に応じて切り替えるのに使用しています.

実際に,ログ出力を行うときは,

#include "DebugLogger.h"

DebugLogger::debug("TextureGroup/textureIDs", "textureID", textureID);

のように,なるべくシンプルな形でログ出力できるように,LogBrowserのシングルトンインスタンスを持ったDebugLoggerからログ出力をしています(OpenCVのcv::imshowのようにあまり依存関係が無いようにしたいと思い,この形になりました).

#include <QString>

class LogBrowser;

class DebugLogger
{
public :
    // Log debug informaiton with the specified categoryPath, label, message.
    /*!
        Log text will be
            label: message
    */
    static void debug(const QString& categoryPath, const QString& label, const QString& message);

    // Singleton instance of LogBrowser.
    static LogBrowser* browser();
};

debug関数で出力されるTextは,”textureID: 0”のように”label: message”の形になります.browser関数はLogBrowserのシングルトンインスタンスを返すstatic関数です. 以下が実装になります.

void DebugLogger::debug(const QString& categoryPath, const QString& label, const QString& message)
{
    browser()->debug( categoryPath, label, message );
}

LogBrowser* DebugLogger::browser()
{
    static LogBrowser* browserInstance = NULL;
    if (browserInstance == NULL)
    {
        browserInstance = new LogBrowser();
        browserInstance->show();
    }
    return browserInstance;
}

debug関数では,LogBrowserのシングルトンインスタンスのdebug関数をそのまま呼ぶだけです.browser関数のシングルトンインスタンス実装は関数内部にstaticな変数を持たせることで実装しています.