Runner in the High

技術のことをかくこころみ

Qtでメニューにファビコンを表示したいときのメモ

ファビコン!
 

タイトル通り。
メニューにかっこよくファビコンを表示したい!という人のためのメモ。
「そんな人間がどれだけいんの?」というツッコミはなしで。。。

QIcon MainWindow::getFavicon(QString url)
{
QEventLoop wait;
QPixmap icon;
QImage img;
QUrl request;

request.setUrl(QString("http://favicon.hatena.ne.jp/?url=%1").arg(url));

netReq = new QNetworkRequest(request);
netRep = netMan->get(*netReq);
connect(netMan, SIGNAL(finished(QNetworkReply*)), &wait, SLOT(quit()));
wait.exec();

img = QImage::fromData(netRep->readAll(), "PNG");
icon = QPixmap::fromImage(img.convertToFormat(QImage::Format_RGB32));

return icon;
}

ファビコンを取得するAPIはてなの非公式のものを使う。

http://favicon.hatena.ne.jp/?url=[URL]

いかんせん非公式なものなのでいつ使えなくなるかはわからない。
でも取得の精度も高いしなくならないといいな。
ちなみに指定するURLにはスキームをちゃんと指定しておかないとまともに動かないので注意。

9、10行目あたりで急に出現するnetRepとかnetReqとかはほとんどQNetwork系の変数。
QNetworkRequestとかQNetworkReplyとか調べればたぶんすぐ分かる、はず。
取得の際にはQEventLoopを用いてこの関数内だけで完結させる。
(排他処理とかがちゃんとしてないのでそこら辺は直したほうがいいかも)

ファビコンのデータが取得できたら上のコードのようにQIconへ変換する。
QImage::convertToFormatにてFormatを指定する際には
QImage::Format_RGB32QImage::Format_Indexed8が指定できる。
取得されるデータは前者を使うと高品質、後者だと低品質なものになる。
他にも指定するともしかしたらなにかが起きるんだろうけどそれは未検証()

void MainWindow::setMenuIcon(void)
{
ui->actionGoogle->setIconVisibleInMenu(true);
ui->actionGoogle->setIcon(getFavicon("http://www.google.co.jp"));

ui->actionAmazon->setIconVisibleInMenu(true);
ui->actionAmazon->setIcon(getFavicon("http://www.amazon.co.jp"));

ui->actionBing->setIconVisibleInMenu(true);
ui->actionBing->setIcon(getFavicon("http://www.bing.com"));

ui->actionYahoo->setIconVisibleInMenu(true);
ui->actionYahoo->setIcon(getFavicon("http://www.yahoo.co.jp"));
}

で、まあこんな感じでひとつひとつメニューアイテムにアイコンをセットしていく。
actionGoogleとかactionBingとかはご覧の通りどれもQActionの変数。
このときにsetIconVisibleInMenuでちゃんと表示するように設定するのを忘れないこと。
以外にこの存在を知らなくてずっと悩んでる人がQtCentreには結構いたような気がする。

PNG形式のファイルを取得してQIconに変換するっていう処理だけで正直結構ハマった。
加えて、あんまりQIconとかQPixmapの変換に関する詳しい資料がネットにない。
ここらへんはまたいつか記事にしてまとめないといかんね。

今回のソースファイルは全てGitHubにて公開してあります
IzumiSy/qfavicon