【Qt】XML


【目的】

  • 讀取 Google Weather。

【原理】

  • Google Weather 提供多樣化的API查詢方式
  • Xml 結點與資料(1)
    • 透過 WMHelp XMLPad Pro EditionXMLmind XML Editor檢視。
      明顯可以看出左邊的圖分類的非常清楚。
      imageimage
    • 同事試過亦可由 FreeMind 讀取XML 資料(透過 PS Pad 整理縮排後)
  • Xml 結點與資料(2),以 2010年 9月 29 日(禮拜三)為例
    • xml_api_reply version=1 (第一層)
      • weather module_id=0 tab_id=0 mobile_row=0 mobile_zipped=1 row=0 section=0
        • forecast_information 預測資料 (第三層)
          • city data=taipei (第四層)
          • postal_code data=taipei
          • latitude_e6 data=
          • forecast_date=2010-09-29
          • current_date_time data=2010-09-29 14:00:00 +0000
          • unit_system data=SI
        • current_conditions 目前狀況 ( 猜測是代表目前時間,比如說 11:00am時的天氣)
          • condition data=多雲
          • temp_f data=79
          • temp_c data=26
          • humidity data=濕度: 86%
          • icon data=/ig/images/weather/cloudy.gif
          • wind_condition data=風向: 公里/小時
        • forecast_conditions 預測狀況(這周的天氣預測)
          • day_of_week data=週三
          • low data=23
          • high data=28
          • icon data=/ig/images/weather/rain.gif
          • condition data=多雲時陰短暫雨
        • forecast_conditions 預測狀況
          • day_of_week data=週四
          • low data=23
          • high data=29
          • icon data=/ig/images/weather/rain.gif
          • condition data=多雲短暫雨
        • forecast_conditions 預測狀況
          • day_of_week data=週五
          • low data=24
          • high data=32
          • icon data=/ig/images/weather/cloudy.gif
          • condition data=多雲
        • forecast_conditions 預測狀況
          • day_of_week data=週六
          • low data=24
          • high data=33
          • icon data=/ig/images/weather/cloudy.gif
          • condition data=多雲
  • Xml 格式資料可透過幾種方式讀取
    • SAX(Simple API for XML)  XML資料唯獨,讀取速度較快
    • DOM(Document Object Model)  可更新 XML 資料
    • Pull Parse(Java推薦方式,目前Qt 不支援)

【程式】

  1. main.c  一樣用之前的 QHttp 範例,main.c 中有兩個地方需特別注意
    1. 抓取資料的網址改成由原本的zh_tw以us顯示,方便處理
      http://www.google.com/ig/api?hl=us&weather=taipei
    2. 抓取網頁成功之後的callback function binding 到 show_weather
      int main(int argc, char *argv[])
      {
        QApplication a(argc, argv);
        Dialog w;
        w.show();
      
        HttpGet getter;
        QUrl url("http://www.google.com/ig/api?hl=us&weather=taipei");
        getter.downloadFile(QUrl(url));
        QObject::connect(&getter, SIGNAL(finished()), &w, SLOT(show_weather()));
      
          return a.exec();
      }
  2. 由於我們不需更改資料,所以以 SAX 先作實驗
    (tbd)

  3. 透過 DOM 的方式 (通常可用 QTreeWidgetItem搭配遞迴方式載入,此處使用苦工方式一個一個讀出)

    1. dialog.h

      #ifndef DIALOG_H
      #define DIALOG_H
      
      #include <QDialog>
      #include <QUrl>
      #include "HttpGet.h"
      #include <iostream>
      #include <QtXml>
      #include <QFile>
      
      namespace Ui {
          class Dialog;
      }
      class Dialog : public QDialog {
          Q_OBJECT
      public:
          Dialog(QWidget *parent = 0);
          ~Dialog();
      protected:
          void changeEvent(QEvent *e);
      private:
          Ui::Dialog *ui;
      private slots:
          void show_weather();
          void show_forecast_information(const QDomNode node3);
          void show_current_conditions(const QDomNode node3);
          void show_forecast_conditions(const QDomNode node3);
      };
      
      #endif // DIALOG_H
    2. dialog.cpp

      void Dialog::show_weather()
      {
          QDomDocument doc;
          QFile file("api");
          QString errorStr;
          int errorLine;
          int errorCol;
          if(!doc.setContent(&file,true,&errorStr,&errorLine,&errorCol)){
              qDebug() << "Unable to open the file";
              return;
          }
          file.close();
      
          QDomElement root = doc.documentElement();
          if (root.tagName() != "xml_api_reply")
              return;
      
          QDomNode node2 = root.firstChild();
          if(node2.toElement().tagName() == "weather")
          {
              QDomNode node3 = node2.firstChild();
                 while (!node3.isNull()){
                  qDebug() << "-" << node3.toElement().tagName();
                  if(node3.toElement().tagName() == "forecast_information")
                      show_forecast_information(node3);
                  else if (node3.toElement().tagName() == "current_conditions")
                      show_current_conditions(node3);
                  else if (node3.toElement().tagName() == "forecast_conditions")
                      show_forecast_conditions(node3);
                  node3 = node3.nextSibling();
                 }
              }
      }
      void Dialog::show_forecast_information(const QDomNode node3)
      {
          QDomNode node4 = node3.firstChild();
          while (!node4.isNull()){
              if(node4.toElement().tagName() == "city")
                  qDebug() << "    +city:" << node4.toElement().attribute("data");
              else if(node4.toElement().tagName() == "postal_code")
                  qDebug() << "    +postal_code:" << node4.toElement().attribute("data");
              else if(node4.toElement().tagName() == "latitude_e6")
                  qDebug() << "    +latitude_e6:" << node4.toElement().attribute("data");
              else if(node4.toElement().tagName() == "forecast_date")
                  qDebug() << "    +forecast_date:" << node4.toElement().attribute("humidity");
              else if(node4.toElement().tagName() == "current_date_time")
                  qDebug() << "    +current_date_time:" << node4.toElement().attribute("data");
              else if(node4.toElement().tagName() == "unit_system")
                  qDebug() << "    +unit_system:" << node4.toElement().attribute("data");
              node4 = node4.nextSibling();
          }
      }
      void Dialog::show_current_conditions(const QDomNode node3)
      {  
          QDomNode node4 = node3.firstChild();
          while (!node4.isNull()){
              if(node4.toElement().tagName() == "condition")
                  qDebug() << "    +condition:" << node4.toElement().attribute("data");
              else if(node4.toElement().tagName() == "temp_f")
                  qDebug() << "    +temp_f:" << node4.toElement().attribute("data");
              else if(node4.toElement().tagName() == "temp_c")
                  qDebug() << "    +temp_c:" << node4.toElement().attribute("data");
              else if(node4.toElement().tagName() == "humidity")
                  qDebug() << "    +humidity:" << node4.toElement().attribute("humidity");
              else if(node4.toElement().tagName() == "icon")
                  qDebug() << "    +icon:" << node4.toElement().attribute("data");
              else if(node4.toElement().tagName() == "wind_condition")
                  qDebug() << "    +wind_condition:" << node4.toElement().attribute("data");
              node4 = node4.nextSibling();
          }
      }
      void Dialog::show_forecast_conditions(const QDomNode node3)
      {
          QDomNode node4 = node3.firstChild();
          while (!node4.isNull()){
              if(node4.toElement().tagName() == "day_of_week")
                  qDebug() << "    +day_of_week:" << node4.toElement().attribute("data");
              else if(node4.toElement().tagName() == "low")
                  qDebug() << "    +low:" << node4.toElement().attribute("data");
              else if(node4.toElement().tagName() == "high")
                  qDebug() << "    +high:" << node4.toElement().attribute("data");
              else if(node4.toElement().tagName() == "icon")
                  qDebug() << "    +icon:" << node4.toElement().attribute("data");
              else if(node4.toElement().tagName() == "condition")
                  qDebug() << "    +condition:" << node4.toElement().attribute("data");
              node4 = node4.nextSibling();
          }
      }
    3. 結果
      - "forecast_information" 
          +city: "taipei" 
          +postal_code: "taipei" 
          +latitude_e6: "" 
          +forecast_date: "" 
          +current_date_time: "2010-09-29 23:00:00 +0000" 
          +unit_system: "US" 
      - "current_conditions" 
          +condition: "Clear" 
          +temp_f: "82" 
          +temp_c: "28" 
          +humidity: "" 
          +icon: "/ig/images/weather/sunny.gif" 
          +wind_condition: "Wind:  mph" 
      - "forecast_conditions" 
          +day_of_week: "Thu" 
          +low: "75" 
          +high: "87" 
          +icon: "/ig/images/weather/rain.gif" 
          +condition: "Rain" 
      - "forecast_conditions" 
          +day_of_week: "Fri" 
          +low: "77" 
          +high: "89" 
          +icon: "/ig/images/weather/cloudy.gif" 
          +condition: "Cloudy" 
      - "forecast_conditions" 
          +day_of_week: "Sat" 
          +low: "77" 
          +high: "91" 
          +icon: "/ig/images/weather/cloudy.gif" 
          +condition: "Cloudy" 
      - "forecast_conditions" 
          +day_of_week: "Sun" 
          +low: "73" 
          +high: "86" 
          +icon: "/ig/images/weather/rain.gif" 
          +condition: "Rain" 

【其它】

【參考】

【Qt】Json parser


目前有許多種選擇。但須注意是否完全支援UTF8。

  1. qt-json http://nilier.blogspot.com/2010/08/json-parser-class-for-qt.html
  2. Qjson http://qjson.sourceforge.net/
  3. JsonQt http://gitorious.org/JsonQt/

目前採用第一個方式,因為第一個方式只需要在原始專案中加入兩個檔案,看起來較為方便。

【目的】

以 AJAX Language API for Translation and Detection 為範例,Translation API 所回傳的結果就是 Json 格式。
假設我們送出下面命令給 Google Translation ,

http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=hello&langpair=en|ru  
所回傳的結果會是
{"responseData": {"translatedText":"привет"}, "responseDetails": null, "responseStatus": 200}
看起來的結構會像是下面圖形,請住義最後 hello 翻譯成俄文的字串會在 responseData的translatedText。

image

【程式】

下面只擷取重要程式,基本上UI會有一個 push button 用來顯示從 Json 抓出來的字串。 
#include <qDebug>
#include "json.h"

QString json="{\"responseData\" : {\"translatedText\":\"привет\"}, \
               \"responseDetails\" : null, \
               \"responseStatus\" : 200}";

bool ok;
QVariantMap result = Json::parse(json, ok).toMap();
if(!ok) {
    qFatal("An error occurred during parsing");
    exit(1);
}

QVariantMap responseData = result["responseData"].toMap();
QString translatedText= responseData["translatedText"].toString();

ui->pushButton->setText(QString::fromUtf8(translatedText.toStdString().c_str()));
qDebug() << "translatedText:" << QString::fromUtf8(translatedText.toStdString().c_str());
qDebug() << "responseDetails:" << result["responseDetails"].toBool();
qDebug() << "responseStatus:" << result["responseStatus"].toInt();

【結果】

 image

【問題】

  • 程式也將結果送到 QDebug(),但不知為何привет會變成亂碼,但如果印出中文是沒問題的。
    image

【上面三種方式的個別補充說明】

  1. JSON parser class for Qt
    http://nilier.blogspot.com/2010/08/json-parser-class-for-qt.html
  2. Qjson http://qjson.sourceforge.net/usage.html
  3. JsonQt
    http://git.fredemmott.co.uk/?p=JsonQt;a=blob;f=tests/README.txt;h=4ebcf735ccbff8556914ed687b27f065dfb4a229;hb=HEAD

【其他】

【Qt】HTML5


Qt 利用 QWebKit 來顯示 HTML 網頁,目前還在研究 Html5  上面的支援程度。
目前可以確定audio/video都沒有支援。

【Demo】

【Lingoes】靈格斯詞霸


Lingoes http://www.lingoes.net/

【目的】

  • 安裝英翻中詞典。
  • 俄翻英。

【環境】

  • Windows Vista。

【步驟】

  1. 下載並安裝 Lingoes。
    image 
  2. 安裝完畢之後就可直接使用。不過不知為何,螢幕取詞 功能動作看起來時有時無,所以我順便
    勾選了剪貼簿取詞 功能。將單字複製到剪貼簿,就會出現翻譯。
    image
  3. 建議下載繁體版的牛津英語詞典。請打開 Lingoes | 辭典管理 | 從Lingoes下載辭典。
    image
  4. 就會連到下載頁面,此時請選 牛津英語詞典 繁體版。下載完後直接打開就會匯入該詞典。
    image
  5. 建議 辭典安裝清單、索引組和取詞組 留下 牛津高階英漢雙語辭典 即可。
    image
  6. 就如同第二個步驟的附圖一樣,可以看到英翻中的結果。
  7. 俄翻英的話目前提供下面這些,請由下面的Hyperlink去找。
    http://www.lingoes.net/en/dictionary/index.html
     image

【ComicShelf】颱風天在家看漫畫


ComicShelf http://www.comicshelf.com/cht/index.php

除了好讀網站(http://www.haodoo.net/)外,另外一個不錯的精神糧食來源。

【使用】

  1. 由於是綠色軟體,下載解壓後直接點選 ComicShelf.exe。
    初始化設置,語言可選 中文(繁體)
    image
  2. 假設要搜尋 Jo Jo 冒險野郎 的話,進入 漫畫瀏覽器 | 漫畫搜索 ,在 漫畫名 這邊打入 Jo
    這個關鍵字,就會看到 搜索站 所列出的結果。這邊看到找到 JOJO奇妙冒險這部。
    image 

【其它】

  • 新動慢速度還蠻快的。

【EPUB】電子書


EPUB http://zh.wikipedia.org/zh-tw/EPUB
EPUB OPF電子出版品結構資料中文規範書v1.0 http://www.oss.org.tw/getfile.php?id=01

【軟體】

【童書或繪本】

【參考】

【Microsoft Fix it】


Microsoft Fix it http://support.microsoft.com/fixit#tab0

【環境】

  • Vista

【發生狀況】

  • 有一陣子都沒更新電腦了,前幾天要 Windows Update 突然發現好久一陣子都停在進度 0。
    image

【步驟】

【IPad】Object-C


【目的】

  • 簡單示範 Object C

【步驟】

  1. tbd

【參考】

【API Hook】Get Word


【參考】

【Google】GPS


GPS Location

【目的】

  • 從Google Map 獲取GPS座標。
  • 驗證GPS座標。

【步驟】

  1. 首先下載並安裝 GPS Location ,我把這Gadget裝在Opera。IE/Chrome…應該都適用。
  2. 先在Google Map選擇好地點。以台北市立體育館某處的公車站牌為例。
    image
  3. 進入 我的地圖 | GPS Location
    image
  4. 按滑鼠左鍵則會出現座標的經緯度。目前是 GPS: 25.049194, 121.549215
     image
  5. 將得到的座標回填 Google Map 的搜尋欄,就會指出剛剛的位置,可提供驗證。
    image
  6. 一樣的,以下網址也是指到一樣的地方。
    http://maps.google.com/maps?q=25.049194, 121.549215
  7. 若以黃石公園在Wiki上面的座標為例,直接輸入Google Map的搜尋欄也可以得到正確位置。
    image
    image
  8. 所以不管是輸入黃石公園的座標 44°36′0″N 110°30′0″W 或直接輸入44.360, -110.300都可以得到正確位置。

【其它】

【參考】

 

Ed32. Copyright 2008 All Rights Reserved Revolution Two Church theme by Brian Gardner Converted into Blogger Template by Bloganol dot com