2014年4月7日月曜日

QtプロジェクトからVisual StudioやXcodeのプロジェクトを作成

Qt .proファイルからIDEのプロジェクトファイルを作成

QtにはQt Creatorという開発環境があります.Qt Creatorでユーザーインターフェイスのデザインからアルゴリズムコーディングまでの全てを実装することも出来ますが,私は,Qt CreatorでQtプロジェクトの作成と設定のみを行い,その後はWindowsではVisual Studio,MacではXcodeなど使い慣れた統合開発環境で開発を行っています.Qt CreatorではかんたんにQtに関する設定が出来る上,クロスプラットフォームである利点を活かせるからです.

まずはQt CreatorでQtプロジェクトを作成する

.proファイルが作成されていますね.ここで依存ライブラリなどの設定も行います.

インクルードパスを追加 (Windows/Macそれぞれで)

INCLUDEPATHとDEPENDPATHにインクルードするためのディレクトリへのパスを追加します
# Windows向けにincludeディレクトリを追加する例
win32: INCLUDEPATH += C:/OpenCV/opencv-2.4.6/build/x64/vc10/include
win32: DEPENDPATH += C:/OpenCV/opencv-2.4.6/build/x64/vc10/include

# Mac向けに追加する例
macx:INCLUDEPATH += /usr/local/Cellar/opencv/2.4.6.1/include
macx:DEPENDPATH += /usr/local/Cellar/opencv/2.4.6.1/include

依存ライブラリを追加 (Windows/Macそれぞれで)

LIBSに"-Lライブラリのディレクトリへのパス", "-l追加するライブラリファイル"で追加するわけですね.
# Windows向けに追加する例(1行目がリリースモード,2行目がデバッグモード)
win32: CONFIG(release, debug|release): LIBS += -LC:/OpenCV/opencv-2.4.6/build/x64/vc10/lib/ -lopencv_core246 -lopencv_highgui246 -lopencv_imgproc246
else: win32:CONFIG(debug, debug|release): LIBS += -LC:/OpenCV/opencv-2.4.6/build/x64/vc10/lib/ -lopencv_core246d -lopencv_highgui246d -lopencv_imgproc246d

# Mac向けに追加する例
macx: LIBS += -L/usr/local/Cellar/opencv/2.4.6.1/lib/ -lopencv_core -lopencv_highgui -lopencv_imgproc

ビルド時のシンボルを定義

ビルド時のシンボルも定義してみます.
# デバッグビルド時は_Debugを定義する
CONFIG(debug, debug|release): DEFINES += _Debug

Visual Studioのプロジェクトを生成

Qtプロジェクトファイル(.pro)があるディレクトリにて次のコマンドを実行します.
# Visual C++ 2010
$qmake -spec win32-msvc2010 -tp vc

# Visual C++ 2012
$qmake -spec win32-msvc2012 -tp vc

Xcodeプロジェクトを生成

Qtプロジェクトファイル(.pro)があるディレクトリにて次のコマンドを実行します.
$qmake -spec macx-xcode

総括

Qt CreatorでQtプロジェクトの作成・設定を行ってqmakeコマンドを使って各統合開発環境のプロジェクトファイルを作成しました.クロスプラットフォームで使い慣れたツールを使って開発をするときに便利だと感じています.

2014年4月2日水曜日

JavaScript + jQuery + CSS で画像を適正サイズに切り取って中央配置する

JavaScriptで画像のトリミング

HTMLやCSSのwidth, heightプロパティを用いれば画像の表示サイズが設定できるのは言うまでもありませんが,画像の伸縮はそのままで画像を切り取ることでサイズ調整を行います.どんなサイズの画像でも指定したサイズに中央を残して切り取れるようにしました.

サンプル


内容

HTML

切り取り対象の画像にはonLoadにあとで作成するclipImageFitSize()関数を実行するように設定します.
<h2>元画像</h2>
<div><img src="image.jpg" alt="Source Image"></div>

<h2>切り取り後</h2>
<div class="container">
<img src="image.jpg" alt="Trimmed Image" onLoad="clipImageFitSize(this,
240, 200, 'center', 'middle')">
</div>

CSS

JavaScriptからCSSのclipプロパティを設定することで切り取りを実現するため,画像タグimgはpositionプロパティをabsoluteにする必要があります.
div.container img {
    /** absoluteに設定する必要がある.  */
    position: absolute;
}

JavaScript

JavaScriptではjQueryを使用します.jQueryからclipプロパティの値を設定します.clipプロパティについてはTag Indexの該当ページでわかりやすく解説されています.対象画像のサイズを取得して,トリミングする領域を算出しています.
<script type="text/javascript" src="jquery-1.4.2.js"></script>
<script type="text/javascript">
/**
* 画像を指定のサイズになるように切り抜るCSSを付与します.画像はposition: absoluteで無ければイケません.
* @param image {Object} 対象となる画像要素
* @param width {Number} 切り取り後の横幅
* @param height {Number} 切り取り後の縦幅
* @param positoinX 切り取り開始位置X(値,もしくは文字列left, center, right)
* @param positionY 切り取り開始位置Y(値,もしくは文字列top, middle, bottom)
*/
var clipImageFitSize = function(image, width, height, positionX, positionY) {
 var top, left, right, bottom;
 if(typeof(positionX) == "Number") {
  left = positionX;
  right = width + positionX;
 } else if(positionX == "left") {
  left = 0;
  right  = width;
 } else if(positionX == "center") {
  left = image.width / 2 - width / 2;
  left = (left < 0 ? 0 : left);
  right = left + width;
 } else if(positionX == "right") {
  left = width;
  right = 0;
 }

 if(typeof(positionY) == "Number") {
  top = positionY;
  bottom = height + positionY;
 } else if(positionY == "top") {
  top = 0;
  bottom = height;
 } else if(positionY == "middle") {
  top = image.height / 2 - height / 2;
  top = (top < 0 ? 0 : top);
  bottom = top + height;
 } else if(positionY == "bottom") {
  top = height;
  bottom = 0;
 }
 right = (right > image.width ? image.width : right);
 bottom = (bottom > image.height ? image.height : bottom);
 var cssStr = "rect(" + String(top) + "px " + String(right) + "px " + String(bottom) + "px " + String(left) + "px)";
 $(image).css("clip", cssStr);
 $(image).css("left", String(-1 * left) + "px");
 $(image).css("top", String(-1 * top) + "px");
 moveToCenter(image);
}
最後のmovoToCenter()関数で画像が親要素の中央に来るように調整します.
/**
* 要素を親要素の中央に配置します.position: absoluteで無ければイケません.
* @param element {Object} 対象のオブジェクト
*/
var moveToCenter = function(element) {
 var parent = $(element).parent().get(0);
 var left = $(parent).width() / 2 - $(element).width() / 2;
 var top = $(parent).height()  / 2 - $(element).height()  / 2;
 $(element).css("left", left);
 $(element).css("top", top);
}

予めトリミングした画像を用いれば,これを実装する必要はありませんが,元サイズの分からない画像をクライアント側でトリミングするときに使うことにします.
それでは..


2014年4月1日火曜日

テストのために,DebianにWordpressをセットアップしてみた.

Raspberry Pi上のDebian Linux

現在,私はRaspberry Pi上でDebian Linuxを稼働させています.お手頃価格で省エネで良いと思っています.
さて,そんなDebianで,Apache + PHP5 + MySQL をベースにしてWordpressをセットアップしてみました.公開用ではなく,Webサイトのテスト用であったため通常の80番ポートではなく,81番ポートでの運用のために設定を行いました.
至って普通のやり方であるため特に新規性はありませんのであしからず..

要項

  • バックエンドにApache2, MySQL
  • 81番ポートでの運用
  • /var/www81/wordpressに設置
  • http://localhost:81/wordpressのURLアクセス

必要事項のインストール

apt-getで必要な物をまずインストールしました.私の環境下では既にapache2とmysqlはインストール済みであったため,PHPのインストールです.
sudo apt-get install php5 php5-mysql

もし,apache2やmysqlがインストール済みでなければ併せてインストールする必要があります.
sudo apt-get install apache2 mysql mysql-server
なお,Apache2やMySQLの基本的な初期設定については,ここでは割愛します.

Apacheの設定

80番ポートではなく,81番ポートに設置するためVirtual Hostで81番向けのサイトを設定しました.
まず,公開用のファイルを設置するディレクトリを作成します.ついでにパーミッションも設定しました.
sudo mkdir /var/www81
sudo chown www-data:www-data -R /var/www81
sudo chmod g+w -R /var/www81

/etc/apache2/sites-avairableに次のようなファイルを作成しました.ファイル名はとりあえずdefault-81にしました.
Listen 81
<VirtualHost *:81>
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www81
        <Directory />
                   Options FollowSymLinks
                   AllowOverride None
        </Directory>
        <Directory /var/www81/>
                Options Indexes FollowSymLinks MultiViews ExecCGI
                AllowOverride None
                Order allow,deny
                allow from all
        </Directory>
        ErrorLog ${APACHE_LOG_DIR}/error81.log
</VirtualHost>
Options にExecCGIを記述してCGIの実行を許可していています.
Apache2に81番ポートのVirtualHostを有効化して,リセットします.
sudo a2ensite default-81
sudo service apache2 restart

MySQLの設定

管理者権限でMySQLにログインして,データベースを作成します.データベースの文字コードはUTF-8になっています.
mysql> create database wordpress_db;

Wordpressのインストールと設定

ターミナルから

Wordpressをダウンロードして,解凍,該当ディレクトリに設置(インストール)します.今回は/var/www81/wordpressとしました.
wget http://wordpress.org/latest.tar.gz
tar -xvzf latest.tar.gz
mv wordpress /var/www81
tarコマンドで展開するとwordpressディレクトリが現れます.それを/var/www81にコピーしました.今回はディレクトリ名をwordpressのままにしましたが,適宜好きな名前に変えましょう.
それではwordpressの設定を行います.設定ファイルのサンプルから設定ファイルwp-config.phpを変更します.
cd /var/www81/wordpress
cp wp-config-sample.php wp-config.php
emacs wp-config.php # 好きなエディタで開く
wp-config.phpを次のように変更します.
/** The name of the database for WordPress */
define('DB_NAME', 'wordpress_db');

/** MySQL database username */
define('DB_USER', '#ユーザー名');

/** MySQL database password */
define('DB_PASSWORD', 'パスワード');

/** MySQL hostname */
define('DB_HOST', 'localhost');

/** Database Charset to use in creating database tables. */
define('DB_CHARSET', 'utf8');

/** The Database Collate type. Don't change this if in doubt. */
define('DB_COLLATE', '');
データベース名(DB_NAME)やユーザー名,パスワードなどは適宜変えてください.
次の” Authentication Unique Keys and Salts.”の項目は,秘密鍵を登録するようですね.https://api.wordpress.org/secret-key/1.1/salt/ で鍵を作成できるようですので,これをそのままコピーしておきましょう.

Webブラウザから

インストールを完了させるために,http://サーバのアドレス:81/wordpress/wp-admin/install.phpにアクセスしましょう.:81は81番ポートだからですね.
こんなページが現れました.
サイトのタイトル,ユーザー名,パスワード,メールアドレスを入力して次に行きましょ,これでインストールは一旦完了のようです.

わかりやすいWikiを参考に

基本的にここの焼き直しになってしまいましたが...
http://wpdocs.sourceforge.jp/WordPress_のインストール

2014年3月26日水曜日

QValidatorとboost::functionを使って関数型言語みたいに入力値のチェックを行うようにしてみた.

QValidatorとboost::functionの組み合わせ

はじめに

GUIツールキットのQtでGUIを作成したとき,QLineEditなどの入力フォームからの入力値が適切であるかどうかを判定する必要があります.このとき,QValidatorの機構を用いると入力値が適切であるかのチェックが簡単になります.これは前回「Qt validator 入力フォームの値をチェックする」で実装しました.

今回はboost::functionを利用して,チェック用の関数を個別に指定できるバリデートクラスを作成してみました.

関数を引数にとって判定を行うクラス

int型を対象としたQLambdaIntValidateクラスとdouble型を対象としたQLambdaDoubleValidateクラスの2つを書いてみました.この2つはint型を扱うのか,double型を扱うのかの違い意外に差異はありません.それぞれQIntValidator及びQDoubleValidatorを継承しています.
(関数を受け取るためクラスのためラムダ式のラムダから命名したのですがもっと名前ないかな~~ww)

QLambdaIntValidator

#include <qintvalidator>
#include <qdoublevalidator>
#ifndef Q_MOC_RUN
#include <boost function.hpp>
#endif

class QLambdaIntValidator: public QIntValidator {
    Q_OBJECT
    using QIntValidator::validate;
public:
    explicit QLambdaIntValidator(QObject* parent = 0);
    explicit QLambdaIntValidator(int min, int max, QObject* parent = 0);
    
    /**
     * @param function 確認用関数
     */
    explicit QLambdaIntValidator(boost::function<bool (int)> function, QObject* parent = 0);
    
    /**
     * @param function 確認用関数
     */
    explicit QLambdaIntValidator(boost::function<bool (int)> function, int min, int max, QObject* parent = 0);
    
    /**
     * int型のチェックに加え,チェックに用いる関数を設定します.
     * @param funciton チェックに用いる関数
     */
    void setValidateFunction(boost::function<bool (int)> function);
    
    /**
     * 指定した関数がfalseを返した場合,どのステートを返すかを指定します.
     * @param state false時に用いるステート
     */
    void setStateWhenFalse(QValidator::State state);
    
    /**
     * 入力値をチェックします.
     * @param text
     * @param pos
     */
    virtual QValidator::State validate(QString& text, int& pos) const;
    
private:
    boost::function<bool (int)> validateFunc;
    QValidator::State falseState;
};
プライベートメンバ変数のvalidateFuncにチェック用の関数を代入します.チェック用メソッドであるvalidate()の中で実行されます.
falseStateはvalidateFuncの戻り値がfalseのとき,QValidator::Stateの戻り値をInvalidにするかIntermediateにするかを指定します.
validate()メソッドの中身を以下に記述します.親クラスのvalidate()を実行後,戻り値がInvalidでなければ,指定されたチェック関数を行います.
QValidator::State QLambdaDoubleValidator::validate(QString &text, int &pos) const {
    QIntValidator::State state = QDoubleValidator::validate(text, pos);
    if(state != QValidator::Invalid && !validateFunc.empty()) {
        bool isOk;
        double num = text.toDouble(&isOk);
        state = (validateFunc(num) && isOk ? QValidator::Acceptable : falseState);
    }
    return state;
}

使い方(使う人いないかもだけど..)

チェック用関数を別途定義

/**
* チェック関数の例
* @param num 調べる値
* @return true=偶数, false=奇数
*/
bool isEvenNumber(int num);

このチェック関数を指定します.
QLambdaIntValidator* validator = new QLambdaIntValidator(&isEvenNumber);
lineEdit->setValidator(validator);

チェックの仕方はいつもと変わりません.
int position = 0;
QStrint str = lineEdit->text();
QLambdaIntValidator* validator = (QLambdaIntValidator*)linEdit->validator();
QValidator::State state = validator->validate(str, position);

どうでしょうか?

2014年3月25日火曜日

Qt validator 入力フォームの値をチェックする

QValidatorで入力値をチェックしてみた

GUIツールキットのQtでGUIを作っています.
QLineEditで入力フォームを作ったときに,入力された値が適切であるかどうかをQtのQValidatorを使って確認するサンプルを作成してみました.

入力値をチェックする機能を自作していたのですが,QtにはQValidatorという便利な機能があることを初めて知りました.コレを使うとスッキリと入力値がチェック出来そうです.

まずQtデザイナを使って次のようなウィンドウを作成しました.
3つのQLineEditを持つウィンドウです.それぞれ次のような役割とします.

ラベルobjectName概要
int form intLineEdit20から500までの整数を入力するフォーム
double form doubleLineEdit浮動小数を入力するフォーム
original form myLineEdit偶数の整数を入力するフォーム

QValidatorは抽象クラスであるため,これを実装したサブクラスを使用します.QtではQIntValidator, QDoubleValidatorとQRegExpValidatorが用意されているみたいですね.
  • QIntValidator 入力値がint型であるかを確認する
  • QDoubleValidator 入力値がdouble型であるかを確認する
  • QRegExpValidator 入力値が指定した正規表現の範囲にあるかを確認する
整数ならQIntValidator, 小数ならQDoubleValidator, 使用できない記号などが含まれていないか確認する場合はQRegExpValidatorと言ったところでしょうか.これ以外にもQValidatorを実装した独自に作成したクラスでもいいですね.

加えて,QIntValidatorとQDoubleValidatorは入力できる数値の範囲も指定できるようです.
// 範囲指定の例: 20から500まで
QIntValidator validator = new QIntValidator(20, 500, this);
ここではintLineEditにQIntValidator, doubleLineEditにQDoubleValidator, myLineEditに独自作成したQEvenIntValidatorを設定します.

// mainwindow.h
class MainWindow: public QMainWindow {
    Q_OBJECT
public:

 /* 省略 */

public slots:
    void intEditTextChanged(const QString& text);
    void doubleEditTextChanged(const QString& text);
    void myEditTextChanged(const QString& text);
private:
    Ui::MainWindow *ui;

    // QValidator群
    QIntValidator *intValidator;
    QDoubleValidator *doubleValidator;
    QEvenIntValidator* evenValidator;

    /**
    * チェックした状態に応じてフォームの背景色を変更します.
    * @param state 状態
    * @param *sender 入力元フォームへのポインタ
    */
    void changeColorBy(QValidator::State state, QLineEdit* sender);
};

これに対してコンストラクタでQValidatorを設定します.setValidator()メソッドで設定するvalidatorのインスタンスを引数に与えます.QIntValidatorとQDoubleValidatorはコンストラクタに入力を受け付ける最小値と最大値を指定できるようです.ここではQIntValidatorに20から500までの数値のみを受け付けるように指定しています.

// mainwindow.cpp
/**
* コンストラクタ
*/
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent), ui(new Ui::MainWindow) {

    /* 省略 */

    // テキスト変更時のシグナルとスロットを接続する
    connect(ui->intLineEdit, SIGNAL(textChanged(const QString&)), this, SLOT(intEditTextChanged(const QString&)));
    connect(ui->doubleLineEdit, SIGNAL(textChanged(const QString&)), this, SLOT(doubleEditTextChanged(const QString&)));
    connect(ui->myLineEdit, SIGNAL(textChanged(const QString&)), this, SLOT(myEditTextChanged(const QString&)));

    // QIntValidatorをintLineEditに設定する.
    intValidator = new QIntValidator(20, 500, this);
    ui->intLineEdit->setValidator(intValidator);

    // QDoubleValidatorをdoubleLineEditに設定する.
    doubleValidator = new QDoubleValidator(this);
    ui->doubleLineEdit->setValidator(doubleValidator);

    // 独自に作成したQEventIntValidatorをmyLineEditに設定する.
    evenValidator = new QEvenIntValidator(this);
    ui->myLineEdit->setValidator(evenValidator);
}

そして,各入力フォームのテキスト変更スロットで入力値の確認を行う部分をコーディングします.QValidatorのvalidate()メソッドで入力値が適切かどうかを取得します.validate()はQValitor::Stateの列挙対を返します.それぞれ
  • Acceptable
  • Intermediate
  • Invalid
です.それぞれ入力値が○,△,×と言ったところでしょうか.数値のように判定が容易な物はAcceptableとInvalidときれいに判定できますが,文字列などの場合は判定に曖昧さが残るため,中間のIntrermediateを使うみたいですね.


QLineEditのvalidator()メソッドで設定しておいたQValidatorへのポインタが取得できます.
ここでは入力値が適切であるかを確認し,その結果に応じてフォームの背景色を変えるようにしました.
// mainwindow.cpp
void MainWindow::intEditTextChanged(const QString& text) {
    QString str = text;
    int position = 0;
    QIntValidator *validator = (QIntValidator*)ui->intLineEdit->validator();
    QValidator::State state = validator->validate(str, position);
    changeColorBy(state, ui->intLineEdit);
}

void MainWindow::doubleEditTextChanged(const QString &text) {
    QString str = text;
    int position = 0;
    QDoubleValidator* validator = (QDoubleValidator*)ui->doubleLineEdit->validator();
    QValidator::State state = ui->doubleLineEdit->validator()->validate(str, position);
    changeColorBy(state, ui->doubleLineEdit);
}

void MainWindow::myEditTextChanged(const QString &text) {
    QString str = text;
    int position = 0;
    QEvenIntValidator* validator = (QEvenIntValidator*)ui->myLineEdit->validator();
    QValidator::State state = validator->validate(str, position);
    changeColorBy(state, ui->myLineEdit);
}

changeColorBy()でフォームの背景色を次のように変えるようにしました.

// mainwindow.cpp
void MainWindow::changeColorBy(QValidator::State state, QLineEdit *sender) {
    switch(state) {
    case QValidator::Acceptable:
        sender->setStyleSheet("background: white");
        break;
    case QValidator::Intermediate:
        sender->setStyleSheet("background: yellow");
        break;
    case QValidator::Invalid:
        sender->setStyleSheet("background: pink");
        break;
    }
}

独自作成したQEvenIntValidatorは偶数の整数のみを受け付けるクラスです.QIntValidatorを継承しました.
//qevenintvalidator.h
class QEvenIntValidator : public QIntValidator
{
    Q_OBJECT
public:
    explicit QEvenIntValidator(QObject *parent = 0);
    QValidator::State validate(QString& text, int pos);
};
// qevenintvalidator.cpp
QEvenIntValidator::QEvenIntValidator(QObject *parent) :
    QIntValidator(parent) {
}

QValidator::State QEvenIntValidator::validate(QString &text, int pos) {
    QValidator::State state = QIntValidator::validate(text, pos);
    if(state != QValidator::Invalid) {
        int num = text.toInt();
        state = (num % 2 == 0 ? QValidator::Acceptable : QValidator::Intermediate);
    }
    return state;
}

実際作成してみたら,全てのValidatorが数値を扱うための物であることが原因なのか,フォームに数字以外の文字を入力できなくなってしまいました.ま,いっかww.

サンプルコード

ここで作成したサンプルコードはgithubにアップロードしました.
https://github.com/hiroyky/qt_validator_sample

参考

http://qt-project.org/doc/qt-4.8/qvalidator.html
http://qt-project.org/doc/qt-4.8/qintvalidator.html
http://qt-project.org/doc/qt-4.8/qlineedit.html

2014年2月26日水曜日

Ubuntu/Debian,ビデオカード搭載のThinkpad上でバックライトが調整できなかった.

私のThinkpad T410はNvidia NVS 3100Mというグラフィックカードを搭載しています.UbuntuでグラフィックドライバをNvidia製のものしたところ,ディスプレイのバックライトが調整できなくなってしまいました.
調べていたらThinkpadでLinuxを使用するWikiと思われる「ThinkWiki」に解決策が詳解されていました(参照)
紹介があるとおり,X11の設定ファイルである/etc/X11/xorg.confに追記すれば直りました.
Section "Device"に次の一行を追加します.
Option "RegistryDwords" "EnableBrightnessControl=1"

追記後はX11もしくはOSを再起動ですね.

2014年2月24日月曜日

Adobe CS4のアップデートが出来なかったのでメモ

Adobe Creative Cloudが全盛になっているであろう今日,Adobe CS4を未だに使い続けている私はAdobe CS4の新規インストールを行いました.
ディスクからのインストールを終えてアップデートを適応しようとしたとき困ってしまいました.

Adobe Updaterから自動アップデートできない

障害は2つ
  1. 「アップデートが応答しません。サーバが一時的にオフ ラインになっているか、インターネットまたはファイアウォール設定が正しくない可能性があります。後でもう一度やり直してください。」というエラーメッセージ
  2. 「次の製品のいくつかのアップデートについては,現時点では判定できません」これで全部判定されなかった

アップデートが応答しません

通常通りWiFi経由でインターネットに接続できていたのですが,試しに有線LANに切り替えてみたところアップデートサーバと通信するようになりました.何でなんでしょう?ともかく解決かな..

次の製品のいくつかのアップデートについては,現時点では判定できません

色々と調べたら,アップデートサーバのセキュリティ証明書が期限切れになっているからみたいです.そこで,システムの日付を昔に戻してから再実行すれば良いとのことでした.(参照)
試しに2011年7月に日付・時計を変更してみたら正常にアップデートできるようになりました.

もうCS4って古いのでしょうかね.笑
ちなみにCS3でも同様に証明書が古くアップデートが実行できないみたいです.
あと,アップデート後に日付を戻すのを忘れていたのでいろいろ支障来してしまいました.