{"action":"created","issue":{"url":"https://api.github.com/repos/ReactiveX/RxPY/issues/49","labels_url":"https://api.github.com/repos/ReactiveX/RxPY/issues/49/labels{/name}","comments_url":"https://api.github.com/repos/ReactiveX/RxPY/issues/49/comments","events_url":"https://api.github.com/repos/ReactiveX/RxPY/issues/49/events","html_url":"https://github.com/ReactiveX/RxPY/pull/49","id":83255900,"number":49,"title":"Added Qt mainloop scheduler","user":{"login":"jdreaver","id":1253071,"avatar_url":"https://avatars.githubusercontent.com/u/1253071?v=3","gravatar_id":"","url":"https://api.github.com/users/jdreaver","html_url":"https://github.com/jdreaver","followers_url":"https://api.github.com/users/jdreaver/followers","following_url":"https://api.github.com/users/jdreaver/following{/other_user}","gists_url":"https://api.github.com/users/jdreaver/gists{/gist_id}","starred_url":"https://api.github.com/users/jdreaver/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jdreaver/subscriptions","organizations_url":"https://api.github.com/users/jdreaver/orgs","repos_url":"https://api.github.com/users/jdreaver/repos","events_url":"https://api.github.com/users/jdreaver/events{/privacy}","received_events_url":"https://api.github.com/users/jdreaver/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2015-06-01T01:28:21Z","updated_at":"2015-06-01T06:18:14Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/ReactiveX/RxPY/pulls/49","html_url":"https://github.com/ReactiveX/RxPY/pull/49","diff_url":"https://github.com/ReactiveX/RxPY/pull/49.diff","patch_url":"https://github.com/ReactiveX/RxPY/pull/49.patch"},"body":"I have added a `QtScheduler` to RxPY. It uses a `QTimer`, which is already very flexible, to perform any scheduling tasks. See the `QtScheduler._qtimer_schedule` method to see the meat of the class. It is compatible with PyQt4, PyQt5, and PySide (I have tested all 3 on my machine, and there isn't a reason there should be any fundamental behavior difference between the three).\r\n\r\nIn order to work, all the scheduler needs is a way to instantiate a `QTimer`. Currently, I have the user pass in the `QtCore` module from whatever Qt wrapper they decide to use. This feels un-Pythonic to me for some reason. I have a couple of alternatives:\r\n\r\n1. Allow the value of `qtcore` in the constructor to be `None`, and have us try to predict what framework to use. Basically, we just try to import them in succession until we don't get an `ImportError` (see the top of the new unit test file in this pull request). The problem with this approach is that we might guess incorrectly.\r\n2. Instead of passing in `QtCore`, have the user pass in `QtCore.QTimer`. This way, they could perform dependency injection if they wanted slightly different `QTimer` behavior from their own subclass. However, I am worried that users will get confused and instead pass in an in instantiated `QTimer` instead of simply the class.\r\n3. Somehow allow the user to select the Qt wrapper to use based on an environment variable, or by using the `rx.config` dict. Then, all we do is import whatever framework that have selected. I think this is the way to go, but I would like input on how to do it correctly. I am not sure that `rx.config` is designed to be modified by users.\r\n\r\nI also added an example. The unit tests and the example are basically copies of the tkinter versions. I just wanted to make sure the scheduler worked correctly for now without being too creative. In the future I will probably add more examples as I use RxPY more."},"comment":{"url":"https://api.github.com/repos/ReactiveX/RxPY/issues/comments/107320546","html_url":"https://github.com/ReactiveX/RxPY/pull/49#issuecomment-107320546","issue_url":"https://api.github.com/repos/ReactiveX/RxPY/issues/49","id":107320546,"user":{"login":"dbrattli","id":849479,"avatar_url":"https://avatars.githubusercontent.com/u/849479?v=3","gravatar_id":"","url":"https://api.github.com/users/dbrattli","html_url":"https://github.com/dbrattli","followers_url":"https://api.github.com/users/dbrattli/followers","following_url":"https://api.github.com/users/dbrattli/following{/other_user}","gists_url":"https://api.github.com/users/dbrattli/gists{/gist_id}","starred_url":"https://api.github.com/users/dbrattli/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dbrattli/subscriptions","organizations_url":"https://api.github.com/users/dbrattli/orgs","repos_url":"https://api.github.com/users/dbrattli/repos","events_url":"https://api.github.com/users/dbrattli/events{/privacy}","received_events_url":"https://api.github.com/users/dbrattli/received_events","type":"User","site_admin":false},"created_at":"2015-06-01T06:18:14Z","updated_at":"2015-06-01T06:18:14Z","body":"This is fantastic. Great work!"}}