アレのチェッカーアプリ

仕組みは秘密だけど、うちの会社は(男子)トイレの個室が
使用中かどうかが分かるようになっている。

結果はjsonで取得できる(社外でも)。

んで、それをチェックするアプリやらが社内でたくさん作られたことがあったんだけど、
自分もなんか作ってみたのでメモ(今も誰かが作ってるかも)。

要件はこんな感じ。

  • 一定時間ごとにチェックして欲しい
  • ウインドウは出さないで、タスクトレイに入っていて欲しい
  • 結果はバルーンメッセージで表示して欲しい

環境はPySideを使った。
Python用のQtライブラリで、PyQtというのもあるんだけどそっちは有料なので、
こちらを使うことにした。


タスクトレイからバルーンメッセージ、というと面倒そうだけど
割と簡単に実現できる。こんな感じ。

import threading
from PySide import QtCore
from PySide import QtGui

class MainWindow(QtGui.QDialog):
    def __init__(self, parent = None):
        super(MainWindow, self).__init__(parent)
        self.resize(0, 0)  # ウインドウは表示しない

        # タスクトレイに「終了」メニューを追加
        self.quitAction = QtGui.QAction(u"&終了", self)
        self.connect(self.quitAction, QtCore.SIGNAL('triggered()'), QtGui.qApp, QtCore.SLOT('quit()'))
        self.quitAction.triggered.connect(self.trayCloseEvent)

        # 終了メニューと終了アクションを結びつける
        self.trayIconMenu = QtGui.QMenu(self)
        self.trayIconMenu.addAction(self.quitAction)

        # タスクトレイメニューとアイコンを設定
        self.trayIcon = QtGui.QSystemTrayIcon(self)
        self.trayIcon.setContextMenu(self.trayIconMenu)
        self.trayIcon.setIcon(QtGui.QIcon(ICON_FILE_NAME))
        
        # トレイを表示
        self.trayIcon.show()

        # チェッカーを持っておく
        self.__checker = Checker()

    # タスクトレイアイコンのメニューから「終了」を選んだ時
    def trayCloseEvent(self):
        self.endApplication()

    # ウインドウを閉じた時
    def closeEvent(self, event):
        self.endApplication()

    # 終了時の処理
    def endApplication(self):
        # スレッドを止めておく
        if self.__th.isAlive():
            self.__th._stop()
        QtGui.qApp.quit()

    # 実行
    def run(self):
        self.set_next_thread()
        return super(MainWindow, self).exec_()

    # 空き状況のチェック
    def check(self):
        r = self.__checker.check()
        self.trayIcon.showMessage("アレの状況", r)
        self.set_next_thread()

    # CHECK_INTERVAL_SECOND秒後にself.checkを実行するように設定
    # QThreadの方が良い...???
    def config_next_thread(self):
        self.__th = threading.Timer(CHECK_INTERVAL_SECOND, self.check)
        self.__th.start()

class Checker:
    def check():
        ### 取得する方法はいくらでもあると思うので、略

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    if not QtGui.QSystemTrayIcon.isSystemTrayAvailable():
        raise OSError("Can not use system tray on this system !")

    app.setQuitOnLastWindowClosed(False)
    app.setApplicationName('Checker')
    mainWindow = MainWindow()
    return mainWindow.run()

コードの行数は全部で140行ぐらい。
実行すると、こういう風に表示される。

f:id:woodboy644:20130729235846p:plain

PythonとQtだし、そのままMacでも動くのでは…と思ったら、
そんな都合の良い話は無かった。

具体的には...

  • Macでバルーンを出すには、Growlが必要 (Growl最新版は有料)
  • この辺に書かれているような、「おまじない」が必要らしい

2つ目が原因かどうかは分かんないけど、素直にGrowlを入れて実行したら
Segmentation Fault になった。

まずはQThreadを使うようにして、おまじないを試してみるのが良いかな。

あと、一定時間ごとに出るとちょっとウザい感じがするので、
ショートカットキーで出せたら良いかもしれない。