2012年5月13日日曜日

【Qt】Macで、QMenuを使おうとしたときの覚え書き。


Qtの入門書(※1)のサンプルをいじっているのですが、作成するアプリケーションが一つのメソッドの動作を確かめるためには割と大きくて、各処理がちゃんとどう実行できるか確かめるために小さなアプリケーションを作成したところ、若干つまずいた部分があったので、メモ。

とりあえず、windowを出して、終了だけできるアプリケーションを実装してみた。そこで、下記のコードのように、ファイルメニュー、ヘルプメニューを作成してみた所、予想としていた結果と違う結果が出てしまった。

void MainWindow::createMenus()
{
  fileMenu = menuBar()->addMenu(tr("&File"));
  fileMenu->addAction(showTestAction);
  fileMenu->addAction(exitAction)
  
  helpMenu = menuBar()->addMenu(tr("&Help"));
  helpMenu->addAction(aboutAction);
  helpMenu->addAction(aboutQtAction);
}

で結果がこれ。

ヘルプメニューは表示されないし、ファイルメニューに設定したはずのメニューはなんか「winTest」っていう特に設定していない(アプリケーション名の)メニューの方に追加されてしまっているし、利用する分には、問題なかったとしても、想像していたのと違う動きをしているのでちょっと調べてみた。

で、Qt本家の記事(http://doc.trolltech.com/4.5/mac-differences.html#menu-bar)によると結局、OSネイティブの使用に合わせてラッパーをつくっているので、上のでwinTestに出ているものに関しては、自動的にこちらのメニューに追加されてしまうみたい。

とはいえ、どういうタイミングでこのメニューに追加されてしまうのかというのがわからなかったので、いろいろといじってみた所。下のコードを

void MainWindow::createActions()
{
  //------------ 略 ----------------//
  
  aboutAction = new QAction("&About",this);
  aboutAction->setStatusTip("Show about this application.");
  connect(aboutAction,SIGNAL(triggered()),
   this,SLOT(aboutTest()));

  //------------ 略 ----------------//
}

このように書き換えてみると
void MainWindow::createActions()
{
  //------------ 略 ----------------//
  
  aboutAction = new QAction("&Bout",this);
  aboutAction->setStatusTip("Show about this application.");
  connect(aboutAction,SIGNAL(triggered()),
   this,SLOT(aboutTest()));

  //------------ 略 ----------------//
}
こんな感じの結果になった。
というわけで、原因はここにあるという事はわかった。実装上の仕組みはまだよくわかっていないので、設定方法の仕組みがわかったら、またメモろうとは思いますが。
とりあえず、Macのメニューの設定時にびっくりしないようにメモ。

※1「入門 Qt 4 プログラミング」
Jasmin Blanchette (著), Mark Summerfield (著), 杵渕 聡 (翻訳), 杉田 研治 (翻訳)
 - amazon

2012年5月7日月曜日

【AS3.0】アプリケーションフレームワークをつくってみた。



ActionScript3.0でアプリケーション用のフレームワークをつくってみた。
Github- Framingo
アプリケーション設計の勉強と、ActionScriptを触り始めてちょうど2年半くらいになるのでそのまとめという意味で、アプリケーションプロトタイピング用の、フレームワークをつくってみました。基本的には自分が使う用、もしくは学習したナレッジの蓄積用として継続的に開発していくつもりです。

世に言うMVCというのを意識してつくったつもりですが、いろいろ調べていくと割と曖昧で、結局なにがMVCなのかっていうのは未だに消化しきれていない感じです。
FlashだとViewの部分を扱う事が多いような気がしますが、処理系が複雑になっていくにつれて、どのように整理してコードを実装して良いのかが、わからなくなってしまう事があったりもしたので、できるだけ見た目が変化する処理の部分と、オンメモリで扱うアプリケーションのデータに対する操作を切り離せるようにしたつもりです。

実装上の主なコンセプトは

  1. ユーザーのアクションに対して、一対一の動作をアプリケーションが行うようにする。
  2. IDEと連携した作業もしやすいようにする。
  3. シンプルな処理の仕組みだけを提供し、なんでもできてしまうような便利メソッドはできるだけ提供しない。
  4. 素早い実装と、コード管理のしやすさを目指す。

こんな感じです。現在バージョンはver 0.1となっていますが、現在はようやく動作するという感じです。まだ実装しきれていない部分や、まったく実装のないクラスなどがいくつかあったりします。プロトタイピング用を目指しているので、さっと実装できるのが良いと思っているのですが、現状結構めんどうくさくて解りにくいです。
XMLで記述して、アプリケーションのひな形やシーン構成が作成できるようにしようと思っていますが、現在は以下のクラスの特定メソッドを必要に応じて継承しないと例外が出るつくりになっています。

src/framingo/core/FMCoreClass.as
src/framingo/model/manager/DataManager.as
src/framingo/model/process/AbstractProcess.as
src/framingo/model/process/ProcessFlow.as
src/framingo/view/factory/SceneFactory.as


また、テストコードやサンプルコード、ドキュメントに関しては、順次整理しようと思っています。まだまだ稚拙な実装は多いと思うので、順次ブラシュアップしていければと思っています。

以下クラス構成

.
`-- framingo
    |-- core
    |   |-- FMApplication.as
    |   |-- FMCoreClass.as
    |   |-- FMCoreSetting.as
    |   |-- config
    |   |   `-- FMVersion.as
    |   |-- error
    |   |   |-- ErrorManager.as
    |   |   `-- UnimplementedError.as
    |   |-- log
    |   |   `-- Logger.as
    |   `-- system
    |       `-- SystemManager.as
    |-- data
    |   |-- AbstractDataGroup.as
    |   |-- AbstractProcessData.as
    |   |-- SceneDataGroup.as
    |   `-- action
    |       |-- AbstractAction.as
    |       |-- ActionSync.as
    |       |-- FlowAction.as
    |       |-- IDataTransfer.as
    |       |-- RenderAction.as
    |       `-- SceneAction.as
    |-- model
    |   |-- events
    |   |   |-- FlowEvent.as
    |   |   |-- ProcessActionEvent.as
    |   |   `-- ProcessEvent.as
    |   |-- factory
    |   |   `-- FlowFactory.as
    |   |-- manager
    |   |   |-- DataManager.as
    |   |   `-- ModelManager.as
    |   `-- process
    |       |-- AbstractProcess.as
    |       `-- ProcessFlow.as
    |-- presenter
    |   |-- ActionPresenter.as
    |   |-- IActionReceivable.as
    |   `-- IThrowableAction.as
    `-- view
        |-- events
        |   |-- ActionObjectEvent.as
        |   |-- RenderObjectEvent.as
        |   |-- SceneEvent.as
        |   `-- SceneManagerEvent.as
        |-- factory
        |   `-- SceneFactory.as
        |-- interactive
        |   `-- ActionObject.as
        |-- manager
        |   |-- DialogManager.as
        |   |-- SceneManager.as
        |   `-- ViewManager.as
        |-- render
        |   |-- IRenderableData.as
        |   `-- RenderObject.as
        `-- scenes
            |-- AbstractScene.as
            `-- SceneChildren.as

2012年2月22日水曜日

【Python】ファイルを検索して行番号を取得する

Pythonを使ってみたかったので、とりあえず書いてみた。
現在のディレクトリ以下のファイルを検索して、指定の文字列のある行番号を取得する。
なんとなくだけど、いまいちよくわかってない部分があったり。



import os
import glob


def get_filepath(rootpath,term):
file_list = []
for root,dir,files in os.walk(rootpath):
for fname in glob.glob(os.path.join(root,term)):
file_list.append(fname)
return file_list


def load_files(file_list):
file_set = {}
for filepath in file_list:
fname = filepath[filepath.rfind("/")+1:len(filepath)]
f = open(filepath,"r")
file_set.update({fname:f})
return file_set

def close_files(file_set):
for f in file_set.values():
f.close()


def get_line_number_with_term(file_set,terms):
line_set = {}
for name,f in file_set.items():
line_number = []
count = 0
for line in f:
if(line.find(terms) != -1):
line_number.append(count)
count+=1
line_set.update({name:line_number})
return line_set

if __name__ == '__main__':
curdir = os.getcwd()
extention =( "*." + raw_input("[ Enter extention ]:") )
pathList = get_filepath(curdir,extention)
fileset = load_files(pathList)
terms = raw_input("[ Enter terms ]:")
lineSet = get_line_number_with_term(fileset,terms)
close_files(fileset)
print lineSet


実行結果

bash-3.2$ python hoge.py
python hoge.py
[ Enter extention ]:py
py
[ Enter terms ]:def
def
{'hoge.py': [5, 13, 21, 26]}

2011年12月21日水曜日

【php】XMLを読み込んで複数のコマンドを実行する

前回のプログラムを少し拡張してみた。XMLをロードして複数コマンドを実行する。


<?php
doMultiProcesses($argc , $argv);
//コマンド
function doMultiProcesses($num,$param){
if($num < 2){
echo "コマンドが入力されていません。\n";
return;
}
execProcess($param);
}

//コマンドの実行
function execProcess($arg)
{
switch($arg[1]){
case "xml":
if(count($arg) < 3){ echo "引数が足りていません\n";return;}
$process = new XMLLoader($arg[2]);
break;
default:
echo "設定されていないコマンドです。\n";
return;
}
$process->execute();
$processes = new Launcher();
$processes->setProcesses($process->processes);
//$processes->isQueue = false;
$processes->execute();

}


/***********************
*
* 抽象クラス
*
**********************/
abstract class AbstractProcess{
abstract public function execute();
abstract public static function toString();
}

class Process
{
public $params;
public $name;

public function Process($name,$params){
$this->name = $name;
$this->params = $params;
}

public static function create($name,$params)
{
$className = $name;
$classParams = $params;
if(class_exists($className)){
$process = new $className($classParams);
}else{
echo $className . "という処理がみつかりません。\n";
}
return $process;
}
}

/***********************
*
* 複数コマンドの実行用
*
***********************/

final class Launcher extends AbstractProcess{

public $processes;
public $isQueue;

public function Launcher(){
$this->isQueue = true;
}

public function setProcesses($value){
$this->processes = $value;
}

public function execute(){
while(count($this->processes) > 0){
if($this->isQueue){
$process = array_shift($this->processes);
}else{
$process = array_pop($this->processes);
}
$process->execute();
}
}

public static function toString(){
return "Launcher";
}
}


/***********************
*
* コマンドローダー
*
***********************/

class XMLLoader extends AbstractProcess{



private $path = "";
public $processes;

public function XMLLoader($path){
$this->path = $path;
$this->processes = array();
}

public function execute(){

if(!file_exists($this->path)) {
echo "ファイルが存在しません\n";
return;
}
try{
$xml = simplexml_load_file($this->path);
}catch(Exception $e ){
echo "XMLの書式が間違っています\n";
return;
}

foreach( $xml->process as $process){
$name = (string)($process->name);
$param = (string)($process->param);
$prc = Process::create($name,$param);

if($prc instanceof AbstractProcess)
array_push($this->processes,$prc);
}
}

public static function toString()
{
return "XMLLoader";
}
}

/***********************
*
* サンプルコマンド
*
***********************/
class Test extends AbstractProcess
{
private $param;
public function Test($param){
$this->param = $param;
}

public function execute(){

echo $this->param . "\n";
}

public static function toString()
{
return "Test";
}

}




これを使って以下のXMLを読み込んで実行する。

<data>
<process>
<name>Test</name>
<param >param1</param>
</command>
<process>
<name>Test</name>
<param >param2</param>
</process>
</data>


実行


mr-elephant:php shuzo$ php process.php xml ./process.xml
param1
param2


とりあえず必要なものだけを実装してみました。
もうちょいなんか工夫できそうな気がします。

というかGithubにあげてみたいと思ったのですが、うまくいってません。orz

※インデントが気持ち悪いところだけ修正しました。
※commandという名前はあまりよくないというご指摘を受けたので、修正しました。
どうせなので、微妙にリファクタリングを追加。

2011年12月19日月曜日

【php】クラスの継承メモ

phpでコード生成のプログラムを書くことがちょくちょく増えてきたので、インターフェイスとかを統一しておきたい。まずはクラスの書き方から勉強。


<?php
cmd($argc , $argv);
//コマンド
function cmd($num,$param){
if($num < 2){
echo "コマンドが入力されていません。\n";
return;
}
commandExec($param);
}

//コマンドの実行
function commandExec($arg)
{
switch($arg[1]){
case "test":
if(count($arg) < 3){ echo "引数が足りていません\n";return;}
$cmd = new TestCommand($arg[2]);
break;
default:
echo "設定されていないコマンドです。\n";
return;
}
$cmd->execute();
}

/***********************
*
* スーパークラス
*
**********************/
abstract class AbstractCommand{
protected $states;
abstract public function execute();
abstract public function toString();
}

/***********************
*
* 子クラス
*
***********************/
class TestCommand extends AbstractCommand
{
private $param;
public function TestCommand($param){
$this->param = $param;
}

public function execute(){

echo $this->param . "\n";
}

public function toString()
{
return "TestCommand";
}

}



これを実行すると。


mr-elephant:php shuzo$ php cmd.php test hoge
hoge


出力されました。上の内容でちょっとつまずいたところは、




class TestCommand extends AbstractCommand
{
private $hoge;
public function TestCommand($param){

$hoge = $param;
}

public function execute(){
echo $hoge . "\n";
}

public function toString()
{
return "TestCommand";
}

}


上のやり方だと出力されず、メンバ変数へのアクセスには必ず$this->hogeを使うとのこと。省略しちゃだめってことですね。

2011年10月11日火曜日

Hello world

Dartでちょっと修正Hello World


int main() {

var hello = echo;

hello('Hello world!!');
}

echo(var str) => print(str);


結果

Hello world!!

http://try-dart-lang.appspot.com/s/Z0ET
うむ。

ついでに(チョイ修正)、

int main() {

var hello = echo;

hello('Hello world!!');
}
/*
echo(String str){
print(str);
}*/

echo(int str){
print(str);
}


結果

Hello world!!


http://try-dart-lang.appspot.com/s/iGUT
うーむ。

2011年9月8日木曜日

【AppleScript】ダイアログボックスを出す。

AppleScriptでダイアログボックスを出す。
あると便利だったりするのでメモ。

on run ARGV
tell application "Finder"
activate
set msg to item 1 of argv
display dialog msg
end tell
end run

コマンドラインで実行権限を与えてあげる

chmod +x alert.applescript

実行

osascript alert.applescript "Hello world"


結果