GTKmm (3.0) と glade によるアプリ (14) - ディレクトリーツリーを表示と処理時間の測定
今回は、ツリービューを使ったディレクトリーを表示します。
ただし、短時間の処理向けです。理由は後ほどに。
また、ついでにツリーデータを取得する時間の計測も行います。
普通はあまりディレクトリーツリーを表示するようなことはないと思いますが、場合によっては特定のディレクトリー以下のツリー表示をしたい場合もあると思います。
今回は、右上Entry-Widgetに入力したディレクトリーをルートディレクトリーとし、左側のTreeView-Widgetにディレクトリーツリーを表示します。
また、開始ボタンクリックから全ツリーデータ取得完了までの時間を計測し、右下に msec 単位で処理時間を表示します。
ソースコードは最後に公開。(zipファイルをダウンロードできます)
A. glade の編集
今回もメインウィンドウのみの構成です。
詳細はダウンロードして、paned_test.glade を確認してください。
※ GtkTreeView を GtkScrolledWindow 内に設置することで、ツリービューが現在のWidgetサイズを超える時、自動的にスクロールバー&スクロール処理を行うようになります。
B. MainWindow.h の編集
● MainWindow.h
… protected: … Gtk::Entry *m_edit_dir = nullptr; Gtk::Button *m_btn_start = nullptr; Gtk::Label *m_lbl_complete_time = nullptr; TreeRecords m_record; Glib::RefPtr< Gtk::TreeStore > m_treestore; private: … void on_m_btn_start_clicked() { m_treestore->clear(); m_lbl_complete_time->set_label( "complete time\nstart" ); const auto startTime = std::chrono::system_clock::now(); Gtk::TreeModel::Row row; getdirs( m_edit_dir->get_text() , 0, row ); const auto endTime = std::chrono::system_clock::now(); const auto timeSpan = endTime - startTime; m_lbl_complete_time->set_label( "complete time\n"+ to_string( std::chrono::duration_cast<std::chrono::milliseconds>(timeSpan).count() ) + "[ms]" ); m_treeview->expand_all(); } int getdirs(string dir, int ndirpos, Gtk::TreeModel::Row parent_row) { Gtk::TreeModel::Row row; struct stat stat_buf; struct dirent **namelist=NULL; string search_path; int ni, ndirs; ndirs = scandir(dir.c_str(), &namelist, NULL, alphasort); if (ndirs == -1) { cout << "ERROR scandir" << endl; free(namelist); return -1; } for (ni = 0;ni < ndirs;ni++){ if ( (string(namelist[ni]->d_name) != ".") && (string(namelist[ni]->d_name) != "..") ){ search_path = dir+string(namelist[ni]->d_name); if (stat(search_path.c_str(), &stat_buf) == 0){ if ((stat_buf.st_mode & S_IFMT) == S_IFDIR){ if (ndirpos == 0) row = *( m_treestore->append() ); else row = *( m_treestore->append( parent_row.children() ) ); row[ m_record.m_col_name ] = namelist[ni]->d_name; getdirs(dir + string(namelist[ni]->d_name) + "/", ndirpos + 1, row); } } else{ cout << "ERROR FILE-STAT" << endl << endl; } } } free(namelist); return 0; } …
1) on_m_btn_start_clicked() 関数
(1.1) TreewView-Widget で表示されている全行をクリア
void Gtk::TreeStore::clear ( );
TreeView に関連付けされている TreeAtore の全行をクリアすることで、TreewView-Widgetの全行をクリアします。
(1.2) ツリーデータを取得し、TreeModel にセット
int getdirs (string, int, Gtk::TreeModel::Row);
string : 検索するディレクトリー
int : ルートからの階層の深さ
Row : TreeModelの行クラス
この関数は下位のディレクトリーがなくなるまで、再帰的に自身を呼び出します。
(1.3) 処理時間の計測
system_clock はシステムのリアルタイムのクロックが扱えます。
std::chrono::duration_cast
とすることで、開始時刻と終了時刻の時間差をミリ秒で取得できます。
2) getdirs(string, int, Gtk::TreeModel::Row) 関数
(2.1) scandir() で指定したディレクトリー走査をし、全エントリーを取得
int scandir ( const char *dirp,
struct dirent ***namelist,
int (*filter)(const struct dirent *),
int (*compar)(const struct dirent **, const struct dirent **) );
dir : 指定ディレクトリー
namelist : 取得結果が保存される構造体ポインター
※ 使用後は free でメモリーを開放する必要があります。
filter : フィルター比較関数
compair : ソート比較関数
alphasort : アルファベット順 ( strcoll )
versionsort : 自然な数字順 ( strverscmp )
戻り値 : 取得したエントリー数
(-1) の時はエラー (メモリ不足)
(2.2) ディレクトリーかどうか判断
stat() 関数で、エントリーの状態を取得し、ディレクトリーか判断する。
S_IFMT (0170000) ファイル種別を示すビット領域を表すビットマスクを使い、ファイルの種別を判断します。 S_IFSOCK 0140000 ソケット
if (( stat_buf.st_mode & S_IFMT ) == S_IFDIR ) を、POSIXのマクロを使って
S_IFLNK 0120000 シンボリックリンク
S_IFREG 0100000 通常のファイル
S_IFBLK 0060000 ブロックデバイス
S_IFDIR 0040000 ディレクトリ
S_IFCHR 0020000 キャラクターデバイス
S_IFIFO 0010000 FIFO
if ( S_ISREG( stat_buf.st_mode ) ) としても結果は同じです。 S_ISREG(m) 通常のファイルか?
S_ISDIR(m) ディレクトリか?
S_ISCHR(m) キャラクターデバイスか?
S_ISBLK(m) ブロックデバイスか?
S_ISFIFO(m) FIFO (名前付きパイプ) か?
S_ISLNK(m) シンボリックリンクか? (POSIX.1-1996 にはない)
S_ISSOCK(m) ソケットか? (POSIX.1-1996 にはない)
C. MainWindow.cc の編集
これは、今までやってきたことと同じですので、ダウンロード後ソースファイルをチェックしてください。
※今回は、ボタンクリックのイベントのまま、ディレクトリーの走査やツリーの更新を行っているため、タスクを握ったままになってしまいます。処理中は表示も何もできないので、長時間処理を要するようなディレクトリーには向きません。
このような処理はサンプルが少ないので、今回のサンプルアプリは貴重だと思います。
最後に、全てのファイルを圧縮したファイル(zip)を載せます。
●ソース一式
GTKプログラミングを学習するなら!
- 作者: ToshioCP
- 発売日: 2017/06/06
- メディア: Kindle版
- この商品を含むブログを見る
GTK+とGladeで作るLinuxプログラミング超入門―かっこいいアプリを自分で作ろう! (CompuBooks)
- 作者: 鈴木哲哉
- 出版社/メーカー: すばる舎
- 発売日: 2000/06
- メディア: 単行本
- クリック: 25回
- この商品を含むブログ (1件) を見る
GTK+・GDKによるLinuxアプリケーション開発 (New riders)
- 作者: エリックハーロウ,Eric Harlow,アンク
- 出版社/メーカー: 翔泳社
- 発売日: 1999/10/01
- メディア: 単行本
- クリック: 56回
- この商品を含むブログ (1件) を見る
- 出版社/メーカー: Saravana Pugazhendi
- 発売日: 2015/11/16
- メディア: アプリ
- この商品を含むブログを見る