+Thu April 29 2010 Shyouzou Sugitani <shy@users.sourceforge.jp>
+ * バージョン4.0.5リリース.
+
+Wed April 28 2010 Shyouzou Sugitani <shy@users.sourceforge.jp>
+ * lib/ninix/sakura.py:
+ GStreamerの奇妙な振舞いへの対策を追加.
+ (https://bugzilla.gnome.org/show_bug.cgi?id=549879 を参照.)
+ 具体的な動作としては--help(-h)コマンドラインオプションを指定すると
+ GStreamerのヘルプが表示されていたのをninix-ayaのものが出るように修正.
+
+Mon April 26 2010 Shyouzou Sugitani <shy@users.sourceforge.jp>
+ * lib/ninix/main.py:
+ 廃止したコマンドラインオプションの処理が残っていたのを削除.
+ * lib/ninix/menu.py:
+ メニューからゴーストの再読み込みを削除.
+
+Fri April 23 2010 Shyouzou Sugitani <shy@users.sourceforge.jp>
+ * lib/ninix/dll/httpc.py:
+ HTTP Status Codeが200(OK)以外の場合にはデータを返さないように修正.
+ * クラスのインスタンス生成時に生成元のクラス等他のクラスへの参照を
+ 渡していたのを止めて, 代わりにコールバック関数の入った辞書型変数を
+ 渡すようにした.(lib/ninix/dll/以下のファイルについては除外.)
+ * lib/ninix/balloon.py:
+ バルーンのウインドウにdeleteイベントが送られてもゴーストが終了しない
+ ように変更.
+ * lib/ninix/dll.py:
+ SAORI互換モジュールからPreferencesクラスへの参照を削除し, Sakuraへの
+ 参照を使うようにした.
+ * Pluginに関するコードをmain.pyから分離してplugin.pyを作成した.
+ * lib/ninix/main.py:
+ SSTP Serverの管理をApplicationクラスから分離してSSTPControlerクラスを
+ 作成した.
+ * lib/ninix/main.py:
+ ApplicationクラスをNew-style classにした.(今後全クラスを変更予定.)
+ current_sakuraをApplicationクラスのpropertyにした.
+ current_sakuraのsetter(a function for setting)内で変更をPreferences
+ に伝えるようにした.
+
+Fri April 9 2010 Shyouzou Sugitani <shy@users.sourceforge.jp>
+ * doc/saori.txt: osuwari.pyとhttpc.pyに関する記述を追加.
+ * lib/ninix/config.py:
+ Configクラスのgetint, getfloatメソッドをget_with_typesに統合.
+ * lib/ninix/dll.py:
+ SAORIクラスに辞書型変数RESPONSEを作成し, 戻り値を持たない
+ SAORI/1.0のレスポンス(204, 400, 500)を入れた.
+ SAORI互換モジュールはこの変数を使用するように修正.
+ * lib/ninix/main.py:
+ Application.get_plugin_list()で変数の代入前に値を参照している部分が
+ あったのを修正.
+ * lib/ninix/main.py:
+ 'OnShellChanging'イベントの引数に渡す変数名を間違えていたのを修正.
+ (3.9.9でのregression.)
+ * lib/ninix/pix.py:
+ create_pixbuf_from_file()の引数is_pnrとuse_pnaには1/0ではなく
+ True/Falseを渡すように変更.
+ * lib/ninix/prefs.py:
+ Preferences.get_with_type()の引数の順序を変更した.
+ * lib/ninix/sakura.py:
+ 専用バルーンを持つゴーストでバルーンを専用バルーンとは別のバルーンに
+ 変えてから専用バルーンに戻すと落ちる問題を修正.
+ * lib/ninix/balloon.py:
+ BalloonWindowのconfig_getintメソッドを__get_with_scalingに変更.
+ (__get_with_scalingでは戻り値の型を第2引数に渡す必要がある.)
+ * lib/ninix/surface.py:
+ SurfaceWindowのget_config_intメソッドを__get_with_scalingに変更.
+ (__get_with_scalingでは戻り値の型を第2引数に渡す必要がある.)
+ * lib/ninix/prefs.py:
+ デフォルトバルーンに設定されているバルーンの存在確認を省略.
+ (存在していない場合には最初に見付かったバルーンが選ばれる.)
+
Tue April 6 2010 Shyouzou Sugitani <shy@users.sourceforge.jp>
* バージョン4.0.4リリース.
* lib/ninix/surface.py:
サーフェス倍率が100%以外の場合に当り判定領域の座標の計算結果が全て
0になるバグを修正.(バージョン4.0.3でのregression.)
-
+
Thu April 1 2010 Shyouzou Sugitani <shy@users.sourceforge.jp>
* Makefile: 使用していなかったPythonのdistutilsに関する部分を削除.
それに合わせてPKG-INFOファイルを削除した.
Wed March 31 2010 Shyouzou Sugitani <shy@users.sourceforge.jp>
* バージョン4.0.3リリース.
-
+
Mon March 29 2010 Shyouzou Sugitani <shy@users.sourceforge.jp>
* 画像を拡大/縮小する際に8x8ピクセル以下にならないように制限をかけた.
(これまでも一部で制限をかけてあったが1x1ピクセルであったり,
スクリプト再生は未対応のまま.)
* lib/ninix/dll/aya5.py:
未実装のシステム関数を呼び出そうとして落ちる問題を修正.
-
+
Fri March 26 2010 Shyouzou Sugitani <shy@users.sourceforge.jp>
* サーフェス/バルーンの拡大縮小で100%の場合を特別扱いするのをやめた.
* pixbuf, pixmapを明示的に削除するのをやめた.
エラーになっていた.)
* lib/ninix/kawari.py: read_local_script()内のtypoを修正.
(readline() -> readlines())
-
+
Thu February 25 2010 Shyouzou Sugitani <shy@users.sourceforge.jp>
* バージョン4.0.2リリース.
* lib/ninix/main.py: ゴースト消滅後の交代で落ちる問題を修正.
-
+
Tue February 23 2010 Shyouzou Sugitani <shy@users.sourceforge.jp>
* lib/ninix/surface.py:
ドロップされたファイルのパスがURLエンコードされたままになっていたため
* lib/ninix/ngm.py: 使用していないモジュールのimportを削除.
* lib/ninix/home.py, lib/ninix/main.py:
gtkrcの読み込み処理を削除.
- * lib/ninix/home.py:
+ * lib/ninix/home.py:
「きのこ」と「猫どりふ」の設定ファイルの読み込みでエラー処理が
抜けていたのを修正.
* lib/ninix/dll/wmove.py, lib/ninix/dll/bln.py:
\_v[]タグとMCIAudio, MCIAudioR互換モジュールを変更した.
MCIAudioRはループ演奏に対応した.
READMEの「必要なもの」にGStreamer Python bindingsを追加した.
-
+
Fri December 4 2009 Shyouzou Sugitani <shy@users.sourceforge.jp>
* Webブラウザの呼び出しにはPythonのwebbrowerモジュールを
使用するようにした.(ユーザー設定からWebブラウザを削除した.)
* バージョン3.9.9aリリース.
* CommunicateWindowクラス(とそれを継承しているクラス)を修正.
(Thanks to addone@users.sourceforge.jp.)
-
+
Wed July 22 2009 Shyouzou Sugitani <shy@users.sourceforge.jp>
* バージョン3.9.9リリース.
* 「きのこ」の'ontop'の処理にgtk.Window.set_transient_for()を
* NGMクローンからのゴーストの更新方法を変更した.
(Sakuraクラスのupdate()メソッドを直接呼ぶのではなく,
"\![updatebymyself]\e"をスクリプトキューに入れるようにした.)
-
+
Fri June 12 2009 Shyouzou Sugitani <shy@users.sourceforge.jp>
* バージョン3.9.8eリリース.
* 3.9.8dでeasyballoon互換モジュールが落ちるのを修正した.
集約した. ユーザー設定の項目も減らした.
SHIORIイベントの発生を抑制する項目(PREFS_EVENT_KILL_LIST)と
マウスボタンの機能を設定する項目(PREFS_MOUSE_BUTTON1,
- PREFS_MOUSE_BUTTON3)を削除した.
+ PREFS_MOUSE_BUTTON3)を削除した.
また, メニューから個々のゴーストについてサーフェス倍率とスクリプトの
再生スピードを設定する項目を削除した.(全ゴーストが同じ設定になる.)
("Extended Window Manager Hints"の_NET_WORKAREAを使用している.
詳細は http://standards.freedesktop.org/wm-spec/wm-spec-latest.html
を参照.)
-
+
Wed May 6 2009 Shyouzou Sugitani <shy@users.sourceforge.jp>
* バージョン3.9.8bリリース.
* sourceforge.jpにGitリポジトリを作成し, ソースコードの管理をGitに
Sun July 22 2007 Shyouzou Sugitani <shy@users.sourceforge.jp>
* バージョン3.9.6リリース.
* OnBallonCloseイベントのサポートを追加.
-
+
Sat July 21 2007 Shyouzou Sugitani <shy@users.sourceforge.jp>
* OnMouseEnterAll, OnMouseLeaveAll, OnMouseEnter, OnMouseLeave
イベントのサポートを追加.
- 全てのスクリプトがトランスレータを通るように修正.(sakura.py)
- 選択肢の範囲チェックを修正.
選択肢の先頭が表示領域内でも途中から外に出ている場合がある.(sakura.py)
-
+
2002/10/27 period 20
- 花柚(hanayu.dll)互換 SAORI モジュール hanayu.py を追加.
- れたす(lettuce.dll)互換 SAORI モジュール lettuce.py を追加.
- 再読み込み後に発生させるイベントを OnBoot に変更.(sakura.py)
- OnGhostChanged に反応が無い場合には OnBoot を呼ぶようにした.(sakura.py)
- '\x' による一時停止時にバルーンに下向き矢印を出させるようにした.(sakura.py)
-
+
2002/09/02 period 17
- DLL 互換モジュールのデフォルトサーチパスの指定を必須にした.(dll.py)
- DLL 互換モジュールを要求する際にサーチパスを追加出来るように変更.(dll.py)
- SAORI互換機能 (saory.py) 追加.
- ユーザーからゴーストへのコミュニケート対応(aya のみ).
- 「和音」のメニューからの MIDI 演奏に対応.
-デバッグ:
+デバッグ:
- 簡易配列を拡張する処理の条件判定が逆になっていたのを修正.
- 変数への代入の際に既に変数が存在するかどうかの判定を忘れていたのを追加.
- - 変数を操作する場合, 事前に AyaVAriable.reset メソッドが実行されるようにした.
+ - 変数を操作する場合, 事前に AyaVAriable.reset メソッドが実行されるようにした.
これにより文字列の演算による簡易配列としての構造の変化に対応.
2002/07/30 period 13
CALLBYNAME, LOGGING, TOUPPER, TOLOWER, TONUMBER2, TOSTRING2,
FLOOR, CEIL, ROUND, SIN, COS, TAN, LOG, LOG10, POW, SQRT,
SETSEPARATOR, FOPEN, FCLOSE, FREAD, FWRITE, ISINTEGER, ISREAL
-
+
2002/05/28 period 5 (canceled)
- 「文」Ver.3 文法に対応
- SHIORI/1.0 APIに対応
- システム関数 ARRAYSIZE を実装.
- 「和音」がエラーで固まるのを防ぐために ghostexcount は常に0を返
すようにした. (COMMUNICATE実装までの暫定措置)
-
+
2002/05/20 period 2
- 文 ver.3 一部対応
- 全角スペースを空白と見なしていなかった問題の修正
------
櫛ケ浜やぎ氏が開発されている「ssu.dll」と互換のモジュールです。
+osuwari.py
+--------
+ukiya氏が開発されている「osuwari.dll」と互換のモジュールです。
+ゴーストをウィンドウに「お座り」させる機能を提供します。
+
+httpc.py
+--------
+櫛ヶ浜やぎ氏が開発されている「httpc.dll」と互換のモジュールです。
+Web上の各種データをHTTPで取得する機能を提供します。
+
連絡先
------
この資料の著作権と文責は、
inst_dst = ninix.home.read_install_txt(prefix)
if not inst_dst or inst_dst.get('name') != inst.get('name'):
mode |= INTERACTIVE
- if inst.getint('refresh', 0):
+ if inst.get_with_type('refresh', int, 0):
# uninstall older versions of the ghost
if confirm_removal(prefix):
mask = inst.get('refreshundeletemask', '').lower().split(':')
inst_dst = ninix.home.read_install_txt(prefix)
if not inst_dst or inst_dst.get('name') != inst.get('name'):
mode |= INTERACTIVE
- if inst.getint('refresh', 0):
+ if inst.get_with_type('refresh', int, 0):
# uninstall older versions of the ghost
if confirm_removal(prefix):
mask = inst.get('refreshundeletemask', '').lower().split(':')
inst_dst = ninix.home.read_install_txt(prefix)
if not inst_dst or inst_dst.get('name') != inst.get('name'):
mode |= INTERACTIVE
- if inst.getint('refresh', 0):
+ if inst.get_with_type('refresh', int, 0):
# uninstall older versions of the ghost
if confirm_removal(prefix):
mask = inst.get('refreshundeletemask', '').lower().split(':')
inst_dst = ninix.home.read_install_txt(prefix)
if not inst_dst or inst_dst.get('name') != inst.get('name'):
mode |= INTERACTIVE
- if inst.getint('refresh', 0):
+ if inst.get_with_type('refresh', int, 0):
# uninstall older versions of the shell
if confirm_removal(prefix):
mask = inst.get('refreshundeletemask', '').lower().split(':')
inst_dst = ninix.home.read_install_txt(dstdir)
if not inst_dst or inst_dst.get('name') != inst.get('name'):
mode |= INTERACTIVE
- if inst.getint('refresh', 0):
+ if inst.get_with_type('refresh', int, 0):
# uninstall older versions of the balloon
if confirm_removal(dstdir):
mask = inst.get('refreshundeletemask', '').lower().split(':')
class Balloon:
- def __init__(self, sakura, prefs, debug=0):
- self.__sakura = sakura
- self.prefs = prefs
+ def __init__(self, callback, debug=0):
+ self.callback = callback
self.debug = debug
self.synchronized = []
self.__scalling = 0
self.__scale = 100 # %
- self.__use_pna = 0
+ self.__use_pna = False
self.__alpha_channel = None
self.user_interaction = False
self.window = []
# create communicatebox
- self.communicatebox = CommunicateBox(self, sakura, debug)
+ communicatebox_callback = {
+ 'reset_user_interaction': self.reset_user_interaction,
+ 'notify_event': self.callback['notify_event'],
+ }
+ self.communicatebox = CommunicateBox(communicatebox_callback, debug)
# create teachbox
- self.teachbox = TeachBox(self, sakura, debug)
+ teachbox_callback = {
+ 'reset_user_interaction': self.reset_user_interaction,
+ 'notify_user_teach': self.callback['notify_user_teach'],
+ }
+ self.teachbox = TeachBox(teachbox_callback, debug)
# create inputbox
- self.inputbox = InputBox(self, sakura, debug)
+ inputbox_callback = {
+ 'reset_user_interaction': self.reset_user_interaction,
+ 'notify_event': self.callback['notify_event'],
+ }
+ self.inputbox = InputBox(inputbox_callback, debug)
def reset_user_interaction(self):
self.user_interaction = False
self.window[side].reset_text_count()
def set_use_pna(self, flag):
- if flag:
- self.__use_pna = 1
- else:
- self.__use_pna = 0
+ self.__use_pna = bool(flag)
for balloon_window in self.window:
balloon_window.set_use_pna(flag)
balloon_window.reset_balloon()
window.set_resizable(False)
window.set_skip_pager_hint(False)
window.set_skip_taskbar_hint(True)
- window.font_name = self.prefs.get('balloon_fonts')
+ window.font_name = self.callback['get_preference']('balloon_fonts')
window.connect('delete_event', self.delete)
window.realize()
return window
return False
def delete(self, window, event):
- self.__sakura.finalize()
- return False
+ return True
def finalize(self):
for balloon_window in self.window:
communicate2 = value # teach box
elif key == 'c3':
communicate3 = value # input box
- self.balloon1 = balloon1 ## FIXME
+ self.balloon0 = balloon0
+ self.balloon1 = balloon1
# create balloon windows
for balloon_window in self.window:
balloon_window.destroy()
self.window = []
- for name, side, id_format, balloon in [('sakura', 0, 's%d', balloon0),
- ('kero', 1, 'k%d', balloon1)]:
- gtk_window = self.create_gtk_window(''.join(('balloon.', name)))
- balloon_window = BalloonWindow(
- gtk_window, side, self.__sakura, desc, balloon,
- id_format, self.__use_pna, self.__alpha_channel, self.debug)
- self.window.append(balloon_window)
- for balloon_window in self.window:
- balloon_window.set_scalling(self.__scalling)
- balloon_window.set_scale(self.__scale)
+ self.add_window(0)
+ self.add_window(1)
# configure communicatebox
self.communicatebox.new(desc, communicate1)
# configure teachbox
self.inputbox.new(desc, communicate3)
def add_window(self, side):
- assert side >= 2 and len(self.window) == side ## FIXME
- gtk_window = self.create_gtk_window('balloon.char%d' % side)
- id_format = 'k%d'
- balloon = self.balloon1 ## FIXME
+ assert len(self.window) == side
+ if side == 0:
+ name = 'balloon.sakura'
+ id_format = 's%d'
+ balloon = self.balloon0
+ elif side == 1:
+ name = 'balloon.kero'
+ id_format = 'k%d'
+ balloon = self.balloon1
+ else:
+ name = 'balloon.char%d' % side
+ id_format = 'k%d'
+ balloon = self.balloon1
+ gtk_window = self.create_gtk_window(name)
+ balloon_window_callback = self.callback.copy() ## FIXME
balloon_window = BalloonWindow(
- gtk_window, side, self.__sakura, self.desc, balloon,
+ gtk_window, side, balloon_window_callback, self.desc, balloon,
id_format, self.__use_pna, self.__alpha_channel, self.debug)
self.window.append(balloon_window)
+ balloon_window.set_scalling(self.__scalling)
balloon_window.set_scale(self.__scale)
- balloon_window.set_balloon(0) ## FIXME
+ if side > 1:
+ balloon_window.set_balloon(0) ## FIXME
def reset_fonts(self):
- font_name = self.prefs.get('balloon_fonts')
+ font_name = self.callback['get_preference']('balloon_fonts')
for window in self.window:
window.window.font_name = font_name
window.update_gc()
def is_shown(self, side):
if len(self.window) > side:
- if self.window[side].is_shown():
- return 1
- else:
- return 0
+ return 1 if self.window[side].is_shown() else 0
else:
return 0
def open_teachbox(self):
if not self.user_interaction:
self.user_interaction = True
- self.__sakura.notify_event('OnTeachStart')
+ self.callback['notify_event']('OnTeachStart')
self.teachbox.show()
def open_inputbox(self, symbol, limittime=-1, default=None):
class BalloonWindow:
- def __init__(self, window, side, sakura, desc, balloon,
+ def __init__(self, window, side, callback, desc, balloon,
id_format, use_pna, alpha, debug):
self.window = window
self.side = side
- self.__sakura = sakura
+ self.callback = callback
self.desc = desc
self.balloon = balloon
self.balloon_id = None
gtk.gdk.POINTER_MOTION_MASK|
gtk.gdk.POINTER_MOTION_HINT_MASK|
gtk.gdk.SCROLL_MASK)
- self.callbacks = []
for signal, func in [('expose_event', self.redraw),
('button_press_event', self.button_press),
('motion_notify_event', self.motion_notify),
('scroll_event', self.scroll)]:
- self.callbacks.append(self.darea.connect(signal, func))
+ self.darea.connect(signal, func)
self.window.add(self.darea)
self.darea.realize()
self.darea.window.set_back_pixmap(None, False)
- mask_r = desc.getint('maskcolor.r', 128)
- mask_g = desc.getint('maskcolor.g', 128)
- mask_b = desc.getint('maskcolor.b', 128)
+ mask_r = desc.get_with_type('maskcolor.r', int, 128)
+ mask_g = desc.get_with_type('maskcolor.g', int, 128)
+ mask_b = desc.get_with_type('maskcolor.b', int, 128)
self.cursor_color = '#%02x%02x%02x' % (mask_r, mask_g, mask_b)
- text_r = desc.getint(['font.color.r', 'fontcolor.r'], 0)
- text_g = desc.getint(['font.color.g', 'fontcolor.g'], 0)
- text_b = desc.getint(['font.color.b', 'fontcolor.b'], 0)
+ text_r = desc.get_with_type(['font.color.r', 'fontcolor.r'], int, 0)
+ text_g = desc.get_with_type(['font.color.g', 'fontcolor.g'], int, 0)
+ text_b = desc.get_with_type(['font.color.b', 'fontcolor.b'], int, 0)
self.text_normal_color = '#%02x%02x%02x' % (text_r, text_g, text_b)
- if desc.getint('maskmethod') == 1:
+ if desc.get_with_type('maskmethod', int) == 1:
text_r = 255 - text_r
text_g = 255 - text_g
text_b = 255 - text_b
(pixbuf.get_width(), pixbuf.get_height()))
def set_use_pna(self, flag):
- if flag:
- self.__use_pna = 1
- else:
- self.__use_pna = 0
+ self.__use_pna = bool(flag)
self.reset_pixbuf_cache()
def set_alpha_channel(self, value):
self.redraw()
def get_scale(self):
- if self.__scalling:
- return self.__scale
- else:
- return 100 # %
+ return self.__scale if self.__scalling else 100 # %
def set_scale(self, scale):
self.__scale = scale # %
self.sstp_gc = self.new_mask_gc(mask, x, y)
# font
default_size = 12 # for Windows environment
- size = self.desc.getint(['font.height', 'font.size'], default_size)
+ size = self.desc.get_with_type(['font.height', 'font.size'], int, default_size)
self.layout = pango.Layout(self.darea.get_pango_context())
self.font_desc = pango.FontDescription(self.window.font_name)
pango_size = self.font_desc.get_size()
# font for sstp message
if self.side == 0:
default_size = 10 # for Windows environment
- size = self.desc.getint('sstpmessage.font.height', default_size)
+ size = self.desc.get_with_type('sstpmessage.font.height', int, default_size)
self.sstp_layout = pango.Layout(self.darea.get_pango_context())
self.sstp_font_desc = pango.FontDescription(self.window.font_name)
pango_size = self.sstp_font_desc.get_size()
else:
sstp_font_height = 0
# font metrics
- origin_x = self.config_getint(
- 'origin.x',
- self.config_getint('zeropoint.x',
- self.config_getint('validrect.left', 14)))
- origin_y = self.config_getint(
- 'origin.y',
- self.config_getint('zeropoint.y',
- self.config_getint('validrect.top', 14)))
- wpx = self.config_getint(
- 'wordwrappoint.x',
- self.config_getint('validrect.right', -14))
+ origin_x = self.__get_with_scaling(
+ 'origin.x', int,
+ self.__get_with_scaling(
+ 'zeropoint.x', int,
+ self.__get_with_scaling('validrect.left', int, 14)))
+ origin_y = self.__get_with_scaling(
+ 'origin.y', int,
+ self.__get_with_scaling(
+ 'zeropoint.y', int,
+ self.__get_with_scaling('validrect.top', int, 14)))
+ wpx = self.__get_with_scaling(
+ 'wordwrappoint.x', int,
+ self.__get_with_scaling('validrect.right', int, -14))
if wpx > 0:
line_width = wpx - origin_x
elif wpx < 0:
line_width = self.width - origin_x + wpx
else:
line_width = self.width - origin_x * 2
- wpy = self.config_getint('validrect.bottom', -14)
+ wpy = self.__get_with_scaling('validrect.bottom', int, -14)
if wpy > 0:
text_height = min(wpy, self.height) - origin_y
elif wpy < 0:
self.sstp_region = (x, y, w, h)
def update_line_regions(self, offset, new_y):
- origin_y = self.config_getint(
- 'origin.y',
- self.config_getint('zeropoint.y',
- self.config_getint('validrect.top', 14)))
- wpy = self.config_getint('validrect.bottom', -14)
+ origin_y = self.__get_with_scaling(
+ 'origin.y', int,
+ self.__get_with_scaling(
+ 'zeropoint.y', int,
+ self.__get_with_scaling('validrect.top', int, 14)))
+ wpy = self.__get_with_scaling('validrect.bottom', int, -14)
if wpy > 0:
text_height = min(wpy, self.height) - origin_y
elif wpy < 0:
if self.__shown:
self.update_gc()
if reset_position:
- self.__sakura.position_balloons()
+ self.callback['position_balloons']()
def set_direction(self, dir):
if self.direction != dir:
def config_adjust(self, name, base, default_value):
path, config = self.balloon[self.balloon_id]
- value = config.getint(name)
+ value = config.get_with_type(name, int)
if value is None:
- value = self.desc.getint(name)
+ value = self.desc.get_with_type(name, int)
if value is None:
value = default_value
if value < 0:
value = base + value
return int(value * self.get_scale() / 100)
- def config_getint(self, name, default_value):
+ def __get_with_scaling(self, name, conv, default_value):
path, config = self.balloon[self.balloon_id]
- value = config.getint(name)
+ value = config.get_with_type(name, conv)
if value is None:
- value = self.desc.getint(name)
+ value = self.desc.get_with_type(name, conv)
if value is None:
value = default_value
- return int(value * self.get_scale() / 100)
+ return conv(value * self.get_scale() / 100)
def __move(self):
x, y = self.get_position()
return self.position
def destroy(self, finalize=0):
- for tag in self.callbacks:
- self.darea.disconnect(tag)
self.window.remove(self.darea)
self.darea.destroy()
self.window.destroy()
def is_shown(self):
- if self.__shown:
- return 1
- else:
- return 0
+ return 1 if self.__shown else 0
def show(self):
- if not self.__shown:
- self.window.show()
- self.__shown = 1
- # make sure window is in its position
- self.__move()
- self.update_gc()
- self.raise_()
+ if self.__shown:
+ return
+ self.window.show()
+ self.__shown = 1
+ # make sure window is in its position
+ self.__move()
+ self.update_gc()
+ self.raise_()
def hide(self):
- if self.__shown:
- self.window.hide()
- self.__shown = 0
- self.images = []
+ if not self.__shown:
+ return
+ self.window.hide()
+ self.__shown = 0
+ self.images = []
def raise_(self):
if self.__shown:
x, y = self.arrow[1]
w, h = self.arrow1_pixbuf[2]
if self.lineno + self.lines < len(self.text_buffer) or \
- self.__sakura.is_paused():
+ self.callback['is_paused']():
self.darea.window.draw_pixbuf(
self.arrow1_gc, self.arrow1_pixbuf[0], 0, 0, x, y, w, h)
elif clear:
if self.selection != new_selection:
sl, sn, el, en, link_id, raw_text, text = \
self.link_buffer[new_selection]
- self.__sakura.notify_event(
+ self.callback['notify_event'](
'OnChoiceEnter', raw_text, link_id, self.selection)
else:
if self.selection is not None:
- self.__sakura.notify_event('OnChoiceEnter')
+ self.callback['notify_event']('OnChoiceEnter')
if new_selection == self.selection:
return 0
else:
return True
def button_press(self, darea, event):
- self.__sakura.reset_idle_time()
- if event.type == gtk.gdk.BUTTON_PRESS:
- click = 1
- else:
- click = 2
- if self.__sakura.is_paused():
- self.__sakura.notify_balloon_click(event.button, click, self.side)
+ self.callback['reset_idle_time']()
+ click = 1 if event.type == gtk.gdk.BUTTON_PRESS else 2
+ if self.callback['is_paused']():
+ self.callback['notify_balloon_click'](event.button, click, self.side)
return True
# arrows
px = int(event.x)
if self.selection is not None:
sl, sn, el, en, link_id, raw_text, text = \
self.link_buffer[self.selection]
- self.__sakura.notify_link_selection(
+ self.callback['notify_link_selection'](
link_id, raw_text, self.selection)
return True
# balloon's background
- self.__sakura.notify_balloon_click(event.button, click, self.side)
+ self.callback['notify_balloon_click'](event.button, click, self.side)
return True
def clear_text(self):
NAME = ''
ENTRY = ''
- def __init__(self, balloon, sakura, debug):
- self.balloon = balloon
- self.sakura = sakura
+ def __init__(self, callback, debug):
+ self.callback = callback
self.debug = debug
self.window = None
self.window.set_modal(True)
self.window.set_position(gtk.WIN_POS_CENTER)
self.window.realize()
- w = desc.getint('communicatebox.width', 250)
- h = desc.getint('communicatebox.height', -1)
+ w = desc.get_with_type('communicatebox.width', int, 250)
+ h = desc.get_with_type('communicatebox.height', int, -1)
self.entry = gtk.Entry()
self.entry.connect('activate', self.activate)
self.entry.set_size_request(w, h)
gtk_image.set_padding(0, 0)
gtk_image.set_from_pixmap(image, mask)
gtk_image.show()
- x = desc.getint('communicatebox.x', 10)
- y = desc.getint('communicatebox.y', 20)
+ x = desc.get_with_type('communicatebox.x', int, 10)
+ y = desc.get_with_type('communicatebox.y', int, 20)
fixed = gtk.Fixed()
fixed.put(gtk_image, 0, 0)
fixed.put(self.entry, x, y)
def delete(self, widget, event):
self.window.hide()
self.cancel()
- self.balloon.reset_user_interaction()
+ self.callback['reset_user_interaction']()
return True
def key_press(self, widget, event):
if event.keyval == gtk.keysyms.Escape:
self.window.hide()
self.cancel()
- self.balloon.reset_user_interaction()
+ self.callback['reset_user_interaction']()
return True
return False
if data:
data = unicode(data, 'utf-8')
if data is not None:
- self.sakura.notify_event('OnCommunicate', 'user', data)
+ self.callback['notify_event']('OnCommunicate', 'user', data)
class TeachBox(CommunicateWindow):
def send(self, data):
if data:
data = unicode(data, 'utf-8')
- self.sakura.notify_user_teach(data)
- self.balloon.reset_user_interaction()
+ self.callback['notify_user_teach'](data)
+ self.callback['reset_user_interaction']()
class InputBox(CommunicateWindow):
data = ''
## CHECK: symbol
if self.symbol == 'OnUserInput' and \
- self.sakura.notify_event('OnUserInput', data):
+ self.callback['notify_event']('OnUserInput', data):
pass
- elif self.sakura.notify_event('OnUserInput', self.symbol, data):
+ elif self.callback['notify_event']('OnUserInput', self.symbol, data):
pass
- elif self.sakura.notify_event(self.symbol, data):
+ elif self.callback['notify_event'](self.symbol, data):
pass
- self.balloon.reset_user_interaction()
+ self.callback['reset_user_interaction']()
def test():
class Config(dict):
+ def get_with_type(self, name, conv, default=None):
+ value = self.get(name)
+ if value is None:
+ return default
+ ##assert conv is not None
+ try:
+ return conv(value)
+ except ValueError:
+ return default # XXX
+
def get(self, name, default=None):
keylist = name if isinstance(name, list) else [name]
for key in keylist:
return self[key]
return default
- def getint(self, name, default=None):
- value = self.get(name)
- if value:
- try:
- return int(value)
- except ValueError:
- pass
- return default
-
- def getfloat(self, name, default=None):
- value = self.get(name)
- if value:
- try:
- return float(value)
- except ValueError:
- pass
- return default
-
def __str__(self):
buf = []
for item in self.iteritems():
class SAORI:
+ RESPONSE = {204: 'SAORI/1.0 204 No Content\r\n\r\n',
+ 400: 'SAORI/1.0 400 Bad Request\r\n\r\n',
+ 500: 'SAORI/1.0 500 Internal Server Error\r\n\r\n',
+ }
+
def __init__(self):
self.loaded = 0
def request(self, req):
req_type, argument = self.evaluate_request(req)
if not req_type:
- return 'SAORI/1.0 400 Bad Request\r\n\r\n'
+ return self.RESPONSE[400]
elif req_type == 'GET Version':
- return 'SAORI/1.0 204 No Content\r\n\r\n'
+ return self.RESPONSE[204]
elif req_type == 'EXECUTE':
result = self.execute(argument)
- if result is None:
- return 'SAORI/1.0 204 No Content\r\n\r\n'
- else:
- return result
+ return self.RESPONSE[204] if result is None else result
else:
- return 'SAORI/1.0 400 Bad Request\r\n\r\n'
+ return self.RESPONSE[400]
def execute(self, args):
return None
if self.__type == 'saori':
if getattr(module, 'Saori', None):
saori = module.Saori()
- saori.prefs = self.__sakura.prefs
if getattr(saori, 'need_ghost_backdoor', None):
saori.need_ghost_backdoor(self.__sakura)
else:
def execute(self, argument):
if not argument:
- return 'SAORI/1.0 400 Bad Request\r\n\r\n'
+ return self.RESPONSE[400]
name = argument[0]
text = argument[1] if len(argument) >= 2 else ''
if len(argument) >= 3:
del bln[bln_id]
if text:
if update == 0 or bln_id not in bln:
- bln[bln_id] = Balloon(self.__sakura, self.prefs, self.dir,
+ bln[bln_id] = Balloon(self.__sakura, self.dir,
data, text,
offset_x, offset_y, name, bln_id)
else:
class Balloon:
- def __init__(self, sakura, prefs, dir, data,
+ def __init__(self, sakura, dir, data,
text, offset_x, offset_y, name, bln_id):
self.dir = dir
self.__sakura = sakura
- self.prefs = prefs
self.name = name
self.id = bln_id
self.data = data # XXX
return talking
def get_sakura_status(self, key):
- if key == 'SurfaceScale': ## FIXME
- result = self.prefs.get('surface_scale')
+ if key == 'SurfaceScale':
+ result = self.__sakura.get_surface_scale()
elif key == 'SurfaceSakura_Shown':
result = int(self.__sakura.surface_is_shown(0))
elif key == 'SurfaceSakura':
s1_x, s1_y = 0, 0
s1_w, s1_h = 0, 0
result = s1_x, s1_y, s1_w, s1_h
- elif key == 'BalloonScale': ## FIXME
- if self.prefs.get('balloon_scalling'):
- result = self.prefs.get('surface_scale')
- else:
- result = 100
elif key == 'BalloonSakura_Shown':
result = int(self.__sakura.balloon_is_shown(0))
elif key == 'BalloonSakura':
self.life_time = 300000
else:
if self.visible:
- if self.position == 'sakura' and not s0_shown:
- self.destroy()
- return None
- if self.position == 'kero' and not s1_shown:
- self.destroy()
- return None
- if self.position == 'sakurab' and not b0_shown:
- self.destroy()
- return None
- if self.position == 'kerob' and not b1_shown:
- self.destroy()
- return None
- if self.nooverlap and \
- not self.talking and sakura_talking:
+ if (self.position == 'sakura' and not s0_shown) or \
+ (self.position == 'kero' and not s1_shown) or \
+ (self.position == 'sakurab' and not b0_shown) or \
+ (self.position == 'kerob' and not b1_shown) or \
+ (self.nooverlap and not self.talking and sakura_talking):
self.destroy()
return None
else:
int(self.y + self.action_y + self.vy))
if self.processed_script or self.processed_text:
self.interpret_script()
- if self.talking and not sakura_talking:
- self.talking = 0
- else:
- self.talking = sakura_talking
+ self.talking = 0 if self.talking and not sakura_talking else sakura_talking
return True
def redraw(self, widget, event):
def execute(self, argument):
if not argument:
- return 'SAORI/1.0 400 Bad Request\r\n\r\n'
+ return self.RESPONSE[400]
command = argument[0]
if command == 'show':
if len(argument) >= 2:
else:
name = ''
if name not in self.data:
- return 'SAORI/1.0 400 Bad Request\r\n\r\n'
+ return self.RESPONSE[400]
if 'graph' in self.data[name] and \
self.data[name]['graph'] in ['line', 'bar',
'radar', 'radar2']:
if name in self.graphs:
self.graphs[name].destroy()
else:
- return 'SAORI/1.0 400 Bad Request\r\n\r\n'
+ return self.RESPONSE[400]
else:
- return 'SAORI/1.0 400 Bad Request\r\n\r\n'
- return 'SAORI/1.0 204 No Content\r\n\r\n'
+ return self.RESPONSE[400]
+ return self.RESPONSE[204]
class Graph:
def get(self, url, start=None, end=None):
url = urlparse.urlparse(url)
if not (url[0] == 'http' and url[3] == url[4] == url[5] == ''):
- return 'SAORI/1.0 400 Bad Request\r\n\r\n'
+ return self.RESPONSE[400]
conn = httplib.HTTPConnection(url[1])
conn.request("GET", url[2])
res = conn.getresponse()
+ if res.status != 200: # XXX
+ return []
data = res.read()
c_type = res.getheader('content-type')
if c_type:
if argument[0] == 'bg':
if len(argument) < 2:
# 'bgするならIDを指定していただけませんと。'
- return 'SAORI/1.0 400 Bad Request\r\n\r\n'
+ return self.RESPONSE[400]
bg = argument[1]
argument = argument[2:]
if len(argument) >= 1:
return 'SAORI/1.0 200 OK\r\n' \
'Result: %s\r\n\r\n' % self.loaded # XXX
elif len(argument) > 3:
- return 'SAORI/1.0 400 Bad Request\r\n\r\n'
+ return self.RESPONSE[400]
elif len(argument) == 2: # FIXME: not supported yet
return 'SAORI/1.0 200 OK\r\n' \
'Result: 0\r\n\r\n'
return None # 'SAORI/1.0 204 No Content\r\n\r\n'
else:
data = self.get(*argument)
+ if not data:
+ return None # 'SAORI/1.0 204 No Content\r\n\r\n'
result = 'SAORI/1.0 200 OK\r\n' \
'Result: %s\r\n' % \
data[0].encode('Shift_JIS', 'replace')
if self.state == 2:
self.state = 1
self.player.set_state(gst.STATE_PLAYING)
- return 'SAORI/1.0 204 No Content\r\n\r\n'
+ return self.RESPONSE[204]
elif self.state == 1:
self.state = 2
self.player.set_state(gst.STATE_PAUSED)
- return 'SAORI/1.0 204 No Content\r\n\r\n'
+ return self.RESPONSE[204]
if os.path.isfile(self.filepath):
self.player.set_property("uri", "file://" + self.filepath)
self.player.set_state(gst.STATE_PLAYING)
self.player.set_state(gst.STATE_NULL)
filename = argv[1].replace('\\', '/').lower()
if os.path.isabs(filename):
- return 'SAORI/1.0 400 Bad Request\r\n\r\n'
+ return self.RESPONSE[400]
self.filepath = os.path.join(self.__sakura.get_prefix(),
'ghost/master', self.dir,
filename)
- return 'SAORI/1.0 204 No Content\r\n\r\n'
+ return self.RESPONSE[204]
def on_message(self, bus, message):
t = message.type
if self.state == 2:
self.state = 1
self.player.set_state(gst.STATE_PLAYING)
- return 'SAORI/1.0 204 No Content\r\n\r\n'
+ return self.RESPONSE[204]
elif self.state == 1:
self.state = 2
self.player.set_state(gst.STATE_PAUSED)
- return 'SAORI/1.0 204 No Content\r\n\r\n'
+ return self.RESPONSE[204]
if os.path.isfile(self.filepath):
self.player.set_property("uri", "file://" + self.filepath)
self.player.set_state(gst.STATE_PLAYING)
if not os.path.isabs(filename): # XXX
filename = filename.lower()
self.filepath = os.path.join(self.dir, filename)
- return 'SAORI/1.0 204 No Content\r\n\r\n'
+ return self.RESPONSE[204]
def on_message(self, bus, message):
t = message.type
def execute(self, argument):
if not argument:
- return 'SAORI/1.0 400 Bad Request\r\n\r\n'
+ return self.RESPONSE[400]
if argument[0] == 'START':
if len(argument) < 7:
- return 'SAORI/1.0 400 Bad Request\r\n\r\n'
+ return self.RESPONSE[400]
try:
assert argument[2] in ['ACTIVE', 'FIX'] or \
argument[2].stratswith('@') or \
assert position in ['TOP', 'LEFT', 'RIGHT', 'BOTTOM']
self.settings['except'] = (target, position)
except:
- return 'SAORI/1.0 400 Bad Request\r\n\r\n'
+ return self.RESPONSE[400]
#self.timeout_id = gobject.timeout_add(self.settings['timeout'], self.do_idle_tasks)
self.timeout_id = gobject.timeout_add(100, self.do_idle_tasks)
- return 'SAORI/1.0 204 No Content\r\n\r\n'
+ return self.RESPONSE[204]
elif argument[0] == 'STOP':
if self.timeout_id is not None:
gobject.source_remove(self.timeout_id)
self.timeout_id = None
self.settings = {}
- return 'SAORI/1.0 204 No Content\r\n\r\n'
+ return self.RESPONSE[204]
else:
- return 'SAORI/1.0 400 Bad Request\r\n\r\n'
+ return self.RESPONSE[400]
def do_idle_tasks(self):
if self.timeout_id is None:
if not target_flag[0]:
return target_flag[1]
pos = self.settings['position']
- scale = self.prefs.get('surface_scale')
+ scale = self.__sakura.get_surface_scale()
offset_x = int(self.settings['offset_x'] * scale / 100)
offset_y = int(self.settings['offset_y'] * scale / 100)
if self.settings['hwnd'].startswith('s'):
def execute(self, argument):
if not argument:
- return 'SAORI/1.0 400 Bad Request\r\n\r\n'
+ return self.RESPONSE[400]
if len(argument) > 1 and argument[1] == 0:
- return 'SAORI/1.0 204 No Content\r\n\r\n'
+ return self.RESPONSE[204]
value = ''
if argument[0] == 'platform':
value = sys.platform ## os.name
if value:
return 'SAORI/1.0 200 OK\r\nResult: %s\r\n\r\n' % value
else:
- return 'SAORI/1.0 204 No Content\r\n\r\n'
+ return self.RESPONSE[204]
def request(self, req):
req_type, argument, charset = self.evaluate_request(req)
if not req_type:
- return 'SAORI/1.0 400 Bad Request\r\n\r\n'
+ return self.RESPONSE[400]
elif req_type == 'GET Version':
- return 'SAORI/1.0 204 No Content\r\n\r\n'
+ return self.RESPONSE[204]
elif req_type == 'EXECUTE':
if argument[0] not in self.function:
- return 'SAORI/1.0 400 Bad Request\r\n\r\n'
+ return self.RESPONSE[400]
name = argument[0]
argument = argument[1:]
if self.function[name][1] == [None]:
pass
elif len(argument) not in self.function[name][1]:
- return 'SAORI/1.0 400 Bad Request\r\n\r\n'
+ return self.RESPONSE[400]
self.value = []
result = self.function[name][0](argument, charset)
if result is not None and result != '':
s = ''.join((s, '\r\n'))
return s
else:
- return 'SAORI/1.0 204 No Content\r\n\r\n'
+ return self.RESPONSE[204]
else:
- return 'SAORI/1.0 400 Bad Request\r\n\r\n'
+ return self.RESPONSE[400]
def ssu_is_empty(self, args, charset):
if not args:
def execute(self, argument):
if not argument or self.clipboard is None:
- return 'SAORI/1.0 400 Bad Request\r\n\r\n'
+ return self.RESPONSE[400]
text = argument[0].encode('utf-8')
self.clipboard.set_text(text)
if len(argument) >= 2 and argument[1] != 0:
'Result: %s\r\n\r\n' % \
argument[0].encode(self.charset, 'replace')
else:
- return 'SAORI/1.0 204 No Content\r\n\r\n'
+ return self.RESPONSE[204]
req_type, argument = self.evaluate_request(req)
if not req_type:
- result = 'SAORI/1.0 400 Bad Request\r\n\r\n'
+ result = self.RESPONSE[400]
elif req_type == 'GET Version':
- result = 'SAORI/1.0 204 No Content\r\n\r\n'
+ result = self.RESPONSE[204]
elif req_type == 'EXECUTE':
if not argument:
- result = 'SAORI/1.0 400 Bad Request\r\n\r\n'
+ result = self.RESPONSE[400]
elif not self.__check_argument(argument):
- result = 'SAORI/1.0 400 Bad Request\r\n\r\n'
+ result = self.RESPONSE[400]
else:
name = argument[0]
if name == 'GET_POSITION':
elif argument[1] == self.kero_name: ## FIXME: HWND
side = 1
else:
- return 'SAORI/1.0 400 Bad Request\r\n\r\n'
+ return self.RESPONSE[400]
try:
x, y = self.__sakura.get_surface_position(side)
w, h = self.__sakura.get_surface_size(side)
'Value1: %d\r\n' \
'Value2: %d\r\n\r\n' % (x, x, x + w / 2, x + w)
except:
- result = 'SAORI/1.0 500 Internal Server Error\r\n\r\n'
+ result = self.RESPONSE[500]
elif name == 'GET_DESKTOP_SIZE':
try:
left, top, scrn_w, scrn_h = ninix.pix.get_workarea()
'Value0: %d\r\n' \
'Value1: %d\r\n\r\n' % (scrn_w, scrn_w, scrn_h)
except:
- result = 'SAORI/1.0 500 Internal Server Error\r\n\r\n'
+ result = self.RESPONSE[500]
else:
self.enqueue_commands(name, argument[1:])
if self.timeout_id is None:
self.do_idle_tasks()
- result = 'SAORI/1.0 204 No Content\r\n\r\n'
+ result = self.RESPONSE[204]
else:
- result = 'SAORI/1.0 400 Bad Request\r\n\r\n'
+ result = self.RESPONSE[400]
return result
def enqueue_commands(self, command, args):
class Menu:
- def __init__(self, kinoko, accelgroup):
- self.__kinoko = kinoko
+ def __init__(self, callback, accelgroup):
+ self.callback = callback
ui_info = '''
<ui>
<popup name='popup'>
'''
self.__menu_list = {
'settings': [('Settings', None, ('Settings...(_O)'), None,
- '', self.__kinoko.edit_preferences),
+ '', self.callback['edit_preferences']),
'/ui/popup/Settings'],
'skin': [('Skin', None, _('Skin(_K)'), None),
None, '/ui/popup/Skin'],
'exit': [('Exit', None, _('Exit(_Q)'), None,
- '', self.__kinoko.close),
+ '', self.callback['close']),
'/ui/popup/Exit'],
}
self.__skin_list = None
self.__menu_list[key][1] = ui_manager.get_widget(path)
def popup(self, button):
- skin_list = self.__kinoko.get_skin_list()
+ skin_list = self.callback['get_skin_list']()
self.__set_skin_menu(skin_list)
self.__popup_menu.popup(
None, None, None, button, gtk.get_current_event_time())
menu = gtk.Menu()
for skin in list:
item = gtk.MenuItem(skin['title'])
- item.connect('activate', self.__kinoko.select_skin, (skin))
+ item.connect('activate', self.callback['select_skin'], (skin))
menu.add(item)
item.show()
self.__menu_list[key][1].set_submenu(menu)
else:
self.__menu_list[key][1].hide()
+
class Nayuki:
- def __init__(self, kinoko):
- self.kinoko = kinoko
+ def __init__(self):
+ pass
+
class Kinoko:
if event in ['set position', 'set surface']:
self.skin.set_position()
self.skin.show()
- elif event == 'set scale': ## FIXME
- scale = self.target.prefs.get('surface_scale')
+ elif event == 'set scale':
+ scale = self.target.get_surface_scale()
self.skin.set_scale(scale)
elif event == 'hide':
if not self.target.surface_is_shown(0):
##print 'OBSERVER(kinoko): ignore -', event
pass
+ def load_skin(self):
+ scale = self.target.get_surface_scale()
+ skin_callback ={
+ 'edit_preferences': self.edit_preferences,
+ 'close': self.close,
+ 'get_skin_list': self.get_skin_list,
+ 'select_skin': self.select_skin,
+ 'get_target_window': lambda *a: self.target.surface.window[0].window, # XXX
+ 'get_kinoko_position': self.target.get_kinoko_position,
+ }
+ self.skin = Skin(self.data, self.accelgroup, skin_callback, scale)
+
def load(self, data, target):
self.data = data
self.target = target
self.target.set_observer(self)
self.accelgroup = gtk.AccelGroup()
- scale = self.target.prefs.get('surface_scale')
- self.skin = Skin(self.data, self.accelgroup, self, scale)
+ self.load_skin()
if self.skin is None:
return 0
else:
self.send_event('OnKinokoObjectChanging')
self.skin.destroy()
self.data = args
- scale = self.target.prefs.get('surface_scale')
- self.skin = Skin(self.data, self.accelgroup, self, scale)
+ self.load_skin()
if self.skin is None:
return 0
else:
self.send_event('OnKinokoObjectChanged')
return 1
+
class Skin:
- def __init__(self, data, accelgroup, kinoko, scale):
+ def __init__(self, data, accelgroup, callback, scale):
self.frame_buffer = []
self.data = data
self.accelgroup = accelgroup
- self.kinoko = kinoko
- self.__menu = Menu(self.kinoko, self.accelgroup)
+ self.callback = callback
+ menu_callback ={}
+ for key in ['edit_preferences', 'close',
+ 'get_skin_list', 'select_skin']:
+ menu_callback[key] = self.callback[key]
+ self.__menu = Menu(menu_callback, self.accelgroup)
self.__scale = scale
self.__shown = 0
self.surface_id = 0 # dummy
w, h, gtk.gdk.INTERP_BILINEAR)
image, mask = surface_pixbuf.render_pixmap_and_mask(255)
except: ## FIXME
- self.kinoko.close(None)
+ self.callback['close'](None)
return
## FIXME
self.w, self.h = image.get_size()
self.window.add(self.darea)
self.darea.realize()
self.darea.window.set_back_pixmap(image, False)
- target_window = self.kinoko.target.surface.window[0].window # XXX
+ target_window = self.callback['get_target_window']()
if self.data['ontop']:
self.window.set_transient_for(target_window)
else:
self.seriko.append_actor(frame, actor)
def set_position(self, xoffset=0, yoffset=0):
- base_x, base_y = self.kinoko.target.get_kinoko_position(
+ base_x, base_y = self.callback['get_kinoko_position'](
self.data['baseposition'])
a, b = [(0.5, 1), (0.5, 0), (0, 0.5), (1, 0.5), (0, 1),
(1, 1), (0, 0), (1, 0), (0.5, 0.5)][self.data['baseadjust']]
self.seriko.invoke(self, actor_id, update)
def delete(self, widget, event):
- self.kinoko.close(None)
+ self.callback['close'](None)
def destroy(self): ## FIXME
self.seriko.terminate(self)
import ninix.sstp
import ninix.communicate
import ninix.ngm
+import ninix.plugin
import ninix.nekodorif
import ninix.kinoko
raise SystemExit, 'Error: cannot open display (abort)\n'
# parse command line arguments
try:
- options, rest = getopt.getopt(sys.argv[1:], 'H:U:R:ph',
+ options, rest = getopt.getopt(sys.argv[1:], 'H:U:h',
['homedir=', 'userdir=', 'sstp-port=', 'debug=', 'help'])
except getopt.error, e:
sys.stderr.write('Error: %s\n' % str(e))
lockfile.close()
+class SSTPControler:
-class Application:
-
- def __init__(self, config, sstp_port=[9801, 11000], debug=0):
- self.ghosts, self.shells, self.balloons, self.plugins, \
- self.nekoninni, self.katochan, self.kinoko = config
+ def __init__(self, callback, sstp_port):
+ self.callback = callback
self.sstp_port = sstp_port
- self.debug = debug
- self.plugin_pids = []
self.sstp_servers = []
self.__sstp_queue = []
self.__sstp_flag = 0
self.__current_sender = None
- # create preference dialog
- self.prefs = ninix.prefs.PreferenceDialog(self)
- # create usage dialog
- self.usage_dialog = UsageDialog()
- self.__communicate = ninix.communicate.Communicate()
- # create ghost manager
- self.__ngm = ninix.ngm.NGM(self)
def enqueue_script_if_ghost(self, if_ghost, script, sender, handle,
address, show_sstp_marker,
(if_ghost, script, sender, handle, address, show_sstp_marker,
use_translator, entry_db))
+ def check_request_queue(self, sender):
+ count = 0
+ for request in self.__sstp_queue:
+ if request[2].split(' / ')[0] == sender.split(' / ')[0]:
+ count += 1
+ if self.__sstp_flag and \
+ self.__current_sender.split(' / ')[0] == sender.split(' / ')[0]:
+ count += 1
+ return str(count), str(len(self.__sstp_queue))
+
def set_sstp_flag(self, sender):
self.__sstp_flag = 1
self.__current_sender = sender
def handle_sstp_queue(self):
if self.__sstp_flag or not self.__sstp_queue:
return
- if_ghost = self.__sstp_queue[0][0]
- sakura = self.get_ghost(if_ghost)
- if sakura is not None:
- self.select_current_sakura(if_ghost)
- elif not self.prefs.get('allowembryo'): # Refuse
- self.__sstp_queue.pop(0)
- return
if_ghost, script, sender, handle, address, show_sstp_marker, \
use_translator, entry_db = self.__sstp_queue.pop(0)
+ if not self.callback['if_ghost'](if_ghost) and \
+ not self.callback['get_preference']('allowembryo'): # Refuse
+ return
+ self.callback['select_current_sakura'](if_ghost)
self.set_sstp_flag(sender)
- sakura = self.ghost_list[self.current_sakura[1]]['instance']
- sakura.enter_temp_mode()
- sakura.enqueue_script(script, sender, handle, address,
- show_sstp_marker, use_translator, entry_db)
+ self.callback['enqueue_script'](
+ script, sender, handle, address,
+ show_sstp_marker, use_translator, entry_db, temp_mode=True)
def receive_sstp_request(self):
try:
except ValueError: # may happen when ninix is terminated
return
+ def get_sstp_port(self):
+ if not self.sstp_servers:
+ return None
+ return self.sstp_servers[0].server_address[1]
+
+ def quit(self):
+ for server in self.sstp_servers:
+ server.close()
+
+ def start_servers(self):
+ for port in self.sstp_port:
+ sstp_callback = {
+ 'enqueue_script_if_ghost': self.enqueue_script_if_ghost,
+ 'check_request_queue': self.check_request_queue,
+ }
+ for key in ['get_sakura_cantalk', 'get_event_response',
+ 'if_ghost', 'keep_silence',
+ 'get_ghost_names', 'get_ghost_name',
+ 'enqueue_event', 'enqueue_script']:
+ sstp_callback[key] = self.callback[key]
+ try:
+ server = ninix.sstp.SSTPServer(('', port), sstp_callback)
+ except socket.error, (code, message):
+ sys.stderr.write('Port %d: %s (ignored)\n' % (port, message))
+ continue
+ self.sstp_servers.append(server)
+ print 'Serving SSTP on port', port
+
+
+class Application(object):
+
+ def __init__(self, config, sstp_port=[9801, 11000], debug=0):
+ self.ghosts, self.shells, self.balloons, self.plugins, \
+ self.nekoninni, self.katochan, self.kinoko = config ## FIXME
+ self.debug = debug
+ # create preference dialog
+ prefs_callback = {
+ 'notify_preference_changed': self.notify_preference_changed,
+ 'get_balloons': self.get_balloons,
+ }
+ self.prefs = ninix.prefs.PreferenceDialog(prefs_callback)
+ sstp_controler_callback = {
+ 'get_sakura_cantalk': self.get_sakura_cantalk,
+ 'get_event_response': self.get_event_response,
+ 'if_ghost': self.if_ghost,
+ 'keep_silence': self.keep_silence,
+ 'get_ghost_names': self.get_ghost_names,
+ 'get_ghost_name': self.get_ghost_name,
+ 'enqueue_event': self.enqueue_event,
+ 'enqueue_script': self.enqueue_script,
+ 'select_current_sakura': self.select_current_sakura,
+ 'get_preference': self.prefs.get,
+ }
+ self.sstp_controler = SSTPControler(sstp_controler_callback, sstp_port)
+ plugin_callback = {
+ 'get_sstp_port': self.sstp_controler.get_sstp_port,
+ }
+ self.plugin_controler = ninix.plugin.PluginControler(
+ self.plugins, plugin_callback)
+ # create usage dialog
+ self.usage_dialog = UsageDialog()
+ self.communicate = ninix.communicate.Communicate()
+ # create ghost manager
+ ngm_callback = {
+ 'update_sakura': self.update_sakura,
+ }
+ self.__ngm = ninix.ngm.NGM(ngm_callback)
+ self.current_sakura = property(self._get_current_sakura,
+ self._set_current_sakura)
+
+ def _set_current_sakura(self, item):
+ print 'DEBUG(_set_current_sakura):', item
+ self._current_sakura = item
+ self.prefs.set_curretn_sakura(self.get_current_sakura_name())
+
+ def _get_current_sakura(self):
+ print 'DEBUG(_get_current_sakura):', self._current_sakura
+ return self._current_sakura
+
def create_ghost(self, data, debug):
default_path = os.path.join(os.environ['PYTHONPATH'], 'ninix/dll')
- return ninix.sakura.Sakura(self, data, default_path,
- self.__communicate, debug)
+ sakura_callback = {
+ 'change_sakura': self.change_sakura,
+ 'close_all': self.close_all_ghosts,
+ 'close_ghost': self.close_ghost,
+ 'edit_preferences': self.prefs.edit_preferences,
+ 'find_balloon_by_name': self.find_balloon_by_name,
+ 'get_preference': self.prefs.get,
+ 'get_balloon_list': self.get_balloon_list,
+ 'get_balloon_description': self.get_balloon_description,
+ 'get_ghost_list': self.get_ghost_list,
+ 'get_kinoko_list': self.get_kinoko_list,
+ 'get_nekodorif_list': self.get_nekodorif_list,
+ 'get_plugin_list': self.get_plugin_list,
+ 'get_shell_list': self.get_shell_list,
+ 'get_otherghostname': self.communicate.get_otherghostname,
+ 'open_ghost_manager': self.open_ghost_manager,
+ 'rebuild_ghostdb': self.communicate.rebuild_ghostdb,
+ 'reset_sstp_flag': self.sstp_controler.reset_sstp_flag,
+ 'request_shell': self.request_shell,
+ 'request_balloon': self.request_balloon,
+ 'show_usage': self.show_usage,
+ 'select_plugin': self.select_plugin,
+ 'select_kinoko': self.select_kinoko,
+ 'select_nekodorif': self.select_nekodorif,
+ 'select_ghost': self.select_ghost,
+ 'select_ghost_by_name': self.select_ghost_by_name,
+ 'select_shell_by_name': self.select_shell_by_name,
+ 'start_sakura': self.start_sakura_cb,
+ 'stop_sakura': self.stop_sakura,
+ 'select_current_sakura': self.select_current_sakura,
+ 'send_message': self.communicate.send_message,
+ 'update_sakura': self.update_sakura,
+ 'vanish_sakura': self.vanish_sakura,
+ }
+ return ninix.sakura.Sakura(data, default_path, sakura_callback, debug)
+
+ def get_sakura_cantalk(self):
+ sakura = self.get_current_sakura_instance()
+ return sakura.cantalk
+
+ def get_event_response(self, event, *arglist, **argdict):
+ sakura = self.get_current_sakura_instance()
+ return sakura.get_event_response(*event)
+
+ def keep_silence(self, quiet):
+ sakura = self.get_current_sakura_instance()
+ sakura.keep_silence(quiet)
+
+ def get_ghost_name(self):
+ sakura = self.get_current_sakura_instance()
+ return '%s,%s' % (sakura.get_selfname(), sakura.get_keroname())
+
+ def enqueue_event(self, event, *arglist, **argdict):
+ sakura = self.get_current_sakura_instance()
+ sakura.enqueue_event(event, *arglist, **argdict)
+
+ def enqueue_script(self, script, sender, handle,
+ host, show_sstp_marker, use_translator,
+ db=None, request_handler=None, temp_mode=False):
+ sakura = self.get_current_sakura_instance()
+ if temp_mode:
+ sakura.enter_temp_mode()
+ sakura.enqueue_script(script, sender, handle,
+ host, show_sstp_marker, use_translator,
+ db, request_handler)
def get_working_ghost(self, cantalk=0):
working_list = [item['instance'] for item in self.ghost_list \
icon_path = None
if icon_path is not None:
try:
- pixbuf = ninix.pix.create_pixbuf_from_file(icon_path, is_pnr=0)
+ pixbuf = ninix.pix.create_pixbuf_from_file(
+ icon_path, is_pnr=False)
except:
pixbuf = None
if pixbuf is not None:
set_list.append(item)
return set_list
+ def get_balloons(self):
+ return self.balloons
+
def get_balloon_list(self): ## FIXME
balloon_list = []
for i in range(len(self.balloons)):
balloon_list.append(item)
return balloon_list
- def get_plugin_list(self):
- plugin_list = []
- for i, plugin in enumerate(self.plugins):
- plugin_name = plugin[0]
- if not menu_items:
- continue
- item = {}
- item['name'] = plugin_name
- item['icon'] = None
- item_list = []
- menu_items = plugin[3]
- for j, menu_item in enumerate(menu_items):
- label = menu_item[0]
- value = (i, j)
- item_list.append((label, value))
- item['items'] = item_list
- plugin_list.append(item)
- return plugin_list
+ def get_plugin_list(self): ## FIXME
+ return self.plugin_controler.get_plugin_list()
def get_nekodorif_list(self):
nekodorif_list = []
def run(self): ## FIXME
self.load()
# set SIGCHLD handler
- signal.signal(signal.SIGCHLD, self.terminate_plugin)
+ signal.signal(signal.SIGCHLD, self.plugin_controler.terminate_plugin)
# start SSTP server
- for port in self.sstp_port:
- try:
- server = ninix.sstp.SSTPServer(('', port), self)
- except socket.error, (code, message):
- sys.stderr.write('Port %d: %s (ignored)\n' % (port, message))
- continue
- self.sstp_servers.append(server)
- print 'Serving SSTP on port', port
+ self.sstp_controler.start_servers()
# start plugins
- try:
- os.setpgid(0, 0)
- except OSError:
- pass
- for plugin_name, plugin_dir, startup, menu_items in self.plugins: ## FIXME
- if startup is not None:
- self.exec_plugin(plugin_dir, startup)
+ self.plugin_controler.start_plugins()
self.set_timeout()
gtk.main()
- def get_current_sakura(self):
+ def get_current_sakura_instance(self):
return self.ghost_list[self.current_sakura[1]]['instance']
- def check_request_queue(self, sender):
- count = 0
- for request in self.__sstp_queue:
- if request[2].split(' / ')[0] == sender.split(' / ')[0]:
- count += 1
- if self.__sstp_flag and \
- self.__current_sender.split(' / ')[0] == sender.split(' / ')[0]:
- count += 1
- return str(count), str(len(self.__sstp_queue))
-
def get_ghost_names(self): ## FIXME
name_list = []
for item in self.ghost_list: ## FIXME
else:
return 0
+ def update_sakura(self, name, sender):
+ item = self.find_ghost_by_name(name, 0)
+ if item is None:
+ return
+ sakura = self.select_ghost_from_list(item)
+ if not sakura.is_running():
+ self.start_sakura(item, init=1)
+ sakura.enqueue_script('\![updatebymyself]\e', sender,
+ None, None, 0, 0, None)
+
def select_current_sakura(self, ifghost=None):
if ifghost is not None:
for item in self.ghost_list:
break
else:
pass
+ else:
+ return
else:
working_list = self.get_working_ghost(cantalk=1)
if working_list:
self.current_sakura = random.choice(working_list).current
+ else:
+ return ## FIXME
def close_ghost(self, sakura):
if not self.get_working_ghost():
def quit(self):
gobject.source_remove(self.timeout_id)
self.usage_dialog.close()
- for server in self.sstp_servers:
- server.close()
+ self.sstp_controler.quit() ## FIXME
self.save_preferences()
gtk.main_quit()
# stop plugins
except IOError:
sys.stderr.write('Cannot write preferences to file (ignored).\n')
- def select_ghost(self, sakura, sequential, event=1):
+ def select_ghost(self, sakura, sequential, event=1, vanished=0):
if len(self.range_ghosts()) < 2:
return
+ # select another ghost
set_type, i, j = sakura.current
if set_type == 's':
i = 0
index_list = self.range_ghosts()
index_list.remove(i)
i = random.choice(index_list)
- self.change_sakura(sakura, ('g', i, 0), 'automatic', event)
+ if self.current_sakura == sakura.current: # XXX
+ self.current_sakura = ('g', i, 0)
+ self.change_sakura(sakura, ('g', i, 0), 'automatic', event, vanished)
def select_shell_by_name(self, sakura, name, event=1):
set_type, i, j = sakura.current
return
self.change_sakura(sakura, item, 'automatic', event)
- def select_sakura(self, event, args):
- sakura, item = args
- if sakura.busy(): ## FIXME
- gtk.gdk.beep()
- return
- self.change_sakura(sakura, item, 'manual')
-
def change_sakura(self, sakura, item, method, event=1, vanished=0):
set_type, i, j = item
assert self.ghosts[i] is not None
proc()
elif sakura.current[0] == set_type and sakura.current[1] == i:
assert sakura.current[2] != j
- sakura.enqueue_event('OnShellChanging', name, path, proc=proc)
+ sakura.enqueue_event('OnShellChanging', name, surface_dir, proc=proc)
else:
name = surface_desc.get('sakura.name', desc.get('sakura.name'))
sakura.enqueue_event('OnGhostChanging', name, method, proc=proc)
name = self.ghost_list[prev[1]]['instance'].get_selfname()
else:
name = None
- sakura.set_use_pna(self.prefs.get('use_pna')) ## FIXME
- sakura.set_surface_scale(self.prefs.get('surface_scale')) ## FIXME
- sakura.set_balloon_scalling(self.prefs.get('balloon_scalling')) ## FIXME
- sakura.set_surface_alpha(self.prefs.get('surface_alpha')) ## FIXME
- sakura.set_balloon_alpha(self.prefs.get('balloon_alpha')) ## FIXME
- sakura.set_animation_quality(self.prefs.get('animation_quality')) ## FIXME
- sakura.set_seriko_inactive(self.prefs.get('seriko_inactive')) ## FIXME
+ sakura.notify_preference_changed()
sakura.start(item, init, temp, vanished, ghost_changed, name)
+ def notify_preference_changed(self):
+ for sakura in self.get_working_ghost():
+ sakura.notify_preference_changed()
+
def start_sakura_cb(self, event, item):
self.start_sakura(item, init=1)
shutil.rmtree(os.path.join(prefix, filename))
except:
print '*** REMOVE FAILED *** :', filename
- # select another ghost
set_type, i, j = sakura.current
- if set_type == 's':
- i = 0
- index_list = self.range_ghosts()
- index_list.remove(i)
- next_i = random.choice(index_list)
- assert i != next_i
- if self.current_sakura == sakura.current:
- self.current_sakura = ('g', next_i, 0)
- # reload and start the new ghost
- self.change_sakura(sakura, ('g', next_i, 0), 'automatic', vanished=1)
+ self.select_ghost(sakura, 0, vanished=1)
self.ghosts[i] = None
self.update_ghost_list(i, sakura)
- def select_plugin(self, event, item):
- i, j = item
- plugin_name, plugin_dir, startup, menu_items = self.plugins[i]
- label, argv = menu_items[j]
- self.exec_plugin(plugin_dir, argv)
+ def select_plugin(self, event, item): ## FIXME
+ self.plugin_controler.select_plugin(event, item)
- def select_nekodorif(self, event, item): ## FIXME
- target, nekodorif_dir = item
+ def select_nekodorif(self, nekodorif_dir, target):
ninix.nekodorif.Nekoninni().load(nekodorif_dir, self.katochan, target)
- def select_kinoko(self, event, item): ## FIXME
- target, data = item
+ def select_kinoko(self, data, target):
ninix.kinoko.Kinoko(self.kinoko).load(data, target)
- def terminate_plugin(self, signum, frame):
- for pid in self.plugin_pids[:]:
- try:
- (pid, status) = os.waitpid(pid, os.WNOHANG)
- except OSError:
- ##print 'Process %d not found.' % pid
- self.plugin_pids.remove(pid)
- if pid > 0:
- ##print 'Process %d terminated.' % pid
- self.plugin_pids.remove(pid)
- ##print 'Running subprocesses:', self.plugin_pids
-
- def get_sstp_port(self):
- if not self.sstp_servers:
- return None
- return self.sstp_servers[0].server_address[1]
-
- def exec_plugin(self, plugin_dir, argv):
- ##print 'exec_plugin:', ' '.join(argv)
- if not os.path.exists(argv[0]):
- return
- port = self.get_sstp_port()
- if port is None:
- port = 'none'
- environ = os.environ.copy()
- environ['NINIX_PID'] = str(os.getpid())
- environ['NINIX_SSTP_PORT'] = str(port)
- environ['NINIX_PLUGIN_DIR'] = plugin_dir
- try:
- pid = os.fork()
- except OSError:
- sys.stderr.write('Error: %s failed (ignored)\n' % argv[0])
- return
- if pid == 0:
- os.chdir(plugin_dir)
- try:
- os.execve(argv[0], argv, environ)
- except OSError:
- raise SystemExit, 'Error: %s failed (abort)\n' % argv[0]
- self.plugin_pids.append(pid)
-
def open_ghost_manager(self):
self.__ngm.show_dialog()
self.timeout_id = gobject.timeout_add(100, self.do_idle_tasks) # 100ms
def do_idle_tasks(self):
- self.handle_sstp_queue()
- self.receive_sstp_request()
+ self.sstp_controler.handle_sstp_queue()
+ self.sstp_controler.receive_sstp_request()
self.set_timeout()
if ai_list:
path = random.choice(ai_list)
assert os.path.exists(path)
- self.pixbuf = ninix.pix.create_pixbuf_from_file(path, is_pnr=0)
+ self.pixbuf = ninix.pix.create_pixbuf_from_file(
+ path, is_pnr=False)
self.pixbuf.saturate_and_pixelate(self.pixbuf, 1.0, True)
else:
self.pixbuf = None
class Menu:
- def __init__(self, sakura, surface):
- self.__sakura = sakura
- self.__surface = surface
+ def __init__(self, callback):
+ self.callback = callback
ui_info = '''
<ui>
<popup name='popup'>
<menu action='Options'>
<menuitem action='Update'/>
<menuitem action='Vanish'/>
- <menuitem action='Reload'/>
<menuitem action='Preferences'/>
<menuitem action='Manager'/>
</menu>
</ui>
'''
self.__menu_list = { ## FIXME
- 'Portal': [('Portal', None, _('Portal sites(_P)'), None),
- None, 1, 1],
- 'Recommend': [('Recommend', None, _('Recommend sites(_R)'), None),
- None, 1, 1],
- 'Options': [('Options', None, _('Options(_F)'), None),
- None, 1, 1],
- 'Options/Update': [('Update', None, _('Network Update(_U)'), None,
- '', lambda *a: self.__sakura.network_update()),
- None, 1, 1],
- 'Options/Vanish': [('Vanish', None, _('Vanish(_F)'), None,
- '', lambda *a: self.__sakura.vanish()),
- None, 1, 1],
- 'Options/Reload': [('Reload', None, _('Reload(_L)'), None,
- '', lambda *a: self.__sakura.reload()),
- None, 1, 1],
- 'Options/Preferences': [('Preferences', None, _('Preferences...(_O)'), None,
- '', lambda *a: self.__sakura.prefs.edit_preferences()),
- None, 1, 1],
- 'Options/Manager': [('Manager', None, _('Ghost Manager(_M)'), None,
- '',
- lambda *a: self.__sakura.app.open_ghost_manager()),
- None, 1, 1],
- 'Information': [('Information', None, _('Information(_I)'), None),
- None, 1, 1],
- 'Information/Usage': [('Usage', None, _('Usage graph(_A)'), None,
- '', lambda *a: self.__sakura.app.show_usage()),
- None, 1, 1],
- 'Information/Version': [('Version', None, _('Version(_V)'), None,
- '', lambda *a: self.__sakura.about()),
- None, 1, 1],
- 'Close': [('Close', None, _('Close(_W)'), None,
- '', lambda *a: self.__sakura.close()),
- None, 1, 1],
+ 'Portal': [
+ ('Portal', None, _('Portal sites(_P)'), None),
+ None, 1, 1],
+ 'Recommend': [
+ ('Recommend', None, _('Recommend sites(_R)'), None),
+ None, 1, 1],
+ 'Options': [
+ ('Options', None, _('Options(_F)'), None),
+ None, 1, 1],
+ 'Options/Update': [
+ ('Update', None, _('Network Update(_U)'), None,
+ '', lambda *a: self.callback['network_update']()),
+ None, 1, 1],
+ 'Options/Vanish': [
+ ('Vanish', None, _('Vanish(_F)'), None,
+ '', lambda *a: self.callback['vanish_sakura']()),
+ None, 1, 1],
+ 'Options/Preferences': [
+ ('Preferences', None, _('Preferences...(_O)'), None,
+ '', lambda *a: self.callback['edit_preferences']()),
+ None, 1, 1],
+ 'Options/Manager': [
+ ('Manager', None, _('Ghost Manager(_M)'), None,
+ '', lambda *a: self.callback['open_ghost_manager']()),
+ None, 1, 1],
+ 'Information': [
+ ('Information', None, _('Information(_I)'), None),
+ None, 1, 1],
+ 'Information/Usage': [
+ ('Usage', None, _('Usage graph(_A)'), None,
+ '', lambda *a: self.callback['show_usage']()),
+ None, 1, 1],
+ 'Information/Version': [
+ ('Version', None, _('Version(_V)'), None,
+ '', lambda *a: self.callback['about']()),
+ None, 1, 1],
+ 'Close': [
+ ('Close', None, _('Close(_W)'), None,
+ '', lambda *a: self.callback['close_sakura']()),
+ None, 1, 1],
'Quit': [('Quit', None, _('Quit(_Q)'), None,
- '', lambda *a: self.__sakura.get_callback('close all')()),
+ '', lambda *a: self.callback['close_all']()),
None, 1, 1],
- 'Change': [('Change', None, _('Change(_G)'), None),
- None, 1, 1],
- 'Summon': [('Summon', None, _('Summon(_X)'), None),
- None, 1, 1],
- 'Shell': [('Shell', None, _('Shell(_S)'), None),
- None, 1, 1],
- 'Balloon': [('Balloon', None, _('Balloon(_B)'), None),
- None, 1, 1],
- 'Costume': [('Costume', None, _('Costume(_C)'), None),
- None, 1, 1],
- 'Stick': [('Stick', None, _('Stick(_Y)'), None,
- '', self.__surface.window_stick, False),
- None, 1, 1],
- 'Nekodorif': [('Nekodorif', None, _('Nekodorif(_N)'), None),
- None, 1, 1],
- 'Kinoko': [('Kinoko', None, _('Kinoko(_K)'), None),
- None, 1, 1],
- 'Plugin': [('Plugin', None, _('Plugin(_P)'), None),
- None, 1, 1],
+ 'Change': [
+ ('Change', None, _('Change(_G)'), None),
+ None, 1, 1],
+ 'Summon': [
+ ('Summon', None, _('Summon(_X)'), None),
+ None, 1, 1],
+ 'Shell': [
+ ('Shell', None, _('Shell(_S)'), None),
+ None, 1, 1],
+ 'Balloon': [
+ ('Balloon', None, _('Balloon(_B)'), None),
+ None, 1, 1],
+ 'Costume': [
+ ('Costume', None, _('Costume(_C)'), None),
+ None, 1, 1],
+ 'Stick': [
+ ('Stick', None, _('Stick(_Y)'), None,
+ '', self.callback['stick_window'], False),
+ None, 1, 1],
+ 'Nekodorif': [
+ ('Nekodorif', None, _('Nekodorif(_N)'), None),
+ None, 1, 1],
+ 'Kinoko': [
+ ('Kinoko', None, _('Kinoko(_K)'), None),
+ None, 1, 1],
+ 'Plugin': [
+ ('Plugin', None, _('Plugin(_P)'), None),
+ None, 1, 1],
}
self.__pixmap = None
self.__pixmap_with_sidebar = None
pixbuf = None
if path_background and os.path.exists(path_background):
try:
- pixbuf = ninix.pix.create_pixbuf_from_file(path_background,
- is_pnr=0)
+ pixbuf = ninix.pix.create_pixbuf_from_file(
+ path_background, is_pnr=False)
except:
pixbuf = None
if pixbuf is None:
if path_sidebar and os.path.exists(path_sidebar):
try:
pixbuf_sidebar = ninix.pix.create_pixbuf_from_file(
- path_sidebar, is_pnr=0)
+ path_sidebar, is_pnr=False)
except:
pixbuf_sidebar = None
if pixbuf_sidebar:
pixbuf = None
if path_foreground and os.path.exists(path_foreground):
try:
- pixbuf = ninix.pix.create_pixbuf_from_file(path_foreground,
- is_pnr=0)
+ pixbuf = ninix.pix.create_pixbuf_from_file(
+ path_foreground, is_pnr=False)
except:
pixbuf = None
if pixbuf is None:
item = gtk.CheckMenuItem(name)
item.set_name('popup menu item')
item.set_active(bool(state))
- item.connect('activate', self.__surface.toggle_bind,
+ item.connect('activate', self.callback['toggle_bind'],
(index, key))
else:
item = gtk.SeparatorMenuItem()
name_list = self.__ui[key][0][side]
if name_list: # caption
for name in name_list:
- caption = self.__sakura.getstring(name)
+ caption = self.callback['getstring'](name)
if caption:
break
if caption:
name_list = self.__ui[key][2][side]
if name_list: # visible
for name in name_list:
- visible = self.__sakura.getstring(name)
+ visible = self.callback['getstring'](name)
if visible is not None:
break
if visible == '0':
assert side in [0, 1] ## FIXME
string = ['sakura', 'kero'][side]
string = ''.join((string, '.popupmenu.visible'))
- if self.__sakura.getstring(string) == '0':
+ if self.callback['getstring'](string) == '0':
return
self.__update_ui(side)
if side == 0:
- portal = self.__sakura.getstring('sakura.portalsites')
+ portal = self.callback['getstring']('sakura.portalsites')
else:
portal = None
self.__set_portal_menu(side, portal)
assert side in [0, 1] ## FIXME
string = ['sakura', 'kero'][side]
string = ''.join((string, '.recommendsites'))
- recommend = self.__sakura.getstring(string)
+ recommend = self.callback['getstring'](string)
self.__set_recommend_menu(recommend)
self.__set_ghost_menu()
self.__set_shell_menu()
#else:
# bannar = None
item = gtk.MenuItem(title)
- item.connect('activate', self.__sakura.notify_site_selection,
+ item.connect('activate',
+ self.callback['notify_site_selection'],
(title, url))
menu.add(item)
item.show()
#else:
# bannar = None
item = gtk.MenuItem(title)
- item.connect('activate', self.__sakura.notify_site_selection,
+ item.connect('activate',
+ self.callback['notify_site_selection'],
(title, url))
menu.add(item)
item.show()
ghost_menu.append(item)
if len(shell_list) <= 1:
shell_name, value = shell_list[0]
- if summon:
- item.connect('activate', callback, value)
- else:
- item.connect('activate', callback, (self.__sakura, value))
+ item.connect('activate', callback, value)
if set_list[i]['instance'].is_running():
item.set_sensitive(False)
else:
for shell_name, value in shell_list:
item = gtk.MenuItem(shell_name)
item.set_name('popup menu item')
- if summon:
- item.connect('activate', callback, value)
- else:
- item.connect('activate', callback, (self.__sakura, value))
+ item.connect('activate', callback, value)
item.show()
if set_list[i]['instance'].is_running():
if summon:
item.set_sensitive(False)
else:
- if self.__sakura.current[1] != value[1]:
+ set_type, i, j = self.callback['get_current_item']()
+ if i != value[1]:
item.set_sensitive(False)
- elif self.__sakura.current[2] == value[2]:
+ elif j == value[2]:
item.set_sensitive(False)
submenu.append(item)
path = 'Summon' if summon else 'Change'
self.__menu_list[path][3] = 1
def __set_ghost_menu(self):
- ghosts = self.__sakura.app.get_ghost_list()
- self.__update_ghost_menu(ghosts, self.__sakura.app.select_sakura, False)
- self.__update_ghost_menu(ghosts, self.__sakura.app.start_sakura_cb, True)
+ ghosts = self.callback['get_ghost_list']()
+ self.__update_ghost_menu(ghosts, self.callback['select_sakura'], False)
+ self.__update_ghost_menu(ghosts, self.callback['start_sakura'], True)
def __set_shell_menu(self):
- set_list = self.__sakura.app.get_shell_list() ## FIXME
+ set_list = self.callback['get_shell_list']()
shell_menu = gtk.Menu()
for i in range(len(set_list)):
name = set_list[i]['name']
shell_list = set_list[i]['shell']
if len(shell_list) <= 1:
shell_name, value = shell_list[0]
- item.connect('activate', self.__sakura.app.select_sakura,
- (self.__sakura, value))
+ item.connect('activate', self.callback['select_sakura'], value)
##if working:
## item.set_sensitive(False)
else:
for shell_name, value in shell_list:
item = gtk.MenuItem(shell_name)
item.set_name('popup menu item')
- item.connect('activate', self.__sakura.app.select_sakura,
- (self.__sakura, value))
+ item.connect('activate', self.callback['select_sakura'],
+ value)
item.show()
##if working: ## FIXME
## item.set_sensitive(False)
self.__menu_list['Shell'][3] = 1
def __set_balloon_menu(self):
- balloon_list = self.__sakura.app.get_balloon_list()
+ balloon_list = self.callback['get_balloon_list']()
balloon_menu = gtk.Menu()
group = None
- name_own = self.__sakura.get_own_balloon_name()
+ name_own = self.callback['get_own_balloon_name']()
if name_own is not None:
item = group = gtk.RadioMenuItem(group, name_own)
item.set_name('popup menu item')
- hid = item.connect('activate', self.__sakura.select_balloon,
+ hid = item.connect('activate', self.callback['select_balloon'],
name_own)
item.show()
balloon_menu.append(item)
name = balloon_list[i]['name']
item = group = gtk.RadioMenuItem(group, name)
item.set_name('popup menu item')
- hid = item.connect('activate', self.__sakura.select_balloon, name)
+ hid = item.connect('activate',
+ self.callback['select_balloon'], name)
item.show()
balloon_menu.append(item)
- if name == self.__sakura.get_current_balloon_name():
+ if name == self.callback['get_current_balloon_name']():
item.handler_block(hid)
item.activate()
item.handler_unblock(hid)
self.__menu_list['Balloon'][3] = 1
def __set_plugin_menu(self):
- plugin_list = self.__sakura.app.get_plugin_list()
+ plugin_list = self.callback['get_plugin_list']()
plugin_menu = gtk.Menu()
for i in range(len(plugin_list)):
name = plugin_list[i]['name']
item_list = plugin_list[i]['items']
if len(item_list) <= 1:
label, value = item_list[0]
- item.connect('activate', self.__sakura.app.select_plugin, value)
+ item.connect('activate', self.callback['select_plugin'], value)
##if working:
## item.set_sensitive(False)
else:
for label, value in item_list:
item = gtk.MenuItem(label)
item.set_name('popup menu item')
- item.connect('activate', self.__sakura.app.select_plugin,
+ item.connect('activate', self.callback['select_plugin'],
value)
item.show()
##if working:
self.__menu_list['Plugin'][3] = 1
def __set_nekodorif_menu(self):
- nekodorif_list = self.__sakura.app.get_nekodorif_list()
+ nekodorif_list = self.callback['get_nekodorif_list']()
nekodorif_menu = gtk.Menu()
for i in range(len(nekodorif_list)):
name = nekodorif_list[i]['name']
item.set_name('popup menu item')
item.show()
nekodorif_menu.append(item)
- item.connect('activate', self.__sakura.app.select_nekodorif,
- (self.__sakura, nekodorif_list[i]['dir']))
+ item.connect('activate', self.callback['select_nekodorif'],
+ nekodorif_list[i]['dir'])
##if working:
## item.set_sensitive(False)
menuitem = self.ui_manager.get_widget(
self.__menu_list['Nekodorif'][3] = 1
def __set_kinoko_menu(self):
- kinoko_list = self.__sakura.app.get_kinoko_list()
+ kinoko_list = self.callback['get_kinoko_list']()
kinoko_menu = gtk.Menu()
for i in range(len(kinoko_list)):
name = kinoko_list[i]['title']
item.set_name('popup menu item')
item.show()
kinoko_menu.append(item)
- item.connect('activate', self.__sakura.app.select_kinoko,
- (self.__sakura, kinoko_list[i]))
+ item.connect('activate', self.callback['select_kinoko'],
+ kinoko_list[i])
##if working:
## item.set_sensitive(False)
menuitem = self.ui_manager.get_widget(''.join(('/popup/', 'Kinoko')))
class Menu:
- def __init__(self, nekoninni, accelgroup):
- self.__nekoninni = nekoninni
+ def __init__(self, callback, accelgroup):
+ self.callback = callback
ui_info = '''
<ui>
<popup name='popup'>
'''
self.__menu_list = {
'settings': [('Settings', None, _('Settings...(_O)'), None,
- '', self.__nekoninni.edit_preferences),
+ '', self.callback['edit_preferences']),
'/ui/popup/Settings'],
'katochan': [('Katochan', None,_('Katochan(_K)'), None),
'/ui/popup/Katochan'],
'exit': [('Exit', None,_('Exit(_Q)'), None,
- '', self.__nekoninni.close),
+ '', self.callback['close']),
'/ui/popup/Exit'],
}
self.__katochan_list = None
self.__menu_list[key][1] = ui_manager.get_widget(path)
def popup(self, button):
- katochan_list = self.__nekoninni.get_katochan_list()
+ katochan_list = self.callback['get_katochan_list']()
self.__set_katochan_menu(katochan_list)
self.__popup_menu.popup(
None, None, None, button, gtk.get_current_event_time())
for katochan in list:
item = gtk.MenuItem(katochan['name'])
item.connect(
- 'activate', self.__nekoninni.select_katochan, (katochan))
+ 'activate', self.callback['select_katochan'], (katochan))
menu.add(item)
item.show()
self.__menu_list[key][1].set_submenu(menu)
self.skin.set_position()
if self.katochan is not None and self.katochan.loaded:
self.katochan.set_position()
- elif event == 'set scale': ## FIXME
- scale = self.target.prefs.get('surface_scale')
+ elif event == 'set scale':
+ scale = self.target.get_surface_scale()
if self.skin is not None:
self.skin.set_scale(scale)
if self.katochan is not None:
self.target = target
self.target.set_observer(self)
self.accelgroup = gtk.AccelGroup()
- scale = self.target.prefs.get('surface_scale')
- self.skin = Skin(self.dir, self.accelgroup, self, scale)
+ scale = self.target.get_surface_scale()
+ skin_callback ={
+ 'finalize': self.finalize,
+ 'has_katochan': self.has_katochan,
+ 'drop_katochan': self.drop_katochan,
+ 'edit_preferences': self.edit_preferences,
+ 'close': self.close,
+ 'get_katochan_list': lambda *a: self.katochan_list,
+ 'select_katochan': self.select_katochan,
+ }
+ self.skin = Skin(self.dir, self.accelgroup, skin_callback, scale)
if self.skin is None:
return 0
self.katochan_list = katochan
def launch_katochan(self, katochan):
if self.katochan:
self.katochan.destroy()
- self.katochan = Katochan(self, self.target)
+ katochan_callback = {
+ 'finalize': self.finalize,
+ 'send_event': self.send_event,
+ 'get_mode': lambda *a: self.mode,
+ 'delete_katochan': self.delete_katochan,
+ }
+ self.katochan = Katochan(katochan_callback, self.target)
self.katochan.load(katochan)
def edit_preferences(self, action):
def close(self, action):
self.finalize()
- def get_katochan_list(self): ## FIXME
- return self.katochan_list
class Skin:
- def __init__(self, dir, accelgroup, nekoninni, scale):
+ def __init__(self, dir, accelgroup, callback, scale):
self.dir = dir
self.accelgroup = accelgroup
- self.nekoninni = nekoninni
+ self.callback = callback
self.x_root = None
self.y_root = None
self.__scale = scale
- self.__menu = Menu(self.nekoninni, self.accelgroup)
+ menu_callback = {}
+ for key in ['edit_preferences', 'close',
+ 'get_katochan_list', 'select_katochan']:
+ menu_callback[key] = self.callback[key]
+ self.__menu = Menu(menu_callback, self.accelgroup)
path = os.path.join(self.dir, 'omni.txt')
self.omni = int(os.path.isfile(path) and os.path.getsize(path) == 0)
self.window = gtk.Window()
pass
def delete(self, widget, event):
- self.nekoninni.finalize()
+ self.callback['finalize']()
def destroy(self): ## FIXME
self.window.destroy()
## gtk.get_current_event_time())
pass
elif event.type == gtk.gdk._2BUTTON_PRESS: # double click
- if self.nekoninni.has_katochan():
+ if self.callback['has_katochan']():
self.start() ## FIXME
- self.nekoninni.drop_katochan()
+ self.callback['drop_katochan']()
elif event.button == 3:
if event.type == gtk.gdk.BUTTON_PRESS:
self.__menu.popup(event.button)
pixbuf = pixbuf.scale_simple(w, h, gtk.gdk.INTERP_BILINEAR)
image, mask = pixbuf.render_pixmap_and_mask(255)
except:
- self.nekoninni.finalize()
+ self.callback['finalize']()
return
self.w, self.h = image.get_size()
self.darea.set_size_request(self.w, self.h)
'other' # 上記カテゴリに当てはまらないもの
]
- def __init__(self, nekoninni, target):
+ def __init__(self, callback, target):
self.side = 0
self.target = target
- self.nekoninni = nekoninni
+ self.callback = callback
self.settings = {}
self.settings['state'] = 'before'
self.settings['fall.type'] = 'gravity'
pixbuf = pixbuf.scale_simple(w, h, gtk.gdk.INTERP_BILINEAR)
image, mask = pixbuf.render_pixmap_and_mask(255)
except:
- self.nekoninni.finalize()
+ self.callback['finalize']()
return
self.w, self.h = image.get_size()
self.darea.set_size_request(self.w, self.h)
def load(self, data):
self.data = data
- self.__scale = self.target.prefs.get('surface_scale')
+ self.__scale = self.target.get_surface_scale()
self.set_state('before')
##print 'DATA:', self.data
if 'category' in self.data:
self.side = 0 # XXX
else:
self.side = 0 # XXX
- if self.nekoninni.mode == 1:
- self.nekoninni.send_event('Emerge')
+ if self.callback['get_mode']() == 1:
+ self.callback['send_event']('Emerge')
else:
if 'before.script' in self.data:
pass ## FIXME
if self.check_collision():
self.set_state('hit')
self.hit = 1
- if self.nekoninni.mode == 1:
+ if self.callback['get_mode']() == 1:
self.id = 1
self.set_surface()
- self.nekoninni.send_event('Hit')
+ self.callback['send_event']('Hit')
else:
pass ## FIXME
if self.check_mikire():
if self.hit_stop >= self.data.get('hit.waittime', 0):
self.set_state('after')
self.set_movement('after')
- if self.nekoninni.mode == 1:
+ if self.callback['get_mode'] == 1:
self.id = 2
self.set_surface()
- self.nekoninni.send_event('Drop')
+ self.callback['send_event']('Drop')
else:
pass ## FIXME
else:
if self.check_mikire():
self.set_state('end')
elif self.settings['state'] == 'end':
- if self.nekoninni.mode == 1:
- self.nekoninni.send_event('Vanish')
+ if self.callback['get_mode']() == 1:
+ self.callback['send_event']('Vanish')
else:
pass ## FIXME
- self.nekoninni.delete_katochan()
+ self.callback['delete_katochan']()
return False
elif self.settings['state'] == 'dodge':
- if self.nekoninni.mode == 1:
- self.nekoninni.send_event('Dodge')
+ if self.callback['get_mode'] == 1:
+ self.callback['send_event']('Dodge')
else:
pass ## FIXME
- self.nekoninni.delete_katochan()
+ self.callback['delete_katochan']()
return False
else:
pass ## check collision and mikire
except:
return ## FIXME
-class InstallationManager(list):
-
- def __init__(self, ngm):
- self.master = ngm
-
- def set_current_ghost(self, set_id):
- self.current_ghost = set_id
-
- def install_ghost(self, dialog):
- a = self.master.ui.catalog.get(self.current_ghost, 'ArchiveUrl')
- os.system("%s '%s'" % (self.master.ninix_install_cmd, a))
+#class InstallationManager(list):
+#
+# def __init__(self, ngm):
+# self.master = ngm
+#
+# def set_current_ghost(self, set_id):
+# self.current_ghost = set_id
+#
+# def install_ghost(self, dialog):
+# a = self.master.ui.catalog.get(self.current_ghost, 'ArchiveUrl')
+# os.system("%s '%s'" % (self.master.ninix_install_cmd, a))
class SearchDialog:
- def __init__(self, ui):
- self.ui = ui
+ def __init__(self, callback):
+ self.callback = callback
self.dialog = gtk.Dialog()
self.dialog.connect('delete_event', self.cancel)
self.dialog.set_modal(True)
def ok(self, widget, event=None):
word = unicode(self.get_pattern(), 'utf-8')
- self.ui.search(word)
+ self.callback['search'](word)
self.hide()
return True
return True
class UI:
- def __init__(self, ngm):
- self.ngm = ngm
+ def __init__(self, callback):
+ self.callback = callback
self.ui_info = '''
<ui>
<menubar name='MenuBar'>
( 'Settings', None,
_('Settings(_O)'), None,
None,
- lambda *a: self.ngm.open_preference_dialog() ),
+ lambda *a: self.callback['open_preference_dialog']() ),
( 'DB Network Update', None,
_('DB Network Update(_N)'), None,
None,
( 'Mask', None,
_('Mask(_M)'), None,
None,
- lambda *a: self.ngm.open_mask_dialog() ),
+ lambda *a: self.callback['open_mask_dialog']() ),
( 'Reset to Default', None,
_('Reset to Default(_Y)'), None,
None,
- lambda *a: self.ngm.reset_to_default() ),
+ lambda *a: self.callback['reset_to_default']() ),
( 'Show All', None,
_('Show All(_Z)'), None,
None,
- lambda *a: self.ngm.show_all() ),
+ lambda *a: self.callback['show_all']() ),
)
self.opened = 0
self.textview = [None, None]
self.button = {}
self.url = {}
self.search_word = ''
- self.search_dialog = SearchDialog(self)
+ search_dialog_callback = {
+ 'search': self.search,
+ }
+ self.search_dialog = SearchDialog(search_dialog_callback)
self.create_dialog()
def create_dialog(self):
self.statusbar.show()
def network_update(self):
- self.ngm.network_update()
+ self.callback['network_update']()
self.update()
def open_search_dialog(self):
def search(self, word):
if word:
self.search_word = word
- if self.ngm.search(word):
+ if self.callback['search'](word):
self.update()
else:
pass ## FIXME
def search_forward(self):
if self.search_word:
- if self.ngm.search_forward(self.search_word):
+ if self.callback['search_forward'](self.search_word):
self.update()
else:
pass ## FIXME
def show_next(self):
- self.ngm.next()
+ self.callback['next']()
self.update()
def show_previous(self):
- self.ngm.previous()
+ self.callback['previous']()
self.update()
def create_surface_area(self, side):
def update_surface_area(self):
for side in [0, 1]:
- name = self.ngm.get('SakuraName') if side == 0 else \
- self.ngm.get('KeroName')
+ name = self.callback['get']('SakuraName') if side == 0 else \
+ self.callback['get']('KeroName')
textbuffer = self.textview[side].get_buffer()
textbuffer.set_text(name)
- filename = self.ngm.get_image_filename(side)
+ filename = self.callback['get_image_filename'](side)
darea = self.darea[side]
darea.realize()
if filename is not None:
box.set_layout(gtk.BUTTONBOX_SPREAD)
box.show()
button = gtk.Button(_('Install'))
- button.connect('clicked', lambda b, w=self: w.ngm.install_current())
+ button.connect('clicked', lambda b, w=self: w.callback['install_current']())
box.add(button)
button.show()
self.button['install'] = button
button = gtk.Button(_('Update'))
- button.connect('clicked', lambda b, w=self: w.ngm.update_current())
+ button.connect('clicked', lambda b, w=self: w.callback['update_current']())
box.add(button)
button.show()
self.button['update'] = button
(_('Version:'), 'Version'),
(_('AIName:'), 'AIName')]
text = ''
- text = ''.join((text, self.ngm.get('Name'), '\n'))
+ text = ''.join((text, self.callback['get']('Name'), '\n'))
for item in info_list:
- text = ''.join((text, item[0], self.ngm.get(item[1]), '\n'))
+ text = ''.join((text, item[0], self.callback['get'](item[1]), '\n'))
text = ''.join((text,
- self.ngm.get('SakuraName'),
- _('SurfaceList:'), self.ngm.get('SakuraSurfaceList'),
+ self.callback['get']('SakuraName'),
+ _('SurfaceList:'), self.callback['get']('SakuraSurfaceList'),
'\n'))
text = ''.join((text,
- self.ngm.get('KeroName'),
- _('SurfaceList:'), self.ngm.get('KeroSurfaceList'),
+ self.callback['get']('KeroName'),
+ _('SurfaceList:'), self.callback['get']('KeroSurfaceList'),
'\n'))
textbuffer = self.info.get_buffer()
textbuffer.set_text(text)
- url = self.ngm.get('HPUrl')
- text = self.ngm.get('HPTitle')
+ url = self.callback['get']('HPUrl')
+ text = self.callback['get']('HPTitle')
self.url['HP'][0] = url
label = self.url['HP'][1]
label.set_markup('<span foreground="blue">%s</span>' % text)
- url = self.ngm.get('PublicUrl')
- text = ''.join((self.ngm.get('Name'), _(' Web Page')))
+ url = self.callback['get']('PublicUrl')
+ text = ''.join((self.callback['get']('Name'), _(' Web Page')))
self.url['Public'][0] = url
label = self.url['Public'][1]
label.set_markup('<span foreground="blue">%s</span>' % text)
- target_dir = os.path.join(self.ngm.home_dir, 'ghost',
- self.ngm.get('InstallDir'))
+ target_dir = os.path.join(self.callback['get_home_dir'](), 'ghost',
+ self.callback['get']('InstallDir'))
self.button['install'].set_sensitive(
bool(not os.path.isdir(target_dir) and
- self.ngm.get('ArchiveUrl') != 'No data'))
+ self.callback['get']('ArchiveUrl') != 'No data'))
self.button['update'].set_sensitive(
bool(os.path.isdir(target_dir) and
- self.ngm.get('GhostType') == 'ゴースト' and
- self.ngm.get('UpdateUrl') != 'No data'))
+ self.callback['get']('GhostType') == 'ゴースト' and
+ self.callback['get']('UpdateUrl') != 'No data'))
def update(self):
self.update_surface_area()
self.update_info_area()
- self.button['next'].set_sensitive(bool(self.ngm.exist_next()))
- self.button['previous'].set_sensitive(bool(self.ngm.exist_previous()))
+ self.button['next'].set_sensitive(bool(self.callback['exist_next']()))
+ self.button['previous'].set_sensitive(bool(self.callback['exist_previous']()))
def show(self):
if self.opened:
class NGM:
- def __init__(self, app):
+ def __init__(self, callback):
+ self.callback = callback
self.current = 0
- self.app = app
self.opened = 0
self.home_dir = ninix.home.get_ninix_home()
self.catalog = Catalog(os.path.join(self.home_dir, 'ngm/data'))
- self.ui = UI(self)
+ ui_callback = {
+ 'open_preference_dialog': self.open_preference_dialog,
+ 'open_mask_dialog': self.open_mask_dialog,
+ 'reset_to_default': self.reset_to_default,
+ 'show_all': self.show_all,
+ 'network_update': self.network_update,
+ 'search': self.search,
+ 'search_forward': self.search_forward,
+ 'next': self.next,
+ 'previous': self.previous,
+ 'get': self.get,
+ 'get_image_filename': self.get_image_filename,
+ 'get_home_dir': lambda *a: self.home_dir,
+ 'exist_next': self.exist_next,
+ 'exist_previous': self.exist_previous,
+ 'install_current': self.install_current,
+ 'update_current': self.update_current,
+ }
+ self.ui = UI(ui_callback)
def get(self, element):
if self.current in self.catalog.data:
pass
def update_current(self): ## FIXME
- item = self.app.find_ghost_by_name(self.get('Name'), 0)
- sakura = self.app.select_ghost_from_list(item)
- if not sakura.is_running():
- self.app.start_sakura(item, init=1)
- sakura.enqueue_script('\![updatebymyself]\e', 'NGM',
- None, None, 0, 0, None)
+ self.callback['update_sakura'](self.get('Name'), 'NGM')
if __name__ == '__main__':
loader.close()
return pixbuf
-def create_pixbuf_from_file(path, is_pnr=1, use_pna=0):
+def create_pixbuf_from_file(path, is_pnr=True, use_pna=False):
head, tail = os.path.split(path)
basename, suffix = os.path.splitext(tail)
if suffix == '.dgp':
--- /dev/null
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2001, 2002 by Tamito KAJIYAMA
+# Copyright (C) 2002, 2003 by MATSUMURA Namihiko <nie@counterghost.net>
+# Copyright (C) 2002-2010 by Shyouzou Sugitani <shy@users.sourceforge.jp>
+# Copyright (C) 2003-2005 by Shun-ichi TAHARA <jado@flowernet.gr.jp>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License (version 2) as
+# published by the Free Software Foundation. It is distributed in the
+# hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+# PURPOSE. See the GNU General Public License for more details.
+#
+
+import os
+import signal
+import sys
+
+
+class PluginControler:
+
+ def __init__(self, plugins, callback):
+ self.plugins = plugins
+ self.plugin_pids = []
+ self.get_sstp_port = callback['get_sstp_port']
+
+ def get_plugin_list(self):
+ plugin_list = []
+ for i, plugin in enumerate(self.plugins):
+ plugin_name = plugin[0]
+ menu_items = plugin[3]
+ if not menu_items:
+ continue
+ item = {}
+ item['name'] = plugin_name
+ item['icon'] = None
+ item_list = []
+ for j, menu_item in enumerate(menu_items):
+ label = menu_item[0]
+ value = (i, j)
+ item_list.append((label, value))
+ item['items'] = item_list
+ plugin_list.append(item)
+ return plugin_list
+
+ def select_plugin(self, event, item):
+ i, j = item
+ plugin_name, plugin_dir, startup, menu_items = self.plugins[i]
+ label, argv = menu_items[j]
+ self.exec_plugin(plugin_dir, argv)
+
+ def terminate_plugin(self, signum, frame):
+ for pid in self.plugin_pids[:]:
+ try:
+ (pid, status) = os.waitpid(pid, os.WNOHANG)
+ except OSError:
+ ##print 'Process %d not found.' % pid
+ self.plugin_pids.remove(pid)
+ if pid > 0:
+ ##print 'Process %d terminated.' % pid
+ self.plugin_pids.remove(pid)
+ ##print 'Running subprocesses:', self.plugin_pids
+
+ def exec_plugin(self, plugin_dir, argv):
+ ##print 'exec_plugin:', ' '.join(argv)
+ if not os.path.exists(argv[0]):
+ return
+ port = self.get_sstp_port()
+ if port is None:
+ port = 'none'
+ environ = os.environ.copy()
+ environ['NINIX_PID'] = str(os.getpid())
+ environ['NINIX_SSTP_PORT'] = str(port)
+ environ['NINIX_PLUGIN_DIR'] = plugin_dir
+ try:
+ pid = os.fork()
+ except OSError:
+ sys.stderr.write('Error: %s failed (ignored)\n' % argv[0])
+ return
+ if pid == 0:
+ os.chdir(plugin_dir)
+ try:
+ os.execve(argv[0], argv, environ)
+ except OSError:
+ raise SystemExit, 'Error: %s failed (abort)\n' % argv[0]
+ self.plugin_pids.append(pid)
+
+ def start_plugins(self):
+ try:
+ os.setpgid(0, 0)
+ except OSError:
+ pass
+ for plugin_name, plugin_dir, startup, menu_items in self.plugins:
+ if startup is not None:
+ self.exec_plugin(plugin_dir, startup)
f.write('%s: %s\n' % (key, self[key]))
f.close()
- def get_with_type(self, name, default, conv=None):
+ def get_with_type(self, name, conv, default):
value = self.get(name)
if value:
if conv is None:
'seriko_inactive': int,
}
- def __init__(self, app):
- self.app = app
+ def __init__(self, callback):
+ self.callback = callback
self.window = gtk.Dialog()
self.window.set_title('Preferences')
self.window.connect('delete_event', self.cancel)
def load(self):
filename = ninix.home.get_preferences()
self.__prefs = Preferences(filename)
+ self.save = self.__prefs.save
self.__prefs.load()
self.reset()
self.__saved_prefs = self.__prefs.copy()
- self.notify() ## FIXME
+ self.callback['notify_preference_changed']()
def reset(self): ### FIXME ###
self.fontsel.set_font_name(
self.get('balloon_fonts', DEFAULT_BALLOON_FONTS))
- name = self.get('default_balloon')
- if self.app.find_balloon_by_name(name) is not None:
- self.set_default_balloon(name)
+ self.set_default_balloon(self.get('default_balloon'))
self.ignore_button.set_active(
bool(self.get('ignore_default', 0)))
scale = self.get('surface_scale', get_default_surface_scale())
def get(self, name, default=None):
assert name in self.PREFS_TYPE
- return self.__prefs.get_with_type(name, default, self.PREFS_TYPE[name])
+ return self.__prefs.get_with_type(name, self.PREFS_TYPE[name], default)
- def save(self): ## FIXME: check key is valid
- name, surface = self.app.get_current_sakura_name() ## FIXME
- self.__prefs['sakura_name'] = self.__saved_prefs['sakura_name'] = name
- self.__prefs['sakura_surface'] = self.__saved_prefs['sakura_surface'] = surface
- self.__prefs.save()
+ def set_current_sakura(self, name, surface):
+ key = 'sakura_name'
+ self.__prefs[key] = self.__saved_prefs[key] = name
+ key = 'sakura_surface'
+ self.__prefs[key] = self.__saved_prefs[key] = surface
def edit_preferences(self):
self.show()
def update(self): ## FIXME
self.__prefs['allowembryo'] = str(int(self.allowembryo_button.get_active()))
self.__prefs['balloon_fonts'] = self.fontsel.get_font_name()
- name = None
selected = self.balloon_treeview.get_selection().get_selected()
if selected:
model, listiter = selected
name = model.get_value(listiter, 0)
- if self.app.find_balloon_by_name(name) is not None:
self.__prefs['default_balloon'] = name
self.__prefs['ignore_default'] = str(int(self.ignore_button.get_active()))
self.__prefs['surface_scale'] = str(int(range_scale[self.surface_scale_combo.get_active()]))
self.hide()
self.update()
self.__saved_prefs.update(self.__prefs)
- self.notify() ## FIXME
+ self.callback['notify_preference_changed']()
def apply(self, widget):
self.update()
- self.notify() ## FIXME
+ self.callback['notify_preference_changed']()
def cancel(self, widget, event=None):
self.hide()
self.__prefs.update(self.__saved_prefs)
self.reset()
- self.notify() ## FIXME
+ self.callback['notify_preference_changed']()
return True
def show(self):
box.pack_start(scrolled, True)
scrolled.show()
model = gtk.ListStore(gobject.TYPE_STRING)
- for desc, balloon in self.app.balloons:
+ for desc, balloon in self.callback['get_balloons']():
name = desc.get('name', '')
listiter = model.append()
model.set_value(listiter, 0, name)
button.show()
return page
- def notify(self): ## FIXME
- for sakura in self.app.get_working_ghost():
- sakura.reset_balloon_fonts() ## FIXME
- flag = self.get('balloon_scalling')
- sakura.set_balloon_scalling(flag) ## FIXME
- scale = self.get('surface_scale')
- sakura.set_surface_scale(scale) ## FIXME
- flag = self.get('use_pna')
- sakura.set_use_pna(flag) ## FIXME
- alpha = self.get('surface_alpha')
- sakura.set_surface_alpha(alpha) ## FIXME
- alpha = self.get('balloon_alpha')
- sakura.set_balloon_alpha(alpha) ## FIXME
- quality = self.get('animation_quality')
- sakura.set_animation_quality(quality) ## FIXME
- flag = self.get('seriko_inactive')
- sakura.set_seriko_inactive(flag) ## FIXME
-
def set_default_balloon(self, name):
model = self.balloon_treeview.get_model()
listiter = model.get_iter_first()
import gtk ## FIXME
import gobject
+# For some reasons gst parses sys.argv on import. This is a workaround.
+# (See https://bugzilla.gnome.org/show_bug.cgi?id=549879 .)
+argv = sys.argv
+sys.argv = []
import pygst
pygst.require("0.10")
import gst
+sys.argv = argv
import ninix.surface
import ninix.balloon
except:
name2codepoint = None
- def __init__(self, app, data, default_path, communicate, debug=0):
- self.app = app
- self.prefs = app.prefs
+ def __init__(self, data, default_path, callback, debug=0):
+ self.callback = callback
self.debug = debug
- self.communicate = communicate
self.sstp_handle = None
self.sstp_entry_db = None
self.sstp_request_handler = None
##
self.old_otherghostname = None ## FIXME
# create vanish dialog
- self.__vanish_dialog = VanishDialog(self)
+ vanish_dialog_callback = {
+ 'notify_vanish_confirmation': self.notify_vanish_confirmation,
+ 'notify_event': self.notify_event,
+ }
+ self.__vanish_dialog = VanishDialog(vanish_dialog_callback)
self.cantalk = 1
self.__sender = 'ninix-aya'
self.__charset = 'Shift_JIS'
'shiori', default_path, saori_lib=saori_lib)
self.__temp_mode = 0
self.__observer = []
- self.balloon = ninix.balloon.Balloon(self, self.prefs, debug)
- self.surface = ninix.surface.Surface(self, self.prefs, debug)
+ balloon_callback = {
+ 'is_paused': self.is_paused,
+ 'notify_balloon_click': self.notify_balloon_click,
+ 'notify_event': self.notify_event,
+ 'notify_link_selection': self.notify_link_selection,
+ 'notify_user_teach': self.notify_user_teach,
+ 'position_balloons': self.position_balloons,
+ 'reset_idle_time': self.reset_idle_time,
+ }
+ for key in ['get_preference']:
+ balloon_callback[key] = self.callback[key]
+ self.balloon = ninix.balloon.Balloon(balloon_callback, debug)
+ surface_callback = {
+ 'about': self.about,
+ 'busy': self.busy,
+ 'close_sakura': self.close,
+ 'enqueue_event': self.enqueue_event,
+ 'getstring': self.getstring,
+ 'get_balloon_size': self.get_balloon_size,
+ 'get_current_balloon_name': self.get_current_balloon_name,
+ 'get_keroname': self.get_keroname,
+ 'get_own_balloon_name': self.get_own_balloon_name,
+ 'get_prefix': self.get_prefix,
+ 'get_selfname': self.get_selfname,
+ 'is_running': self.is_running,
+ 'network_update': self.network_update,
+ 'notify_deiconified': self.notify_deiconified,
+ 'notify_event': self.notify_event,
+ 'notify_iconified': self.notify_iconified,
+ 'notify_observer': self.notify_observer,
+ 'notify_site_selection': self.notify_site_selection,
+ 'notify_surface_click': self.notify_surface_click,
+ 'notify_surface_mouse_motion': self.notify_surface_mouse_motion,
+ 'reset_idle_time': self.reset_idle_time,
+ 'select_balloon': self.select_balloon,
+ 'select_kinoko': self.select_kinoko,
+ 'select_nekodorif': self.select_nekodorif,
+ 'select_sakura': self.select_sakura,
+ 'set_balloon_direction': self.set_balloon_direction,
+ 'set_balloon_position': self.set_balloon_position,
+ 'vanish_sakura': self.vanish,
+ 'get_current_item': self.get_current_item,
+ }
+ for key in ['close_all', 'get_preference', 'edit_preferences',
+ 'open_ghost_manager', 'show_usage', 'start_sakura',
+ 'get_ghost_list', 'get_shell_list', 'get_balloon_list',
+ 'get_nekodorif_list', 'get_kinoko_list',
+ 'get_plugin_list', 'select_plugin']:
+ surface_callback[key] = self.callback[key]
+ self.surface = ninix.surface.Surface(surface_callback, debug)
self.keep_silence(False)
desc, shiori_dir, use_makoto, surface_set, balloon, prefix, \
shiori_dll, shiori_name = data
self.new(desc, shiori_dir, use_makoto, surface_set, balloon, prefix,
shiori_dll, shiori_name)
- def get_callback(self, name): ## FIXME
- callback = {'close all': self.app.close_all_ghosts,
- 'select sakura': self.app.select_sakura,
- 'start': self.app.start_sakura_cb,
- 'select plugin': self.app.select_plugin,
- 'select nekodorif': self.app.select_nekodorif,
- 'select kinoko': self.app.select_kinoko,
- }
- if name in callback:
- return callback[name]
+ def get_current_item(self):
+ return self.current
+
+ def select_sakura(self, event, item):
+ if self.busy():
+ gtk.gdk.beep()
+ return
+ self.callback['change_sakura'](self, item, 'manual')
+
+ def select_nekodorif(self, event, item):
+ self.callback['select_nekodorif'](item, self)
+
+ def select_kinoko(self, event, item):
+ self.callback['select_kinoko'](item, self)
def set_observer(self, observer):
if observer not in self.__observer:
self.shiori_name = shiori_name
name = (shiori_dll, shiori_name)
self.shiori = self.__dll.request(name)
- self.updateman = ninix.update.NetworkUpdate(self)
+ update_callback = {
+ 'enqueue_event': self.enqueue_event,
+ 'check_event_queue': self.check_event_queue,
+ }
+ self.updateman = ninix.update.NetworkUpdate(update_callback)
self.audio_player = gst.element_factory_make("playbin", "player")
fakesink = gst.element_factory_make("fakesink", "fakesink")
self.audio_player.set_property("video-sink", fakesink)
reset_event = ['OnGhostChanging', 'OnShellChanging', 'OnVanishSelected']
+ def check_event_queue(self):
+ return bool(self.event_queue)
+
def enqueue_event(self, event, *arglist, **argdict): ## FIXME
for key in argdict:
assert key in ['proc'] # trap typo, etc.
def reset_idle_time(self):
self.idle_start = time.time()
+ def notify_preference_changed(self): ## FIXME
+ self.balloon.reset_fonts()
+ flag = self.callback['get_preference']('use_pna')
+ self.set_use_pna(flag)
+ scale = self.callback['get_preference']('surface_scale')
+ self.set_surface_scale(scale)
+ flag = self.callback['get_preference']('balloon_scalling')
+ self.set_balloon_scalling(flag)
+ alpha = self.callback['get_preference']('surface_alpha')
+ self.set_surface_alpha(alpha)
+ alpha = self.callback['get_preference']('balloon_alpha')
+ self.set_balloon_alpha(alpha)
+ quality = self.callback['get_preference']('animation_quality')
+ self.set_animation_quality(quality)
+ flag = self.callback['get_preference']('seriko_inactive')
+ self.set_seriko_inactive(flag)
+
def set_use_pna(self, flag): ## FIXME
self.surface.set_use_pna(flag)
self.balloon.set_use_pna(flag)
result = self.surface.get_position(side)
return result if result is not None else (0, 0)
- def reset_balloon_fonts(self): ## FIXME: remove
- self.balloon.reset_fonts()
+# def reset_balloon_fonts(self): ## FIXME: remove
+# self.balloon.reset_fonts()
def set_balloon_position(self, side, x, y):
self.balloon.set_position(side, x, y)
def vanish_by_myself(self):
self.vanished_count += 1
self.ghost_time = 0
- self.app.stop_sakura(self.app.vanish_sakura)
+ self.callback['stop_sakura'](self.callback['vanish_sakura'])
def get_name(self):
return self.desc.get('name', unicode(_('Sakura&Unyuu'), 'utf-8'))
result = ''
if to and result:
def proc():
- self.communicate.send_message(
+ self.callback['send_message'](
to, self.get_selfname(), result)
communication = proc
else:
def proc(self=self):
self.vanished_count += 1
self.ghost_time = 0
- gobject.idle_add(self.app.vanish_sakura, self) ## FIXME
+ gobject.idle_add(self.callback['vanish_sakura'], self)
self.enqueue_event('OnVanishSelected', proc=proc)
self.vanished = 1 ## FIXME
def notify_iconified(self):
self.cantalk = 0
- self.app.select_current_sakura()
+ self.callback['select_current_sakura']()
if not self.passivemode:
self.reset_script(1)
self.stand_by(1)
def notify_deiconified(self):
if not self.cantalk:
self.cantalk = 1
- self.app.select_current_sakura()
+ self.callback['select_current_sakura']()
if not self.passivemode:
self.notify_event('OnWindowStateRestore')
return
name = self.get_own_balloon_name()
if item != name:
- desc, balloon = self.app.get_balloon_description(item)
+ desc, balloon = self.callback['get_balloon_description'](item)
+ else:
+ desc, balloon = self.own_balloon
self.balloon.hide_all()
self.set_balloon(desc, balloon)
self.balloon.set_balloon_default()
def set_surface_default(self, side=None):
self.surface.set_surface_default(side)
+ def get_surface_scale(self):
+ return self.surface.get_scale()
+
def set_surface_scale(self, scale):
self.surface.set_scale(scale)
self.balloon.set_scale(scale)
- self.notify_observer('set scale')
def get_surface_size(self, side):
result = self.surface.get_surface_size(side)
if set_type == 'g':
print 'ghost', item
if not self.surface_set:
- shell_name, surface_set, balloon = self.app.request_shell(0)
+ shell_name, surface_set, balloon = self.callback['request_shell'](0)
name, surface_dir, surface_desc, surface_alias, surface, surface_tooltips = \
surface_set[0]
surface_set = None
balloon = self.own_balloon
elif set_type == 's':
print 'shell', item
- shell_name, surface_set, balloon = self.app.request_shell(i)
+ shell_name, surface_set, balloon = self.callback['request_shell'](i)
name, surface_dir, surface_desc, surface_alias, surface, surface_tooltips = \
surface_set[j]
if not surface_set:
name = prev_name
self.set_surface(surface_desc, surface_alias, surface, surface_name,
surface_dir, surface_tooltips)
- if self.prefs.get('ignore_default') or not balloon:
+ if self.callback['get_preference']('ignore_default') or not balloon:
balloon_name = self.desc.get('balloon', '')
number = None
if balloon_name:
- number = self.app.find_balloon_by_name(balloon_name)
+ number = self.callback['find_balloon_by_name'](balloon_name)
if number is None:
- default_balloon = self.prefs.get('default_balloon')
- number = self.app.find_balloon_by_name(default_balloon) or 0
- balloon = self.app.request_balloon(number)
+ default_balloon = self.callback['get_preference']('default_balloon')
+ number = self.callback['find_balloon_by_name'](default_balloon) or 0
+ balloon = self.callback['request_balloon'](number)
desc, balloon = balloon
self.set_balloon(desc, balloon)
if not temp:
self.notify_observer('finalize')
self.__running = 0
self.save_history()
- self.communicate.rebuild_ghostdb(self, None)
+ self.callback['rebuild_ghostdb'](self, None)
self.hide_all()
self.surface.finalize()
self.balloon.finalize()
if self.clock[0] != second: ## FIXME
if not self.__temp_mode:
self.ghost_time += 1
- self.communicate.rebuild_ghostdb(
+ self.callback['rebuild_ghostdb'](
self,
self.get_selfname(),
self.get_surface_id(0),
- self.get_surface_id(1)) ## FIXME
- otherghostname = self.communicate.get_otherghostname(
- self.get_selfname()) ## FIXME
+ self.get_surface_id(1))
+ otherghostname = self.callback['get_otherghostname'](
+ self.get_selfname())
if otherghostname != self.old_otherghostname:
args = []
args.extend(otherghostname)
self.__balloon_life = 0
self.stand_by(0)
self.notify_event('OnBalloonClose', self.__current_script)
- if self.prefs.get('sink_after_talk'):
+ if self.callback['get_preference']('sink_after_talk'):
self.surface.lower_all()
elif self.event_queue and self.handle_event():
pass
if self.__temp_mode == 1:
time.sleep(1.4)
self.finalize()
- self.app.close_ghost(self)
- self.app.reset_sstp_flag()
+ self.callback['close_ghost'](self)
+ self.callback['reset_sstp_flag']()
return False
else:
- self.app.reset_sstp_flag()
+ self.callback['reset_sstp_flag']()
self.leave_temp_mode()
return True
else:
self.hide_all()
sys.stdout.write('reloading....\n')
self.shiori.unload()
- self.app.stop_sakura(self, self.app.reload_current_sakura, self)
+ self.callback['stop_sakura'](self, self.callback['reload_current_sakura'], self)
self.restart() ## FIXME
sys.stdout.write('done.\n')
self.enqueue_event(*self.reload_event)
return True
def quit(self):
- self.app.stop_sakura(self)
+ self.callback['stop_sakura'](self)
### SCRIPT PLAYER ###
def start_script(self, script, origin=None):
self.balloon.set_balloon_default()
self.current_time = time.localtime(time.time())
self.reset_idle_time()
- if self.prefs.get('raise_before_talk'):
+ if self.callback['get_preference']('raise_before_talk'):
self.raise_all()
def __yen_e(self, args):
self.script_wait = time.time() + amount
def __yen_w(self, args):
- script_speed = self.prefs.get('script_speed')
+ script_speed = self.callback['get_preference']('script_speed')
if not self.quick_session and script_speed >= 0:
self.__set_weight(args[0], 0.05) # 50ms
def __yen__w(self, args):
- script_speed = self.prefs.get('script_speed')
+ script_speed = self.callback['get_preference']('script_speed')
if not self.quick_session and script_speed >= 0:
self.__set_weight(args[0], 0.001) # 1ms
self.quit()
def __yen_plus(self, args):
- self.app.select_ghost(self, 1)
+ self.callback['select_ghost'](self, 1)
def __yen__plus(self, args):
- self.app.select_ghost(self, 0)
+ self.callback['select_ghost'](self, 0)
def __yen_m(self, args):
self.write_sstp_handle(self.expand_meta(args[0]))
else:
self.balloon.open_inputbox(args[2])
elif args[0:2] == ['open', 'configurationdialog']:
- self.prefs.edit_preferences()
+ self.callback['edit_preferences']()
elif args[0:2] == ['change', 'shell'] and argc > 2:
- self.app.select_shell_by_name(self, args[2], 0)
+ self.callback['select_shell_by_name'](self, args[2], 0)
elif args[0:2] == ['change', 'ghost'] and argc > 2:
if args[2] == 'random':
- self.app.select_ghost(self, 0, 0)
+ self.callback['select_ghost'](self, 0, 0)
else:
- self.app.select_ghost_by_name(self, args[2], 0)
+ self.callback['select_ghost_by_name'](self, args[2], 0)
elif args[0:1] == ['updatebymyself']:
if not self.busy(check_updateman=False):
self.__update()
count = self.balloon.get_text_count(self.script_side)
if self.surface.invoke_talk(self.script_side, surface_id, count):
self.balloon.reset_text_count(self.script_side)
- script_speed = self.prefs.get('script_speed')
+ script_speed = self.callback['get_preference']('script_speed')
if script_speed > 0:
self.script_wait = time.time() + script_speed * 0.02
return
text = self.expand_meta(node[1])
if self.anchor:
self.anchor[1] = ''.join((self.anchor[1], text))
- script_speed = self.prefs.get('script_speed')
+ script_speed = self.callback['get_preference']('script_speed')
if not self.quick_session and script_speed >= 0:
self.processed_text = text
else:
class VanishDialog:
- def __init__(self, sakura):
- self.__sakura = sakura
+ def __init__(self, callback):
+ self.callback = callback
self.window = gtk.Dialog()
self.window.connect('delete_event', self.cancel)
self.window.set_title('Vanish')
def ok(self, widget, event=None):
self.window.hide()
- self.__sakura.notify_vanish_confirmation()
+ self.callback['notify_vanish_confirmation']()
return True
def cancel(self, widget, event=None):
self.window.hide()
- self.__sakura.notify_event('OnVanishCancel')
+ self.callback['notify_event']('OnVanishCancel')
return True
class SSTPServer(AsynchronousSSTPServer):
- def __init__(self, address, app):
- self.__app = app
+ def __init__(self, address, callback):
+ self.callback = callback
AsynchronousSSTPServer.__init__(self, address, SSTPRequestHandler)
self.request_handler = None
def close(self):
self.socket.close()
- def get_current_sakura(self):
- return self.__app.get_current_sakura()
-
- def if_ghost(self, ifghost):
- return self.__app.if_ghost(ifghost)
-
- def get_ghost_names(self):
- return self.__app.get_ghost_names()
-
- def check_request_queue(self, sender):
- return self.__app.check_request_queue(sender)
-
- def enqueue_script_if_ghost(
- self, if_ghost, script, sender, handle,
- address, show_sstp_marker, use_translator, entry_db):
- self.__app.enqueue_script_if_ghost(
- if_ghost, script, sender, handle,
- address, show_sstp_marker, use_translator, entry_db)
class SSTPRequestHandler(BaseSSTPRequestHandler):
def handle(self):
- sakura = self.server.get_current_sakura()
- if not sakura.cantalk:
+ if not self.server.callback['get_sakura_cantalk']():
self.error = self.version = None
if not self.parse_request(self.rfile.readline()):
return
event = self.get_event()
if event is None:
return
- sakura = self.server.get_current_sakura()
- script = sakura.get_event_response(*event)
+ script = self.server.callback['get_event_response'](*event)
if script and self.check_script(script):
return
if version == 1.0:
address = self.client_address
self.send_response(200) # OK
show_sstp_marker, use_translator = self.get_options()
- self.server.enqueue_script_if_ghost(
+ self.server.callback['enqueue_script_if_ghost'](
if_ghost, script, sender, handle,
address, show_sstp_marker, use_translator, entry_db)
if entry_db is None or entry_db.is_empty():
self.send_response(200) # OK
show_sstp_marker, use_translator = self.get_options()
- sakura = self.server.get_current_sakura()
- sakura.enqueue_script(script, sender, handle, address,
- show_sstp_marker, use_translator)
+ self.server.callback['enqueue_script'](
+ script, sender, handle, address,
+ show_sstp_marker, use_translator)
elif self.server.request_handler:
self.send_response(409) # Conflict
else:
show_sstp_marker, use_translator = self.get_options()
- sakura = self.server.get_current_sakura()
- sakura.enqueue_script(script, sender, handle, address,
- show_sstp_marker, use_translator,
- entry_db, self.server)
+ self.server.callback['enqueue_script'](
+ script, sender, handle, address,
+ show_sstp_marker, use_translator, entry_db, self.server)
self.server.request_handler = self # keep alive
PROHIBITED_TAGS = [r'\j', r'\-', r'\+', r'\_+', r'\!']
continue
script = line[7:].strip()
if current: # NOTIFY
- ghost = self.ghost_names()
+ ghost = self.server.callback['get_ghost_name']()
if ghost == if_ghost:
return script, if_ghost
else: # SEND
- if self.server.if_ghost(if_ghost):
+ if self.server.callback['if_ghost'](if_ghost):
return script, if_ghost
if default is None:
default = script, if_ghost
result = host == '127.0.0.1'
return result
- def ghost_names(self):
- sakura = self.server.get_current_sakura()
- return '%s,%s' % (sakura.get_selfname(), sakura.get_keroname())
-
# EXECUTE
def do_EXECUTE_1_0(self):
self.handle_command()
return
elif command == 'getname':
self.send_response(200)
- name = self.ghost_names()
+ name = self.server.callback['get_ghost_name']()
self.wfile.write(''.join((name.encode('utf-8', 'ignore'), '\r\n')))
self.wfile.write('Charset: UTF-8\r\n')
elif command == 'getversion':
self.wfile.write('ninix-aya %s\r\n' % ninix.version.VERSION)
elif command == 'quiet':
self.send_response(200)
- sakura = self.server.get_current_sakura()
- sakura.keep_silence(True)
+ self.server.callback['keep_silence'](True)
elif command == 'restore':
self.send_response(200)
- sakura = self.server.get_current_sakura()
- sakura.keep_silence(False)
+ self.server.callback['keep_silence'](False)
elif command == 'getnames':
self.send_response(200)
- for name in self.server.get_ghost_names():
+ for name in self.server.callback['get_ghost_names']():
self.wfile.write(
''.join((name.encode('utf-8', 'ignore'), '\r\n')))
self.wfile.write('Charset: UTF-8\r\n')
elif command == 'checkqueue':
self.send_response(200)
- count, total = self.server.check_request_queue(sender)
+ count, total = self.server.callback['check_request_queue'](sender)
self.wfile.write(''.join((count, '\r\n')))
self.wfile.write(''.join((total, '\r\n')))
else:
return None
return unicode(command, charset, 'replace').lower()
- def do_COMMUNICATE_1_1(self): ## FIXME
+ def do_COMMUNICATE_1_1(self):
if not self.check_decoder():
return
sender = self.get_sender()
if sentence is None:
return
self.send_response(200) # OK
- sakura = self.server.get_current_sakura()
- sakura.enqueue_event('OnCommunicate', sender, sentence)
+ self.server.callback['enqueue_event'](
+ 'OnCommunicate', sender, sentence)
return
def get_sentence(self):
keymap_old = {}
keymap_new = {}
- def __init__(self, sakura, prefs, debug=0):
- self.__sakura = sakura
- self.prefs = prefs
+ def __init__(self, callback, debug=0):
self.debug = debug
self.window = []
self.__menu = None
self.desc = None
self.__use_pna = False
self.__alpha_channel = None
+ self.callback = callback
def set_debug(self, debug):
self.debug = debug
for surface_window in self.window:
surface_window.set_scale(scale)
surface_window.reset_surface()
+ self.callback['notify_observer']('set scale')
def set_animation_quality(self, quality):
for surface_window in self.window:
gtk_window.deiconify()
def window_state(self, window, event):
- if not self.__sakura.is_running():
+ if not self.callback['is_running']():
return
if event.new_window_state & gtk.gdk.WINDOW_STATE_ICONIFIED:
if window == self.window[0].window:
- self.__sakura.notify_iconified()
- self.__sakura.notify_observer('iconified')
+ self.callback['notify_iconified']()
+ self.callback['notify_observer']('iconified')
for surface_window in self.window:
gtk_window = surface_window.window
if gtk_window != window and \
gtk.gdk.WINDOW_STATE_ICONIFIED:
gtk_window.deiconify()
if window == self.window[0].window:
- self.__sakura.notify_deiconified()
+ self.callback['notify_deiconified']()
return
def delete(self, window, event):
- self.__sakura.quit()
- return False
+ return True
def key_press(self, window, event):
name = self.keymap_old.get(event.keyval, event.string)
keycode = self.keymap_new.get(event.keyval, event.string)
if name or keycode:
- self.__sakura.notify_event('OnKeyPress', name, keycode)
+ self.callback['notify_event']('OnKeyPress', name, keycode)
return True
def window_stick(self, action):
for surface_window in self.window:
surface_window.destroy()
self.window = []
- for name, side, default, alias in [('sakura', 0, '0', alias0),
- ('kero', 1, '10', alias1)]:
- if name == 'sakura':
- title = self.__sakura.get_selfname() or \
- ''.join(('surface.', name)) ## FIXME
- else:
- title = self.__sakura.get_keroname() or \
- ''.join(('surface.', name)) ## FIXME
- skip_taskbar = bool(side >= 1)
- gtk_window = self.create_gtk_window(title, skip_taskbar)
- seriko = self.get_seriko(surface)
- tooltips = {}
- if name in self.__tooltips:
- tooltips = self.__tooltips[name]
- surface_window = SurfaceWindow(
- gtk_window, side, self.__sakura, self.prefs, desc, alias,
- surface, tooltips, pixbufs, seriko, region, mayuna, bind[name],
- default, self.__use_pna, self.__alpha_channel, self.debug)
- self.window.append(surface_window)
self.__surface = surface
- self.__menu = ninix.menu.Menu(self.__sakura, self)
+ self.add_window(0, '0', alias0, mayuna, bind['sakura'])
+ self.add_window(1, '10', alias1, mayuna, bind['kero'])
+ menu_callback = {
+ 'stick_window': self.window_stick,
+ 'toggle_bind': self.toggle_bind,
+ }
+ for key in ['network_update', 'vanish_sakura', 'edit_preferences',
+ 'open_ghost_manager', 'show_usage', 'about',
+ 'close_sakura', 'close_all', 'getstring',
+ 'notify_site_selection', 'get_ghost_list', 'select_sakura',
+ 'start_sakura', 'get_shell_list', 'get_balloon_list',
+ 'get_own_balloon_name', 'select_balloon',
+ 'get_current_balloon_name', 'get_current_item',
+ 'get_plugin_list', 'select_plugin',
+ 'get_nekodorif_list', 'select_nekodorif',
+ 'get_kinoko_list', 'select_kinoko']:
+ menu_callback[key] = self.callback[key]
+ self.__menu = ninix.menu.Menu(menu_callback)
top_dir = self.prefix
name = self.desc.get('menu.background.bitmap.filename',
'menu_background.png')
name = name.replace('\\', '/')
path = os.path.join(top_dir, name)
if not os.path.exists(path):
- top_dir = os.path.join(self.__sakura.get_prefix(),
+ top_dir = os.path.join(self.callback['get_prefix'](),
'ghost', 'master')
path = os.path.join(top_dir, 'menu_background.png')
if os.path.exists(path):
if path_background:
self.__menu.set_pixmap(
path_background, path_sidebar, path_foreground)
- fontcolor_r = self.desc.getint('menu.background.font.color.r', 0)
- fontcolor_g = self.desc.getint('menu.background.font.color.g', 0)
- fontcolor_b = self.desc.getint('menu.background.font.color.b', 0)
+ fontcolor_r = self.desc.get_with_type('menu.background.font.color.r', int, 0)
+ fontcolor_g = self.desc.get_with_type('menu.background.font.color.g', int, 0)
+ fontcolor_b = self.desc.get_with_type('menu.background.font.color.b', int, 0)
background = (fontcolor_r, fontcolor_g, fontcolor_b)
- fontcolor_r = self.desc.getint('menu.foreground.font.color.r', 0)
- fontcolor_g = self.desc.getint('menu.foreground.font.color.g', 0)
- fontcolor_b = self.desc.getint('menu.foreground.font.color.b', 0)
+ fontcolor_r = self.desc.get_with_type('menu.foreground.font.color.r', int, 0)
+ fontcolor_g = self.desc.get_with_type('menu.foreground.font.color.g', int, 0)
+ fontcolor_b = self.desc.get_with_type('menu.foreground.font.color.b', int, 0)
foreground = (fontcolor_r, fontcolor_g, fontcolor_b)
self.__menu.set_fontcolor(background, foreground)
self.__menu.create_mayuna_menu(self.get_mayuna_menu())
- def add_window(self, side, default):
- assert side >= 2 and len(self.window) == side ## FIXME
- name = 'char%d' % side
- title = ''.join(('surface.', name))
- gtk_window = self.create_gtk_window(title, 1)
+ def add_window(self, side, default, alias=None, mayuna={}, bind={}):
+ assert len(self.window) == side
+ if side == 0:
+ name = 'sakura'
+ title = self.callback['get_selfname']() or \
+ ''.join(('surface.', name))
+ elif side == 1:
+ name = 'kero'
+ title = self.callback['get_keroname']() or \
+ ''.join(('surface.', name))
+ else:
+ name = 'char%d' % side
+ title = ''.join(('surface.', name))
+ skip_taskbar = bool(side >= 1)
+ gtk_window = self.create_gtk_window(title, skip_taskbar)
seriko = self.get_seriko(self.__surface)
tooltips = {}
if name in self.__tooltips:
tooltips = self.__tooltips[name]
+ surface_window_callback = {}
+ for key in ['enqueue_event', 'notify_observer', 'get_preference',
+ 'set_balloon_direction', 'reset_idle_time',
+ 'notify_surface_click', 'notify_event', 'busy',
+ 'notify_surface_mouse_motion']:
+ surface_window_callback[key] = self.callback[key]
surface_window = SurfaceWindow(
- gtk_window, side, self.__sakura, self.prefs, self.desc, None,
+ gtk_window, side, surface_window_callback, self.desc, alias,
self.__surface, tooltips, self.__pixbufs, seriko, self.__region,
- {}, {}, default, self.__use_pna, self.__alpha_channel, self.debug)
+ mayuna, bind, default, self.__use_pna, self.__alpha_channel,
+ self.debug)
self.window.append(surface_window)
surface_window.set_scale(self.__scale)
##surface_window.set_surface(default)
x, y = self.get_position(side)
sox, soy = self.window[side].get_surface_offset()
w, h = self.get_surface_size(side)
- bw, bh = self.__sakura.get_balloon_size(side)
+ bw, bh = self.callback['get_balloon_size'](side)
ox, oy = self.get_balloon_offset(side)
direction = self.get_direction(side)
align = self.get_alignment(side)
by = min(y + soy + oy, top + scrn_h - bh)
self.set_position(side, x, y)
self.set_direction(side, direction)
- self.__sakura.set_balloon_position(side, bx, by)
+ self.callback['set_balloon_position'](side, bx, by)
def reset_position(self):
left, top, scrn_w, scrn_h = ninix.pix.get_workarea()
y = top
else:
y = top + scrn_h - h
- bw, bh = self.__sakura.get_balloon_size(side)
+ bw, bh = self.callback['get_balloon_size'](side)
ox, oy = self.get_balloon_offset(side)
direction = 0 # left
bx = max(x - bw + ox, left)
else:
- b0w, b0h = self.__sakura.get_balloon_size(side - 1)
- b1w, b1h = self.__sakura.get_balloon_size(side)
+ b0w, b0h = self.callback['get_balloon_size'](side - 1)
+ b1w, b1h = self.callback['get_balloon_size'](side)
o0x, o0y = self.get_balloon_offset(side - 1)
o1x, o1y = self.get_balloon_offset(side)
w, h = self.get_surface_size(side)
by = min(y + oy, top + scrn_h - bh)
self.set_position(side, x, y)
self.set_direction(side, direction)
- self.__sakura.set_balloon_position(side, bx, by)
+ self.callback['set_balloon_position'](side, bx, by)
s0x, s0y, s0w, s0h = x, y, w, h ## FIXME
- ##self.__sakura.notify_observer('set position')
+ ##self.callback['notify_observer']('set position')
def set_position(self, side, x, y):
if len(self.window) > side:
self.window[side].set_position(x, y)
- self.__sakura.notify_observer('set position')
+ self.callback['notify_observer']('set position')
def get_position(self, side):
if len(self.window) > side:
def show(self, side):
if len(self.window) > side:
self.window[side].show()
- self.__sakura.notify_observer('show')
- self.__sakura.notify_observer('raise', (side)) ## FIXME
+ self.callback['notify_observer']('show')
+ self.callback['notify_observer']('raise', (side)) # XXX
def hide_all(self):
for side in range(len(self.window)):
self.window[side].hide()
- self.__sakura.notify_observer('hide')
+ self.callback['notify_observer']('hide')
def hide(self, side):
if len(self.window) > side:
self.window[side].hide()
- self.__sakura.notify_observer('hide')
+ self.callback['notify_observer']('hide')
def raise_all(self):
for side in range(len(self.window)):
self.window[side].raise_()
- self.__sakura.notify_observer('raise', (side))
+ self.callback['notify_observer']('raise', (side))
def raise_(self, side):
if len(self.window) > side:
self.window[side].raise_()
- self.__sakura.notify_observer('raise', (side))
+ self.callback['notify_observer']('raise', (side))
def lower_all(self):
for side in range(len(self.window)):
self.window[side].lower()
- self.__sakura.notify_observer('lower')
+ self.callback['notify_observer']('lower')
def lower(self, side):
if len(self.window) > side:
self.window[side].lower()
- self.__sakura.notify_observer('lower')
+ self.callback['notify_observer']('lower')
def invoke(self, side, actor_id):
if len(self.window) > side:
pixbuf = None
if path is not None:
try:
- pixbuf = ninix.pix.create_pixbuf_from_file(path, is_pnr=0)
+ pixbuf = ninix.pix.create_pixbuf_from_file(path, is_pnr=False)
except:
pixbuf = None
for window in self.window:
('text/plain', 0, 0),
]
- def __init__(self, window, side, sakura, prefs, desc, alias, surface, tooltips,
+ def __init__(self, window, side, callback, desc, alias, surface, tooltips,
pixbuf, seriko, region, mayuna, bind,
default_id, use_pna, alpha, debug):
self.window = window
self.side = side
- self.__sakura = sakura
- self.prefs = prefs
+ self.callback = callback
self.desc = desc
self.alias = alias
self.tooltips = tooltips
gtk.gdk.POINTER_MOTION_MASK|
gtk.gdk.POINTER_MOTION_HINT_MASK|
gtk.gdk.SCROLL_MASK)
- self.callbacks = []
for signal, func in [('expose_event', self.redraw),
('button_press_event', self.button_press),
('button_release_event', self.button_release),
('drag_data_received', self.drag_data_received),
('scroll_event', self.scroll),
]:
- self.callbacks.append(self.darea.connect(signal, func))
+ self.darea.connect(signal, func)
self.darea.drag_dest_set(gtk.DEST_DEFAULT_ALL, self.dnd_targets,
gtk.gdk.ACTION_COPY)
self.window.add(self.darea)
if scheme == 'file' and os.path.exists(pathname):
filelist.append(pathname)
if filelist:
- self.__sakura.enqueue_event(
+ self.callback['enqueue_event'](
'OnFileDrop2', chr(1).join(filelist), self.side)
return True
# relocate window
self.set_position(x, y)
if self.side < 2:
- self.__sakura.notify_observer('set surface')
+ self.callback['notify_observer']('set surface')
def iter_mayuna(self, surface_width, surface_height, mayuna, done):
for surface, interval, method, args in mayuna.patterns:
cr.paint()
cr.set_source_pixbuf(self.current_surface_pixbuf, 0, 0)
cr.paint_with_alpha(self.__alpha_channel)
- if self.prefs.get('check_collision'):
+ if self.callback['get_preference']('check_collision'):
self.draw_region()
def remove_overlay(self, actor):
self.__move(xoffset, yoffset)
if self.side < 2:
args = (self.side, xoffset, yoffset)
- self.__sakura.notify_observer('move surface', args) # animation
+ self.callback['notify_observer']('move surface', args) # animation
def get_balloon_offset(self):
path, config = self.surface[''.join(('surface', self.surface_id))]
side = self.side
if side == 0:
name = 'sakura'
- x = config.getint('%s.balloon.offsetx' % name)
- y = config.getint('%s.balloon.offsety' % name)
+ x = config.get_with_type('%s.balloon.offsetx' % name, int)
+ y = config.get_with_type('%s.balloon.offsety' % name, int)
elif side == 1:
name = 'kero'
- x = config.getint('%s.balloon.offsetx' % name)
- y = config.getint('%s.balloon.offsety' % name)
+ x = config.get_with_type('%s.balloon.offsetx' % name, int)
+ y = config.get_with_type('%s.balloon.offsety' % name, int)
else:
name = 'char%d' % side
x, y = None, None # XXX
if x is None:
- x = self.desc.getint('%s.balloon.offsetx' % name, 0)
+ x = self.desc.get_with_type('%s.balloon.offsetx' % name, int, 0)
if y is None:
- y = self.desc.getint('%s.balloon.offsety' % name, 0)
+ y = self.desc.get_with_type('%s.balloon.offsety' % name, int, 0)
x *= self.__scale / 100
y *= self.__scale / 100
return x, y
return part
return ''
- def get_config_int(self, name, scaling=False):
+ def __get_with_scaling(self, name, conv):
basename = ''.join(('surface', self.surface_id))
path, config = self.surface[basename]
- value = config.getint(name)
+ value = config.get_with_type(name, conv)
if value is not None:
- if scaling:
- value = int(value * self.__scale / 100)
+ value = conv(value * self.__scale / 100)
return value
def get_center(self):
- centerx = self.get_config_int('point.centerx', scaling=True)
- centery = self.get_config_int('point.centery', scaling=True)
+ centerx = self.__get_with_scaling('point.centerx', int)
+ centery = self.__get_with_scaling('point.centery', int)
return centerx, centery
def get_kinoko_center(self):
- centerx = self.get_config_int('point.kinoko.centerx', scaling=True)
- centery = self.get_config_int('point.kinoko.centery', scaling=True)
+ centerx = self.__get_with_scaling('point.kinoko.centerx', int)
+ centery = self.__get_with_scaling('point.kinoko.centery', int)
return centerx, centery
def get_direction(self):
def set_direction(self, direction):
self.direction = direction # 0: left, 1: right
- self.__sakura.set_balloon_direction(self.side, direction)
+ self.callback['set_balloon_direction'](self.side, direction)
def set_position(self, x, y):
self.position = (x, y)
old_x, old_y = self.get_position()
if new_x != old_x or new_y != old_y or new_y != y - q:
self.set_position(new_x, new_y)
- self.__sakura.notify_observer('set position')
+ self.callback['notify_observer']('set position')
def get_position(self):
return self.position
def destroy(self):
self.reset_pixbuf_cache()
- for tag in self.callbacks:
- self.darea.disconnect(tag)
self.seriko.terminate(self)
self.window.remove(self.darea)
self.darea.destroy()
self.window.window.lower()
def button_press(self, window, event):
- self.__sakura.reset_idle_time()
+ self.callback['reset_idle_time']()
x = int(event.x)
y = int(event.y)
x = int(x * 100 / self.__scale)
y = int(y * 100 / self.__scale)
click = 1 if event.type == gtk.gdk.BUTTON_PRESS else 2
- self.__sakura.notify_observer('raise', (self.side)) # automagical raise
- self.__sakura.notify_surface_click(
+ # automagical raise
+ self.callback['notify_observer']('raise', (self.side))
+ self.callback['notify_surface_click'](
event.button, click, self.side, x, y)
if click == 1 and event.button == 1:
self.window.begin_move_drag(
if part == '':
self.window.set_tooltip_text(None)
self.darea.window.set_cursor(None)
- self.__sakura.notify_event(
+ self.callback['notify_event'](
'OnMouseLeave', x, y, '', self.side, self.__current_part)
else:
if part in self.tooltips:
self.window.set_tooltip_text(None)
cursor = gtk.gdk.Cursor(gtk.gdk.HAND1)
self.darea.window.set_cursor(cursor)
- self.__sakura.notify_event(
+ self.callback['notify_event'](
'OnMouseEnter', x, y, '', self.side, part)
self.__current_part = part
- if not self.__sakura.busy():
+ if not self.callback['busy']():
if state & gtk.gdk.BUTTON1_MASK or \
state & gtk.gdk.BUTTON2_MASK or \
state & gtk.gdk.BUTTON3_MASK:
pass
else:
- self.__sakura.notify_surface_mouse_motion(
+ self.callback['notify_surface_mouse_motion'](
self.side, x, y, part)
return True
count = 0
if count != 0:
part = self.get_touched_region(x, y)
- self.__sakura.notify_event('OnMouseWheel',
- x, y, count, self.side, part)
+ self.callback['notify_event'](
+ 'OnMouseWheel', x, y, count, self.side, part)
return True
def toggle_bind(self, bind_id):
x, y, state = event.x, event.y, event.state
x = int(x * 100 / self.__scale)
y = int(y * 100 / self.__scale)
- self.__sakura.notify_event('OnMouseEnterAll', x, y, '', self.side, '')
+ self.callback['notify_event'](
+ 'OnMouseEnterAll', x, y, '', self.side, '')
def window_leave_notify(self, window, event):
x, y, state = event.x, event.y, event.state
x = int(x * 100 / self.__scale)
y = int(y * 100 / self.__scale)
if self.__current_part != '': # XXX
- self.__sakura.notify_event(
+ self.callback['notify_event'](
'OnMouseLeave', x, y, '', self.side, self.__current_part)
self.__current_part = ''
- self.__sakura.notify_event('OnMouseLeaveAll', x, y, '', self.side, '')
+ self.callback['notify_event'](
+ 'OnMouseLeaveAll', x, y, '', self.side, '')
return True
def configure(self, window, event):
__BACKUP_SUFFIX = '.BACKUP'
- def __init__(self, sakura):
- self.__sakura = sakura
+ def __init__(self, callback):
+ self.callback = callback
self.event_queue = []
self.state = None
self.backups = []
def interrupt(self):
self.event_queue = []
- if self.__sakura:
- self.__sakura.enqueue_event('OnUpdateFailure', 'artificial')
+ self.callback['enqueue_event']('OnUpdateFailure', 'artificial')
self.state = None
self.stop(revert=1)
return time.time() - self.timestamp > self.timeout
def run(self):
- if self.state is None or (self.__sakura and self.__sakura.event_queue):
+ if self.state is None or self.callback['check_event_queue']():
return 0
elif self.state == 0:
self.start_updates()
import sys
if len(sys.argv) != 3:
raise SystemExit, 'Usage: update.py homeurl ghostdir\n'
- update = NetworkUpdate(None)
+ update = NetworkUpdate({'enqueu_event': lambda *a: None,
+ 'check_event_queue': lambda *a: None,})
update.start(sys.argv[1], sys.argv[2], timeout=60)
while 1:
state = update.state
# PURPOSE. See the GNU General Public License for more details.
#
-NUMBER = '4.0.4'
+NUMBER = '4.0.5'
CODENAME = 'jump off into never-never land'
VERSION = '%s (%s)' % (NUMBER, CODENAME)