【Shell】echo


輸出空白行

$ echo -e "\r" > file.txt
如果 \r 不行的話 可以改成 \n 。
如果有問題的話記得使用  –x  除錯。例如
$ sh –x shell_script

【金流平台】OpenPay


台灣的幾種金流平台先記一下,可直接到超商列印付款繳費,不會留下個人資料。

  • 台灣里 OpenPay(和7-11合作)

【參考】

【Perl】基本用法


有點類似sed/awk,Perl 的強項在於比對字串,比如說想比對檔案內特定的字串你必須要做幾件事

  1. 想列出目錄下的所有檔案。
  2. 讀入檔案內容,並將符合的字串放入hash table。
  3. 用hash table 作比對
  4. 將最後結果存檔後離開

Makefile 的參數

  • Config.in
    FLAGS+=-DDEBUG
  • Makefile
    include Config.in
    all:
            gcc -o hello hello.c ${FLAGS}
  • Hello.c
    #include <stdio.h>
    int main(void)
    {
    #if (DEBUG)
            printf("DEBUG=1\n");
    #else
            printf("DEBUG=0\n");
    #endif
            return 0;
    }

以下簡單記一下 Perl 的簡單用法

  • 變數,Perl只支援三種型態
    • 字串
    • 一維陣列
    • Hash Table
  • 讀取命令列參數 ( $1,$2…)
  • Debug 參數的使用
  • Hash Table 的排序
  • (tbd)

【Qt】Custom shaped dialog


【目的】

  • 顯示不規則視窗。
  • 如果要寫一個手機模擬器的話,一般視窗會有一個 border(中間圖形),
    我們希望能把視窗的外框拿掉,讓使用者有一個更真實的感覺(右邊部分)。
    • 左圖: 原始圖(170x334),拿來當底圖。
    • 中圖: 一般執行結果。
    • 右圖: 使用setMask ,將 Dialog 外框拿掉。
    • 原本手機有四顆按鈕(Verizon字串下方),我們也在這邊實現第一顆按鈕的功能。
      你可以看到右圖和左圖下方第一顆按鈕是不一樣的,當使用者按下第一顆按鈕,則會關掉視窗。
      按鈕外型通常會顯示跟左圖第一個按鈕一樣, 但此處不特別作處理。
    • 圖形由網路隨機抓取示範,本人並非圖形作者。

      image image image 

【環境】

  • Windows Vista。

【程式】
創造一個Dialog。放置一個 pushButton。 並加入下面的程式碼。其中重要的部分如下。

  • dialog.cpp ( 使用 setMask 來遮罩出所需圖形)
    Dialog::Dialog(QWidget *parent) :
        QDialog(parent),
        ui(new Ui::Dialog)
    {
      this->setGeometry(0, 0, 170, 334);
      this->setStyleSheet("background-image: url(background.jpg)");
      this->setMask(QRegion(0, 0, 170, 334, QRegion::Rectangle));
      //this->setAcceptDrops(true);
      //this->setAutoFillBackground(true);
      //setWindowOpacity(1);
      ui->setupUi(this);
    }
    void Dialog::on_pushButton_clicked()
    {
      close();
    }
  • dialog.h ( 當使用者按下第一顆按鈕,將整個應用程式關閉)
    class Dialog : public QDialog {
        Q_OBJECT
    ...
        void on_pushButton_clicked();
    };
  • dialog.ui (此處直接定義出 pushButton 位置)
    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0">
     <class>Dialog</class>
     <widget class="QDialog" name="Dialog">
      <property name="geometry">
       <rect>
        <x>0</x>
        <y>0</y>
        <width>397</width>
        <height>489</height>
       </rect>
      </property>
      <property name="windowTitle">
       <string>Emulator</string>
      </property>
      <widget class="QPushButton" name="pushButton">
       <property name="geometry">
        <rect>
         <x>18</x>
         <y>305</y>
         <width>30</width>
         <height>10</height>
        </rect>
       </property>
       <property name="text">
        <string/>
       </property>
      </widget>
     </widget>
     <layoutdefault spacing="6" margin="11"/>
     <resources/>
     <connections/>
    </ui>
    結果 123

【結果】

  • 同上圖最右方。

【問題】

  • 如何產生更真實效果,如把四個角落的邊都修成圓弧形(RoundRectangle)或更不規則外框。
    A: 由於QRegion目前只支援Rectangle/Ellipse,並沒有支援RoundRect。
    如需實現更不規則外框,請參考 Qt | Tux 這個範例。以下提示程式重點部分。
    主要就是把圖形的輪廓遮罩成視窗的外框。
    main.c (圖片來至 http://upload.wikimedia.org/wikipedia/commons/3/3e/Tux-G2.png
    #include <QPixmap>
    #include <QPalette>
    #include <QBrush>
    #include <QFile>
    #include <QBitmap>
    
    int main(int argc, char *argv[])
    {
      QApplication a(argc, argv);
      Dialog w;
      QString fn = "../tux.png";
    
      if (!QFile::exists(fn))
      exit(1);
    
      QPixmap pixmap("../tux.png");
      QPalette palette;
      palette.setBrush(w.backgroundRole(), QBrush(pixmap));
      w.setPalette(palette);
      w.setFixedSize( pixmap.size() );
      w.setMask(pixmap.mask());
      w.show();
      return a.exec();
    }
    呈現結果 (底下的小企鵝就是整個不規則視窗)
    image
  • 因為外框遮罩掉後,導致無法移動視窗位置。如何實現拖曳功能。
    A: 需自行定義 mousePressEvent/mouseMoveEvent。
  • 除了 Dialog ,如何產生不規則外型元件(如不規則的 pushButton)。
    • 直接設定 Icon,將 Text 拿掉 。
    • 設定 Flat 。
    • 將 pushButton size 設成跟 Icon 大小一樣。
  • 以上方式和下面方式有何不同?
    setWindowFlags(Qt::FramelessWindowHint);

【參考】

【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" 

【其它】

【參考】

 

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