Qt Quickでスプラッシュスクリーンを表示

こんにちは。こんばんわ?
Qt Advent Calendar 2017の24日目を担当する@IoriAYANEです。

今回は、Qt Quickでスプラッシュスクリーンを表示しつつ、その必要性について語りたいと思います。
他のカレンダーの記事と比べるととってもゆるふわですが、ご了承ください。

/// まずは導入してみる ///
 導入してみます。
 今回のサンプルの主なファイルは以下の通りです。

  ・main.qml
  ・MainWindow.qml

 main.qmlの方でスプラッシュスクリーンを表示する部分を作り込みます。
 MainWindow.qmlは今回のサンプルではどんな内容でも良いので省略します。

 サンプルの仕様を簡単にまとめると以下の通りです。

  ・起動後、画像だけのウインドウを表示
  ・上記ウインドウが表示できしだいメインウインドウのロード開始
  ・メインウインドウのロードが完了しても最低2秒は、上記ウインドウを表示しつづける

 です。

import QtQuick 2.9
import QtQuick.Window 2.3

Item {
    property double startTime: 0

    //スプラッシュスクリーンに相当するウインドウ
    Window {
        id: splash
        visible: true
        width: 480
        height: 300
        //ウインドウ枠をなし・閉じるボタンなどをなしにする
        flags: Qt.SplashScreen
        Component.onCompleted: {
            //スプラッシュスクリーンができたらアプリ本体である
            //MainWindow.qmlを読み込み開始
            startTime = new Date().getTime()
            loader.source = "MainWindow.qml"
        }
        Image {
            //かっこいい絵を用意しよう
            anchors.centerIn: parent
            source: "images/splash_screen.png"
        }
        //ロードが終わっても一定時間は表示するために
        //時間を管理するためのタイマー
        Timer {
            id: timer
            repeat: false
            interval: 1000
            onTriggered: {
                splash.close()
                loader.item.visible = true
            }
        }
    }

    Loader {
        id: loader
        asynchronous: true
        onLoaded: {
            var elapseTime = new Date().getTime() - startTime
            if(elapseTime > 2000){
                //スプラッシュスクリーンが一定時間以上表示されているので
                //すぐにウインドウを切り替える
                splash.close()
                loader.item.visible = true
            }else{
                //ロードは終わったけど一定時間たってないのでちょっと待つ
                timer.interval = 2000 - elapseTime
                timer.start()
            }
        }
    }
}

 対して難しくないですね。
 
 QMLの使い方というかエレメントの組み方でポイントになっているのはアプリケーションのルートにItemエレメントを使用していることです。
 むかーしは、どんなエレメントを使用してもウインドウが生成されていたのですが、現状はApplicationWindowやWindowエレメントのようなウインドウ系のエレメントをあえて使用しないとウインドウは生成されません。
 複数のウインドウを持つアプリケーションを作成しやすくするための措置だと思うのですが、C++(main.cppなど)からQMLを利用するときに使用するクラスにQQmlApplicationEngineクラスを使用するとウインドウが表示されません。そのQQmlApplicationEngineクラスがQt Creatorがプロジェクトを新規作成したときに使われているため、今回のサンプルのような構成でウインドウを二つ並列で用意するといったことが可能になります。ちなみに、QQuickViewクラスを使用するとウインドウが作成されます。

 Windowエレメントのflagsプロパティでウインドウの形態(ウインドウ枠をダイアログ形式や×ボタンを無くすとか)を設定できます。しかも、スプラッシュスクリーン用も用意されいて準備がとても良いです。
 どんな値が設定できるかは「enum Qt::WindowType」を参照してください。

 Loaderエレメントのasynchronousプロパティをtrueにするとメインウインドウをロード中にスプラッシュスクリーンをブロックしないです。今回の作りではたいして意味はないですが......。何らかの状況表示を更新する場合には必要です。

 やっぱり、簡単ですね。


/// で、なんでいるんだっけ? ///
 Qt Quickのアプリケーション(というよりQt QuickでGUIを作ったアプリケーション)は、実行時にテキストのQMLファイルを解釈している関係で起動が遅いです。しかも、QMLファイルの解釈が終わるまでウインドウなどは表示されず、ユーザーにはダブルクリックのミスを疑わせたりと非常にわかりづらい状況です。
 そんな中でQt 5.9からQt Quick Compilerの恩恵を一部受けられるようになりました。QMLのキャッシュファイル(*.qmlc, *.jsc)を用意して近い状況にしてくれるようになりました。デフォルトでは初回起動時に作成します。そのため、起動速度が2回目以降で改善されました。
 
 そうは言っても大規模なアプリケーションで読み込むQMLファイルが多いと起動に時間がかかるのは避けられません。
 そこで、スプラッシュスクリーンです。
 可能な限り軽量に作成したスプラッシュスクリーンを表示し、その後、メインのGUIを含むQMLファイルを読み込む流れにします。
 もちろん、アプリ本体の扉になる画面が軽量ならそこから必要に応じて逐次ロードもありですね。それを極端にしたのがスプラッシュスクリーンなので。

 以前、Qtデバイスの高速起動】Part1: 車載インストルメントクラスタという公式のブログ記事でも紹介されていたように、全くノーリアクションは良くない、なにかユーザーの目に映るモノを用意して裏で頑張るという手法をとるわけです。


/// 状況確認 ///
 QMLの解釈で時間がかかるとはいったものの実際どんなもんだろうってところだと思います。
 なので、参考情報です。
 QMLプロファイラーが用意されているため、それを使用して計測しました。

 詳細:Profiling QML Applications

 題材として僕が開発している電子書籍(epub)を作るソフト「LeME」を使用しました。手元に使えそうなのがなかったので^^;
 結果としてはすごくざっくり数値だと思って以下をみてください。

 
ファイルキャッシュコンパイル(ms)生成(ms)合計(ms)
スプラッシュなし40237277
あり15222237
本体なし253493746
あり156539695
 
 実行するたびに誤差で値が変化していると思いますが、キャッシュがあるとプロファイラでいうところのコンパイル時間が減ります。
 今回題材にしたLeMEがQMLファイル20個程度の規模ですが、スプラッシュスクリーンの方が体感できるレベルで早く表示が可能です(と言っても1秒以下ですが)。
 ただ、Qtの大きなライブラリがディスクキャッシュに入っているかも大きく影響しそうで、そっちの方が実は影響が大きいのではなかろうかという説もあり、無駄なあがき感もありそうですけどね......。ディスクキャッシュが効いているだろうなって状況でもスプラッシュスクリーンのような軽量ウインドウならワンテンポ速く表示できるので微妙な待ちがなくなって良いと思います。

/// おまけ ///
 キャッシュファイルは基本的にQMLファイルと同じフォルダに作成されますが、書き込みできない場合(リソースに含まれるときなど)は、QStandardPaths::CacheLocationのサブフォルダに保存されます。


/// 最後に ///
 本当に意味があるのか怪しい感をにおわせてしまいましたが、キャッシュが効けば早くなるのは間違いないですし、複数ウインドウのアプリケーションも作れることは理解していただけたと思います。
 
 Qt Advent Calendar 2017も残すところ、最終日のみ。
 期待して待ちたいと思います。ではでは。

10/22に開催された技術書典3にサークル参加してきました。

スペースにお越しいただいた皆さんありがとうございます。
台風の中、技術書典に集まった皆さんお疲れ様でした。
今回も最高の運営をしてくれたスタッフの皆さんありがとうございました。

/// 当日の運営 ///
 当日以前に、お手伝いで来てくれる人をちゃんと探して無くて数日前に急遽依頼するという酷い対応をしてしまったので、引き受けてくれた@sharkppさんには感謝です。
 で、当日ですが。
 時間よりちょっと早く開場したサークル入場で入って準備をして最後まで居た感じです。

 100冊オーバー頒布するようなサークルさんとは違って基本的にまったりなのでお客さんとのやりとり自体はそれほど大変じゃないです。
 ただ、それでも知っている人が挨拶にきてくれたり、本の中身について話したりするとどうしてもかかりっきりになるので、お手伝いさんがいると本当に心強いです。あとは自分が他のサークルさんを見て回ったりトイレに行ったりも安心してできます。
 と言うわけで、2人参加がお勧めです。ソロ参加の人すごいなーといつも思ってます。
 さりげなく電子書籍(epub)を作るソフト「LeME」のデモとチラシを置いていたのですが、何人かの人に興味を持って貰えました。本当はチラシを積極的に配りにいかないとなーと思いつつ出不精してます。
 今回は整理券配布が功を奏したのか、人がひどく滞留することもなく流れていた印象でした。再入場と戦利品確認部屋があったのが良かったのかなと。
 サークルとしては特にトラブルもなく無難に過ごせたかなと思います。

/// 頒布数 ///
 在庫が宅配中なので正確にはわからないですが。

 新刊:(12+24)/50
 既刊:(2+10)/20
 ※(かんたん後払い+現金)/印刷
 ※既刊は持ち込み数

 かんたん後払いを利用してくれた人は、13人でした。
 新刊と既刊の両方を買ってくれた人もいるので、だいたい25%くらいの人が電子決済で購入してくれていたと思います。
 傾向としては早めの時間に来てくれた人ほど、電子決済率が高い感覚です。
 購入が確定するとその場で頒布履歴に表示されてシェアコード(小さくて見にくかった><)が確認できてスムーズでした。
 あと、購入する側も不正してませんよってのをアピールする感じか、決済ボタンを押すところから見せてくれる人もいました。単にぼくが操作しているところガン見していたからかもしれませんが^^;

 被チェック数が前回の技術書典2と比べても少ないしこんなもんかなーと思ってましたが、ひとつ忘れ物をしていました。若干ずるくさいものの今までQtユーザー会の勉強会用に何冊かまとめ買いしてもらっていたのをすっかり忘れてやりとりをしていませんでした。なので、トータルで見れば概ね予定通りだったのではと。思ってます。
 そもそも、QtとQt Quickを知っている前提、一見さんお断り状態な内容なのによくこんなに買ってもらえたなぁと思います。Qtって聞いたことあるけど、入門してみようかって人は完全に置いてきぼりなので......。そんな本なので完売しないで欲しいと思ってくれた人全員にお届けできたのは良かったかなと思います。
 ついつい、売れるか売れないかを気にしてしまいがちですが、同人誌にしている内容って大体自分が知りたい・残しておきたい情報をまとめているだけなので、なにが問題なんだと。そう考えることにしてます。
 でも、できれば完売したいですけどねー。「完売、ありがとうございます!」って呟きたいw

/// お金的な話 ///
 ・印刷(88ページ50部):\30,890-
 ・交通費(新幹線往復):\20,220-
 ・表紙イラスト代:ひみつ
 ・その他小物:過去に買った物の使い回しので不明

 よく見ると新刊は完売しなくても印刷代だけなら赤にはならないです。ただ、表紙のイラストはかわぐちけいさん(漫画家さん)に描いてもらっているので費用がかかってます。なので、これから電子版の売上が勝負だったりします。
 イラスト代ですが、もともと以前からの付き合いもあって(いろいろはしょると)タダでも良いよくらいの勢いで引き受けてもらっているのですが、そんなわけにもいかないので気持ちでお支払いしているので、具体的な金額は伏せています。

/// あると良いもの ///
 ・透明なブックカバー
  立ち読みしてもらうようの見本誌に取り付けます。
  見本シールとか張っても本体を汚しませんし、見本用の本を間違えて売ってしまう心配も減ります。
  後で在庫整理しているときも一発で見本用とわかります。

/// 最後に ///
 楽しかったので、また参加したいです!
 
 なんか色々書こうと思ってたけど、書きながら忘れたので思い出したら呟きます。

 またもや技術書オンリーイベント「技術書典3」に参加します!
 なんと年2回に増量して開催されています。ナンバリングではない超技術書典も含めると4回目、すごいです。

 さてさて、今回もなんとか新刊を用意できました。
 いつも通り、Qt Quickの本です。

/// サークルの情報 ///

 サークル名:理ろぐ
 配置場所:お-12

/// 新刊情報 ///

 hyoushi_only.jpg
タイトル:Qt Quickを使いこなすクロスプラットフォームUIプログラミング3
著者 : 理音伊織
イラスト : かわぐちけい
B5サイズ / 84ページ
予価:1000円

 Qt Quick拡張プラグインの作成方法と少し変わったQMLタイプ(エレメント)の作成方法を解説します。
 QMLタイプ(エレメント)作成のおさらいからプラグインとして構築し、Qt Creatorのデザイナーでの編集に利用できるようにするところまでエスコートします。
 また、プラグインのバージョンアップに合わせたQMLタイプの拡張も解説します。
 目次などの詳細情報はBOOTHを参照してください。

/// 既刊情報 ///

 hyoushi_M.jpg
タイトル:Qt Quickを使いこなすクロスプラットフォームUIプログラミング2
著者 : 理音伊織
イラスト : かわぐちけい
B5サイズ / 72ページ
価格:1000円

   春の技術書典2で頒布した本で、Qt Quick Controls 2についての解説書です。  たくさんある機能の中でもスタイルについて取り上げています。基本的な使い方からオリジナルスタイルの作成方法まで解説します。  目次などの詳細情報はBOOTHを参照してください。


/// 展示情報 ///

 当日は、電子書籍(epub)を作るソフトの「LeME」のデモも行っています。
 Wordやテキストや画像から作成できます。
 漫画・小説・技術書をターゲットにしてます。
 もし、電子書籍に興味のある方は、遊びに来て下さい。


 では、当日お会いできることを楽しみしております。

夏コミ(C92)参加情報

 すっかり直前になってしまいましたし、コミケのWebカタログの方に見本やらなんやら登録はしていますが、こちらもで告知です。

サークル:理ろぐ
スペース:3日目 東P-23a

Webカタログでは、見本として冒頭が読めるようになってます。


/// 新刊情報 ///
7a04df06-d84c-4708-9aae-800ba7b2319d.png
タイトル:渚くんの鏡に映る恋人
価格:700円
仕様:文庫・172ページ
著者:あやねいおり
イラスト:ましろ.あー。

今回も新刊を買ってくれた人には、おまけで栞をプレゼントします。

/// 既刊情報 ///
以下の3種類を持っていきます。
・雨の贈り物(500円)
・ワールド・アドミニストレーター(800円)
・君の中の魔法少女(500円)

君の中の魔法少女はラス1ですので、お早めに?


/// その他 ///
あと、電子書籍作成ツール「LeME」のデモもやってます。
イメージキャラクターとして、リーゼロッテ・ルーダ・グーテンベルグにデビューしてもらいました。
こちらもよろしくお願いします。

技術書典2にサークル参加してきました

 予告通り、4/9に秋葉原のアキバスクエアで開催された技術書典2にサークルとして参加してきました。
 今回は、若干調子にのって印刷し過ぎた話とか、制作に関して少しレポしたいと思います。
 が、まず最初に、当日運営を頑張っていたスタッフの皆さんに感謝の気持ちを伝えたいと思います。とても、楽しかったです。ありがとうございます。
 そして、スペースにお越しいただいた皆様ありがとうございます。

様子など

 9:30頃に会場付近でお手伝いをしてくれることになっていた人と待ち合わせをしました。他のサークルさんが少し並んでました。この後すぐにサークル入場が始まって準備開始です。本来は10時からのところを準備を頑張って早めに開けてくれたそうで。流石です。  IMAG0750.jpg

 せっせこ準備をしてこんな店構えで皆さんのお越しをお待ちしておりました。
 C87wd4vV0AEs4gX.jpg

 ぼやけて見にくいのですが、UDXの柱のサイネージで「技術書典2開催中!」という文字が表示されてました。なんか、凄いところでイベントやってるなーと改めて思いました。
 IMAG0752-2.jpg

 なんと、これ以外写真が残っていないという状況でした。もう少し、会場を回りつつ写真撮ったり余裕を持ちたいという気持ちがありつつも、スペースに来てくれた方の対応をちゃんとしたい気持ちもあって結局ほとんどスペースにいました。まぁたいしてトークがうまくないのでたどたどしい説明を少しする程度なんですけどね。でも、「既刊を持ってます」と言っていただいたり、わざわざ質問しに来ていただいたりとあると、とても嬉しいです。それに買ってもらえたら「ありがとうございます」と直接言いたいです。
 

何を頒布していた?

 Qtというクロスプラットフォームフレームワークに関連した本を頒布していました。詳細は「技術書典2で「Qt Quickを使いこなすクロスプラットフォームUIプログラミング2 」を頒布します」を見ていただければと思います。
 Qtって過去だとGoogleEarthやSkypeとか、最近だとLINEのデスクトップ版で使われていたりします。あとは車のナビ的な位置にあるでっかいモニターで使われていたりします。あまり、表だってQt使っているよって主張されることがなくて目立ってないのが残念です。「何とか入ってる」くらいあると目立ちそうなのですけどね。

どれくらい売れたの?

 おそらくどこのサークルさんも気になるところだと思うので数だけですが。
 ・新刊は、100冊印刷で47冊売り
 ・既刊は、50冊印刷で38冊売り
 正直なところ、去年の来場者数が1200くらいで、今年は倍くらいは来るだろうし、Qtに興味を持っている人も相対的に増えるだろうと思っていましたが、甘かったようです。
 もともと4月末の超技術書典を見越して多めにと考えてはいたものの、新刊はQtを知っていて更にQt Quickを使ったことがあるという前提まで必要な内容だったので、数が出にくくなるのは目に見えていたのです。なんか発注するとき変な考えをおこしたようです。あわよくば完売したいとか考えていたようです。
 技術書典サイトの被チェック数が46なので、チェックしてた人は概ね買いに来てくれた感じでしょうか。

制作について

 技術系ではおそらく嫌われ者のWordを使ってます。Re:VIEWとか流行ってますしね。複数人で原稿をGitで管理とかするなら、テクブさんが公開しているシステム使ったりが便利だと思います。基本、ソロ執筆前提ですが参考になればと思います。

 使っているソフト
  ・Microsoft Office Word 2013(本文)
  ・一太郎 2015(文章校正のみ)
  ・JUST PDF 3(PDF版の出力)
  ・LeME(epub版の出力)
  ・しまや出版さんの「Wordをカンタン入稿」(プリンタドライバで入稿データを作ってくれる)
  ・Adobe Photoshop CC 2017(表紙のタイトルロゴ入れ)
  ・Microsoft Office PowerPoint 2013(チラシ)
  ・Inkscape 0.92.1(おまけ用PDF版ダウンロードカード)

 なんでWord使ってるの?って疑問あると思います。なので理由を列挙してみたいと思います。
  ・仕事でWordを使っているので慣れている
  ・初めて同人誌を作るときにしまや出版さんの上記のプリンタドライバがあると
   入稿データを簡単に失敗無く作れたので安心して入稿できた
  ・出来上がりの状態を見ながら編集をしたい
   (タグとかを見ながら編集が苦手。内容に集中したいのにノイズになる)
  ・図が直接描ける(出来上がりと似てますが)
  ・当初は一太郎を持ってなかったので文章校正機能が無いよりは全然マシだったから
  ・他の人にレビューしてもらうとき、OneDriveで共有してメモ機能で指摘してもらえて、
   相手がWord持ってなくてもWeb版で対応できて便利

 こんな感じでしょうか。他にもあった気がするけど。
 出版業界の人に言わせればWordで組版なんてするものじゃないって思っているかもしれませんが、ぼくレベルでは十分です。
 それに、ちゃんと使えば結構便利です。アウトライン・スタイル・相互参照あたりを押さえておけば、十分便利に使えます。この記事を読んでいらっしゃる皆さんは神Excelを指させるくらいでしょうから、きっと仕事では使いこなしていると思います。
 スタイルを使うと書式設定を一括管理できて変更も楽なので、本文に直接設定したりしないです。相互参照を設定しておけば、PDFやepubにするときに別の章や表とか図にリンクが張られるのも便利ですね。いろいろあると思うけど、ぱっと思い出せないなー。これくらいか?
 ただ、すでに書きましたが、複数人で編集するのは向いてませんし、差分も見にくく、バージョン管理がしにくいです。なので、LaTexやRe:VIEWを使うのも良いと思います。

 本文とは関係ないですが、今回の新刊では以下のフォントを使用しました。
  ・本文:JJS游明朝体 Pr6N L
  ・見出し、表、図:JJS游ゴシック体 Pr6N D
  ・ソースコード:Source Code Pro
 既刊では以下を使ってました。
  ・本文:IPAex明朝
  ・見出し、表、図:IPAexゴシック
  ・ソースコード:Source Code Pro
 個人的には、本文を明朝体、表や図の中ではゴシック体が読みやすいと思っています。本文がゴシック体は少し主張しすぎかなーと。ただ、商業誌でも本文がゴシック体の本はいくらでもあるので好みで良いと思います。

 表紙のイラストについては、以前からTwitterで付き合いのあるかわぐちけいさんに描いていただいてます(全部の本ではないですが)。
 ただし、イラストのみでタイトルロゴは自分で入れているため、今年はPhotoshop CCを導入しました。凄い捗りました。フリーでCMYKを使用できるソフトではKritaがあるのですが。ぼくには使いこなせませんでした。でも、Windows/Linux/macOSで動く優れものだったりしますし、KDEソフトなので内部でQtが使われていたりもします。
 ロゴについては、いつも凄い苦労しているのですが、とある作品のオマージュの気持ちでロゴの配色を決めたら凄い楽に進みました。配色大事です。
 ところで、技術書に萌え絵を使うのはどうなんだろう的な意見もあるようですが、ぼくがそうしたかったのだから仕方が無いとしか言いようがなかったりします。実際、「会社に置きづらいよ」って意見も直接聞いているので、損している部分はあるのでしょうけれど、仕方が無いのです。ぼくがそうしたいから。同人誌だし。

海外の反応

 実は、あったのです。
 



 どこで見つけてきたのか、技術書典前に出していた案内サイトを発見したようです。日本語でしか書いてないですが、今時はGoogle翻訳とかで何とかなってしまう感じなんですかね。
 そもそもQt Quickの本が少なすぎてすぐにヒットしてしまうのかも?
 Qtの中の人にも捕捉されていたらしいので、驚きを隠せない感じです。

 さて、とりとめもなく色々書いてきましたが、読んでいただいてありがとうございます。
 改めて、関係した皆様にお疲れ様と楽しかったですねとありがとうを。
 次回は超技術書典です。現場でぜひお会いしましょう!

 技術書の同人誌即売会「技術書典2(2017/4/9)」に参加します。
 今年で2回目のこのイベント。開場が秋葉原UDXに変わってかなり拡大しています。とても楽しいイベントになりそうです。たくさんの人に来てもらって賑わうと良いなーと思ってます。

 さて、今回もQt本を頒布します。新刊が用意できたので、ぜひ、遊びに来て下さい。
 実はお隣さんもQt関連のサークルさんです。

/// サークルの情報 ///

 サークル名:理ろぐ
 配置場所:え-28


/// 新刊情報 ///

 hyoushi_M.jpg
タイトル:Qt Quickを使いこなすクロスプラットフォームUIプログラミング2
著者 : 理音伊織
イラスト : かわぐちけい
B5サイズ / 72ページ
予価:1000円

 Qt Quick Controls 2についての解説書です。
 たくさんある機能の中でもスタイルについて取り上げています。基本的な使い方からオリジナルスタイルの作成方法まで解説します。
 目次などの詳細情報はBOOTHを参照してください。

 Qt Quick Controls 2のスタイルをさわっていたら、作り方知りたくなるよなーと思って調べ始めたのですが、標準で用意されているマテリアルと同じことができるようにしようとすると結構大変なことになることがわかって、意外と苦労しました。なんというか、目玉的な内容ができて良かったとも言えますけども(笑
 内容とは関係ないがですが、今回はフォントを変えて行間を少し広くしたので読みやすくなっているかなと。
 恒例のPDF版の販売は超技術書典(4/29,30)が終わったら開始します。少々お待ちください。


/// 既刊情報 ///

hyoushi.jpg
タイトル:Qt Quickを使いこなすクロスプラットフォームUIプログラミング+
著者 : 理音伊織
イラスト : かわぐちけい
B5サイズ / 116ページ
予価:1300円

 去年の技術書典で頒布した本の再版です。  内容的には夏コミ(C86)で頒布したQt Quick本のQt5.6対応に加筆修正したものです。  追加分として、Qt Quickデザイナーについても少しふれてます(これだけ知ってれば何とかなる的な)。  目次などはBOOTHでご確認ください。  こちらは既にBOOTHでPDF版を販売しておりますが、紙の本で欲しいよって方はどうぞ。


/// 特典情報 ///

 今回も本を購入していただいた方にPDF版を配布します。新刊・既刊ともにです。
 ダウンロードURLを記載したカードか何かを添付します。何にするかは悩み中です(間に合うのか?!)。


 今回もなんとか新刊が出せそうで良かったです。
 同じ4月の超技術書典にも参加しますので、よろしくお願いします。というか、ニコニコ超会議っていったこと無いので別の意味でも楽しみです。どうなることかサッパリですが(笑
 あと、本当にどうでも良いですが、「+」は改訂で「2」は続きという意味です。
 では、当日お会いできることを楽しみしております。

 アプリの開発をしていると、実行時に必要なファイルがでてくると思います。dllとかsoとかdylibとか......、いえ、今回の記事では何でも良いのですけどね。何か設定的なことを書いたテキストでもリソース的なファイルでも何でも。
 大抵、シャドウビルドで開発をするのでそれらのファイルは通常、手でコピーしなければなりません。シャドウビルドで作られたフォルダに都合良く勝手にコピーはされませんから。
 で、数日前の「Qtからお手軽にZIPファイルを扱えるQuaZIPの紹介」でも、サラッとdllをコピーする方法を紹介したのですが、若干使い勝手が悪いです。
 複数のファイルをコピーしたい場合にこの方法だと冗長になってしまうので、イマイチです。
 なので、少しは楽にならないかなーと考えた方法を紹介します。もっと、良い方法があったら誰か教えてください! 凄い人!

/// ポイント ///
 繰り返しもありますが

置換関数を作る
 結局のところ、パスを作るところが冗長なので置換関数でなんとかします。なんとも普通な発想です。もう少し、qmakeっぽいやり方ないものかと思いますが......。
 結局、QMAKE_EXTRA_TARGETSに登録するところは、頑張って書かないといけないのが現状の難点です。つまり、プロジェクト設定でMakeの引数をいっぱい書かないといけないって事です。

コピーコマンドは「$(COPY_DIR)」で書く
 これはMakefileへ「$(COPY_DIR)」がそのまま出力されるので、Makefileで定義されるコピーコマンドが使えます。環境にproファイルで何とかする必要がありません。

Windowsはパスの区切り文字を「\」に統一
 proファイル内は、「/」で統一して書いて良い(Makefileを出力するときにqmakeがなんとかしてくれる)のですが、QMAKE_EXTRA_TARGETSのcommandsはそのままMakefileに出力されるので環境に合わせたパスの表記をしなければなりません。


では、こんな感じです。

/// hoge.pro ///
# 置換関数の宣言(使うところより前)
defineReplace(makeCopyCommand){
    DEPEND_FILE = $$1
    win32:{
        CONFIG(debug,debug|release){
            APP_BUILD_DIR=$$shadowed($${PWD})/debug
        }else{
            APP_BUILD_DIR=$$shadowed($${PWD})/release
        }
        DEPEND_FILE ~= s|/|\|gi
        APP_BUILD_DIR ~= s|/|\|gi
    }else{
        APP_BUILD_DIR=$$shadowed($${PWD})
    }
    return($(COPY_DIR) $$DEPEND_FILE $$APP_BUILD_DIR)
}
# なんかのファイル1個目
copyfile1.commands += $$makeCopyCommand($${PWD}/hoge.txt)
QMAKE_EXTRA_TARGETS += copyfile1
# なんかのファイル2個目
copyfile2.commands += $$makeCopyCommand($${PWD}/../fuga/fuga.dll)
QMAKE_EXTRA_TARGETS += copyfile2
(※proファイルに日本語を書くと化けます。説明用にあえて日本語を書いているだけなのでご注意ください)

/// プロジェクト設定 ///
 以下の画像のようにビルドステップを追加してMakeの引数を設定します。
 qmake_project_setting_build_step.JPG
 (※プロジェクトのパスは今回の例と関係ないので気にしないでください)

 リリースとデバッグの両方で設定してください。ビルド設定を切り替えて「アレ?コピーされない?」となりますので。
 何はともあれ、これでいちいちビルドフォルダへコピーする煩わしさから解放されます。

 

/// 宣伝 ///
 proファイルの詳しいことを知りたい方は、緑野翁さんの著書「qmake入門」を参照してください。BOOK☆WALKERか今冬のコミケC91(2016/12/29 ビックサイト)のスペース「西み32b」で入手できます。
  BOOK☆WALKER:qmake入門

冬コミ(C91)新刊情報「雨の贈り物」

 冬コミの新刊情報です!
 本作も「小説家になろう」に投稿している作品「雨の贈り物」の書籍化です。
 いろいろ、加筆修正している感じです。
 そして、今回も表紙と挿絵が入ります! 風都ふうちさんに相談させてもらって、いろいろとこだわって描いていただいたので、ぜひ、現物を手にしてください。表紙と挿絵で連動しているところも、見所です。
 当日、スペースにてお待ちしております。

表紙_修正_販促用M.jpg

/// 情報 ///
サークル名:理ろぐ
場所:金曜日 西ひ02b
ページ数:132ページ
予価:500円
著者:あやねいおり
イラスト:風都ふうち(pixiv)

/// 内容 ///
 ある日の高校の帰り道、閉店してしまったお店の前で少女は子犬と出会う。
 それは、思わぬ再会へと繋がり、過去を思い出すきっかけとなる。
 これは、子犬を中心に始まる、ちょっと不思議な出会いの話。




/// その他 ///
 既刊も2種類持っていきます。
 こちらのイラストは、ましろ.あー。さんです。
 ・ワールド・アドミニストレーター
  販促用(表紙のみ).jpg
 ・君の中の魔法少女
  MagicalGirlInYourHeart_Topp.jpg 

Qtからお手軽にZIPファイルを扱えるQuaZIPの紹介

 この投稿は、Qt Advent Calendar 2016の22日目の投稿です。
 毎年、この日を確保しております。理由は、簡単、冬コミの原稿が終わっているはずだから!
 そして、過去2回はCalendarエレメントがらみの記事を投稿していたので、今年もそうしようかなーと思っていたのですが、変更しました。
 QuaZIPについての日本語の情報ってサラッと探した感じだとないのですが、非常にお手軽なので別にって感じなのかもですけれども、あえて書いてみる事にしました。
 むしろ、QuaZIPのライブラリを使うためのqmakeの設定(*.pro)の方がもしかしたら慣れてない人にはありがたい内容かもしれない、と思った次第です。ガンガンに使っている人にとっては、基礎だと思いますが。

 と言うわけで、QtでいわゆるZIPファイルを「簡単」に扱うにはQuaZIPというライブラリが非常に便利です。

  公式サイト:QuaZIP - Qt/C++ wrapper for ZIP/UNZIP package

 このライブラリ自体がQtで作られているわけなので、使わなくてもZIPファイルを扱えますが、折角のライブラリを使わない手はありません。プロジェクトの事情でも無い限り使いたいところです。
 というわけで、QuaZIP自体のビルドからお手軽な使用方法までを紹介します。
 ちなみに、LGPL 2.1です。


/// 環境 ///
 今回紹介するに当たっての環境は以下の通りです。
 ・QuaZIP 0.7.2
 ・Windows 10(64bit)
 ・Qt 5.7.0
 ・Visual Studio 2015

 試しては居ませんが、Qt4系にも対応しているようです。


/// 準備 ///
 公式サイトからソースコードのアーカイブを入手します。
 それをお好きな作業フォルダに解凍します。
 以下のフォルダ構成で作業を進めることを想定しています。

 作業フォルダ:C:\QtProjects
 解凍フォルダ:C:\QtProjects\quazip-0.7.2


/// ビルド方法 ///
 ビルドはビルド用のフォルダを作るシャドウビルドで行います。
 32bit版もビルドする前提でフォルダ名などをつけていますので、適宜読み替えてください。
 qmakeするときにzlib.h用にインクルードパスを追加する必要があります。この辺りは公式にも環境に合わせて適宜やってねって書いてありますけども。
 PREFIXに指定するパスは、カレントからではなくquazip.proからの相対パスです。

 >"c:\Program Files\Microsoft Visual Studio 14.0\vc\vcvarsall.bat" x86_amd64
 >PATH=%PATH%;C:\Qt\5.7\msvc2015_64\bin

 >mkdir build-quazip-x64
 >cd build-quazip-x64

 >qmake -r ..\quazip-0.7.2\quazip\quazip.pro "PREFIX=..\..\quazip\x64" "INCLUDEPATH+=$$[QT_INSTALL_PREFIX]/include/QtZlib"
 >nmake all
 >nmake release-install debug-install

 以下のファイルができていればOKです。
 .\quazip\x64\lib\quazip.dll
 .\quazip\x64\lib\quazip.lib
 .\quazip\x64\lib\quazipd.dll
 .\quazip\x64\lib\quazipd.lib
 .\quazip\x64\lib\quazipd.pdb
 .\quazip\x64\include\quazip\* h

 Macの場合は、INCLUDEPATHの代わりに「LIBS+=-lz」を追加します。


/// アプリケーションに組み込み ///
 適当なアプリケーションプロジェクトを作成します。
 今回は特にUIどうこう気にしないので、ボタンを押したらテストコードが実行できる感じでいきますので、Qtウィジェットのプロジェクトが簡単で良いと思います。
 プロジェクト名「QuazipExample」で進めます。
 まず、ライブラリを追加する設定を記述するファイルを作成します。

quazip.pri
# for quazip
QUAZIP_DIR = $${PWD}/../quazip
win32:{
    TARGET_PLATROM = $$(PLATFORM)
    equals(TARGET_PLATROM, "X64"):{
        # 64bit
        QUAZIP_DIR = $$QUAZIP_DIR/x64
    }else{
        # 32bit
        QUAZIP_DIR = $$QUAZIP_DIR/x86
    }
}
INCLUDEPATH += $$QUAZIP_DIR/include
CONFIG(debug,debug|release){
    win32: LIBS += $$QUAZIP_DIR/lib/quazipd.lib
}else{
    win32: LIBS += $$QUAZIP_DIR/lib/quazip.lib
}
unix: LIBS += -L$$QUAZIP_DIR/lib/ -lquazip

# for zlib
win32: INCLUDEPATH += $$[QT_INSTALL_PREFIX]/include/QtZlib


# copy library file
win32:{
    CONFIG(debug,debug|release){
        QUAZIP_LIB_PATH=$$QUAZIP_DIR/lib/quazipd.dll
        APP_BUILD_DIR=$$shadowed($${PWD})/debug
    }else{
        win32:QUAZIP_LIB_PATH=$$QUAZIP_DIR/lib/quazip.dll
        APP_BUILD_DIR=$$shadowed($${PWD})/release
    }
    QUAZIP_LIB_PATH ~= s|/|\|gi
    APP_BUILD_DIR ~= s|/|\|gi
}else{
    QUAZIP_LIB_PATH=$$QUAZIP_DIR/lib/libquazip.so.*
    APP_BUILD_DIR=$$shadowed($${PWD})
}
copyquazip.commands = $(COPY_DIR) $$QUAZIP_LIB_PATH $$APP_BUILD_DIR
QMAKE_EXTRA_TARGETS += copyquazip
 後半でカスタムターゲットとして「copyquazip」を作成します。これをプロジェクトの設定のビルドステップに追加すると自動でdllがコピーされるようになります。
 カスタムターゲットのコマンドの「$(COPY_DIR)」はMakefileにこのまま出力されます。そして、Makefileの中でWindowsだとxcopyを使うように設定されていますので、proファイルでプラットフォームごとの設定を書かなくてもすみます。
 この処理は、実はMacは必要ないです。macdeployqtを実行すると勝手にコピーしてくれるのでズルいですw

 続いて、上記のファイルをプロジェクトファイルから読み込まれるようにします。
QuazipExample.pro
    include(quazip.pri)
 プロジェクトの設定は、「ビルドステップ」→「ビルドステップを追加」で「Make」を選択し、「Makeの引数」に「copyquazip」と入力します。
 つまり、
 >make copyquazip
 をやってくれるようにするわけです。

 Qt Creatorからビルドするときや、Qtをインストールしたときに作られるコマンドプロンプトのショートカット「Qt 5.7 64-bit for Desktop (MSVC 2015)」などを使用すると64bit環境のときだけ環境変数として「PLATFORM=X64」が定義されています。これを利用して使用するライブラリのパスを切り替えられるようにしています。
 このファイルの設定について詳しいことを知りたい方は、緑野翁さんの著書「qmake入門」を参照してください。BOOK☆WALKERか今冬のコミケC91(2016/12/29 ビックサイト)のスペース「西み32b」で入手できます。
  BOOK☆WALKER:qmake入門


/// お手軽な圧縮と解凍 ///
 QuaZIPには、簡単お手軽機能をまとめた「JlCompress」クラスがあります。
 特定のファイルを圧縮したり、解凍したりがお手軽ポンです。
 紹介する関数は全てstaticです。

 リファレンス:JlCompress Class Reference

 正直、ここを見れば説明不要って感じですが、一応めげずに紹介します。

bool JlCompress::compressFile(QString fileCompressed,
                              QString file)
fileに指定されているファイルを圧縮します。

bool JlCompress::compressFiles(QString fileCompressed,
                               QStringList files)
filesに登録してあるファイルを圧縮します。
色々な場所に散らばったファイルを選んで圧縮する場合などに使えそうですね。


bool JlCompress::compressDir(QString fileCompressed,
                             QString dir = QString(), 
                             bool recursive = true)
dirに指定したフォルダの中身を圧縮します。
recursiveをfalseにするとサブフォルダの中は無視されます。もちろんフォルダ自体も無視されます。
dirを省略すると、カレントフォルダの中身を圧縮します。
隠しファイルは無視されます。


bool JlCompress::compressDir(QString fileCompressed,
                             QString dir, bool recursive,
                             QDir::Filters  filters)
これもフォルダごと圧縮します。
基本は同じですが、filtersが指定できるので隠しファイルを含められます。
QDir::Hiddenを指定すると隠しも含めて保存されます。
QDir::Filesなどを指定すると空っぽの結果になります。なぜだろう......。


 ここまでが圧縮系(compressHoge)の関数です。これらは、圧縮後のパスに既存のファイルを指定すると上書きします。追加ではありません。
 フォルダは無圧縮でファイルは必ず圧縮されます。一般のアーカイブソフトなどですと何らかの条件で圧縮したりしなかったりしているみたいですが、QuaZIPでは一律圧縮です。


QStringList JlCompress::getFileList(QString fileCompressed)
圧縮されているファイルの一覧を取得します。
この後紹介するファイルを個別で解凍するときに必要になります。

QString JlCompress::extractFile(QString fileCompressed,
                                QString fileName,
                                QString fileDest = QString() 
                                )
fileNameで指定したファイルのみを解凍します。
ZIPファイルの中にフォルダがあれば、それも含めて指定します。getFileListで取得したリストの中から選べばOKです。
解凍先を省略するとカレントフォルダに、解凍されます。
指定するとフォルダ構成を無視して指定したファイル名(パス)で解凍されます。

QStringList JlCompress::extractFiles(QString fileCompressed,
                                     QStringList files,
                                     QString dir = QString() 
                                     )
filesに指定したファイルをZIPファイルの中から解凍します。
dirに指定したフォルダに解凍します。指定したフォルダが存在しないと自動で作成されます。
dirを省略するとカレントフォルダに解凍されます。

QStringList JlCompress::extractDir(QString fileCompressed,
                                   QString dir = QString() 
                                   )
dirに指定したフォルダに解凍します。
無ければ作成されます。

 以上です。簡単ですね。
 今回紹介した関数はすべて圧縮ファイルのパスを文字列で与えていますが、中にはQIODeviceを使用して解凍できる関数もあります。
 何となくご理解いただいていると思いますが、今回紹介したクラスはお手軽なのですが、できることが大味です。個別のファイル単位で圧縮したり無圧縮でパッキングだけしたり、と処理を変えたりするには別のクラスを使用しなければなりません。圧縮したけどかえってサイズが大きくなったとかあるので、理想を言えばいろいろ頑張る必要があります。結局のところケースバイケースなのでご要求に合わせて考えてみてください。なので、細かい話はまた別の機会にしたいと思います。  結局、ライブラリを紹介したいのか、*.proファイルの設定を紹介したいのか謎な感じになりましたが、参考になれば何よりです。

冬コミC91に参加します

 サークル「理ろぐ」は、コミックマーケット91にも参加です。
 今回も創作系のエリアで、「金曜日 西地区 "ひ" 02b」です。

 Webカタログでもサークル情報を公開してます。
  https://webcatalog.circle.ms/Circle/13015363/

 今回は西館でサークルが配置されるのは、西1だけなのでなんだか隔離部屋扱いされているようです。
 何となくまったりした雰囲気になりそうですが、企業エリアへ行った帰りにでも寄ってください(西2~4が企業です)。

 本の内容ですが、女子高生と女子高生の犬を通じたちょっと不思議な出会いのお話の予定!
 小説家になろうにアップしている前半と、これからアップする(予定)の後半に表紙と挿絵を付ける感じです。
  ・雨降りの再会
  ・雨降りの発見

 表紙絵をイラストレーターさんにお願いしてしまった手前、書ききらねばなりません(自ら追い込んだ)。
 毎度、自由気ままに書いている本ですが、なにとぞ。
 スペースに遊びにくてくれるだけでも嬉しいので、まだまだ先のようなあっという間な年末にお会いしましょう!

 あと、
 当日は、新刊と既刊の小説を2種類持っていきます。
 既刊(もう無くなってしまったQt本とか)は、BOOTH(https://relog.booth.pm/)で販売していますのでよろしくお願いします。