├── .gitattributes
├── .gitignore
├── .idea
├── misc.xml
├── modules.xml
├── vcs.xml
├── workspace.xml
└── zroya.iml
├── LICENSE.txt
├── MANIFEST.in
├── README.md
├── TODO
├── changelog
├── docs
├── .buildinfo
├── .nojekyll
├── _images
│ ├── example_full_features_action.png
│ ├── example_full_features_attribution.png
│ ├── in_action_multiline_image.png
│ ├── in_action_one_line.png
│ ├── tutorials_callbacks_final.gif
│ ├── tutorials_first_steps.png
│ ├── tutorials_first_steps_troubleshooting.gif
│ ├── tutorials_template_actions.png
│ ├── tutorials_template_image.png
│ └── tutorials_template_three_lines.png
├── _sources
│ ├── commiting.rst.txt
│ ├── committing.rst.txt
│ ├── content.rst.txt
│ ├── documentation.rst.txt
│ ├── in_action.rst.txt
│ ├── index.rst.txt
│ └── tutorials
│ │ ├── callbacks.rst.txt
│ │ ├── index.rst.txt
│ │ ├── installation.rst.txt
│ │ └── template.rst.txt
├── _static
│ ├── ajax-loader.gif
│ ├── alabaster.css
│ ├── audio.html
│ ├── audio
│ │ ├── Alarm01.wav
│ │ ├── Alarm02.wav
│ │ ├── Alarm03.wav
│ │ ├── Alarm04.wav
│ │ ├── Alarm05.wav
│ │ ├── Alarm06.wav
│ │ ├── Alarm07.wav
│ │ ├── Alarm08.wav
│ │ ├── Alarm09.wav
│ │ ├── Alarm10.wav
│ │ ├── Default.wav
│ │ ├── Email.wav
│ │ ├── IM.wav
│ │ ├── Reminder.wav
│ │ ├── Ring01.wav
│ │ ├── Ring02.wav
│ │ ├── Ring03.wav
│ │ ├── Ring04.wav
│ │ ├── Ring05.wav
│ │ ├── Ring06.wav
│ │ ├── Ring07.wav
│ │ ├── Ring08.wav
│ │ ├── Ring09.wav
│ │ └── Ring10.wav
│ ├── basic.css
│ ├── comment-bright.png
│ ├── comment-close.png
│ ├── comment.png
│ ├── css
│ │ └── styles.css
│ ├── custom.css
│ ├── desktop.ini
│ ├── doctools.js
│ ├── documentation_options.js
│ ├── down-pressed.png
│ ├── down.png
│ ├── example_full_features.png
│ ├── example_full_features_action.png
│ ├── example_full_features_attribution.png
│ ├── file.png
│ ├── in_action_multiline_image.png
│ ├── in_action_one_line.png
│ ├── jquery-3.2.1.js
│ ├── jquery.js
│ ├── minus.png
│ ├── plus.png
│ ├── pygments.css
│ ├── searchtools.js
│ ├── tutorials_callbacks_final.gif
│ ├── tutorials_first_steps.png
│ ├── tutorials_first_steps_troubleshooting.gif
│ ├── tutorials_template_actions.png
│ ├── tutorials_template_image.png
│ ├── tutorials_template_three_lines.png
│ ├── underscore-1.3.1.js
│ ├── underscore.js
│ ├── up-pressed.png
│ ├── up.png
│ └── websupport.js
├── commiting.html
├── committing.html
├── content.html
├── documentation.html
├── genindex.html
├── in_action.html
├── index.html
├── objects.inv
├── py-modindex.html
├── search.html
├── searchindex.js
└── tutorials
│ ├── callbacks.html
│ ├── index.html
│ ├── installation.html
│ └── template.html
├── docs_source
├── doxygen
│ └── Doxyfile
└── sphinx
│ ├── make.bat
│ └── source
│ ├── _static
│ ├── audio.html
│ ├── audio
│ │ ├── Alarm01.wav
│ │ ├── Alarm02.wav
│ │ ├── Alarm03.wav
│ │ ├── Alarm04.wav
│ │ ├── Alarm05.wav
│ │ ├── Alarm06.wav
│ │ ├── Alarm07.wav
│ │ ├── Alarm08.wav
│ │ ├── Alarm09.wav
│ │ ├── Alarm10.wav
│ │ ├── Default.wav
│ │ ├── Email.wav
│ │ ├── IM.wav
│ │ ├── Reminder.wav
│ │ ├── Ring01.wav
│ │ ├── Ring02.wav
│ │ ├── Ring03.wav
│ │ ├── Ring04.wav
│ │ ├── Ring05.wav
│ │ ├── Ring06.wav
│ │ ├── Ring07.wav
│ │ ├── Ring08.wav
│ │ ├── Ring09.wav
│ │ └── Ring10.wav
│ ├── css
│ │ └── styles.css
│ ├── desktop.ini
│ ├── example_full_features.png
│ ├── example_full_features_action.png
│ ├── example_full_features_attribution.png
│ ├── in_action_multiline_image.png
│ ├── in_action_one_line.png
│ ├── tutorials_callbacks_final.gif
│ ├── tutorials_first_steps.png
│ ├── tutorials_first_steps_troubleshooting.gif
│ ├── tutorials_template_actions.png
│ ├── tutorials_template_image.png
│ └── tutorials_template_three_lines.png
│ ├── committing.rst
│ ├── conf.py
│ ├── content.rst
│ ├── documentation.rst
│ ├── in_action.rst
│ ├── index.rst
│ └── tutorials
│ ├── callbacks.rst
│ ├── index.rst
│ ├── installation.rst
│ └── template.rst
├── generate_stubs.py
├── module
├── event_handler.cpp
├── event_handler.h
├── init.cpp
├── init.h
├── module.sln
├── module
│ ├── module.vcxproj
│ ├── module.vcxproj.filters
│ └── module.vcxproj.user
├── py_init.cpp
├── py_init.h
├── py_module.cpp
├── py_module.h
├── py_template.cpp
├── py_template.h
├── py_utils.cpp
├── py_utils.h
├── utils.cpp
├── utils.h
├── wintoastlib.cpp
└── wintoastlib.h
├── setup.py
├── tests
├── files
│ ├── Readme.txt
│ └── image.png
├── test_actions.py
├── test_callbacks.py
├── test_hide.py
├── test_init.py
├── test_show.py
└── test_template.py
└── zroya
├── __init__.py
├── dismiss_reason.py
├── template_enums.py
├── version.py
└── zroya.pyi
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | *.egg-info/
24 | .installed.cfg
25 | *.egg
26 | .vs
27 |
28 | # PyInstaller
29 | # Usually these files are written by a python script from a template
30 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
31 | *.manifest
32 | *.spec
33 |
34 | # Installer logs
35 | pip-log.txt
36 | pip-delete-this-directory.txt
37 |
38 | # Unit test / coverage reports
39 | htmlcov/
40 | .tox/
41 | .coverage
42 | .coverage.*
43 | .cache
44 | nosetests.xml
45 | coverage.xml
46 | *.cover
47 | .hypothesis/
48 |
49 | # Translations
50 | *.mo
51 | *.pot
52 |
53 | # Django stuff:
54 | *.log
55 | local_settings.py
56 |
57 | # Flask stuff:
58 | instance/
59 | .webassets-cache
60 |
61 | # Scrapy stuff:
62 | .scrapy
63 |
64 | # Sphinx documentation
65 | docs/_build/
66 |
67 | # PyBuilder
68 | target/
69 |
70 | # Jupyter Notebook
71 | .ipynb_checkpoints
72 |
73 | # pyenv
74 | .python-version
75 |
76 | # celery beat schedule file
77 | celerybeat-schedule
78 |
79 | # SageMath parsed files
80 | *.sage.py
81 |
82 | # Environments
83 | .env
84 | .venv
85 | env/
86 | venv/
87 | ENV/
88 |
89 | # Spyder project settings
90 | .spyderproject
91 | .spyproject
92 |
93 | # Rope project settings
94 | .ropeproject
95 |
96 | # mkdocs documentation
97 | /site
98 |
99 | # mypy
100 | .mypy_cache/
101 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/zroya.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Jan Malčák
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include generate_stubs.py
2 | include README.md
3 | include ./module/*.h
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://opensource.org/licenses/MIT)
2 | [](https://pypi.python.org/pypi/zroya/)
3 | [](https://pypi.python.org/pypi/zroya/)
4 | [](https://gitHub.com/malja/zroya/graphs/commit-activity)
5 |
6 | # zroya2
7 | Zroya is a Python package for creating native Windows notifications.
8 |
9 | In contrast to first version of zroya, zroya2 is a Python extension built around C++
10 | [WinToast](https://github.com/mohabouje/WinToast) library.
11 |
12 | **Note**: Zroya2 is in beta testing. I would be grateful for any bug reports.
13 |
14 | ## Prerequisites
15 |
16 | There are no requirements at the moment.
17 |
18 | ## Installation
19 |
20 | Zroya2 is now available from pypi:
21 |
22 | ```
23 | python -m pip install zroya
24 | ```
25 |
26 | ## Example
27 |
28 | ```python
29 |
30 | import zroya
31 |
32 | # Initialize zroya module. Make sure to call this function.
33 | # All parameters are required
34 | zroya.init("YourAppName", "CompanyName", "ProductName", "SubProduct", "Version")
35 |
36 | # Create notification template. TYPE_TEXT1 means one bold line withou image.
37 | template = zroya.Template( zroya.TemplateType.Text1 )
38 | # Set first line
39 | template.setFirstLine("My First line")
40 |
41 | # Save notification id for later use
42 | notificationID = zroya.show(template)
43 |
44 | # .. do something, maybe sleep?
45 |
46 | # Hide notification
47 | zroya.hide(notificationID)
48 | ```
49 |
50 | ## Documentation
51 |
52 | You may find some limited documentation on [Zroya Page](https://malja.github.io/zroya)
53 |
--------------------------------------------------------------------------------
/TODO:
--------------------------------------------------------------------------------
1 | Required before release:
2 | ========================
3 |
4 | - Write documentation for C part of the project
5 | - Add more tests
6 | - Add Template __init__ method to zroya.pyi
7 |
8 | Future goals:
9 | ==============
10 |
11 | - Make sure it is not required to call init function
12 | - Add support for future WinToast features
13 | - Commit changes in WinToast library back to its github project
14 | - Add removeAction, getAction methods to WinToastLib
--------------------------------------------------------------------------------
/changelog:
--------------------------------------------------------------------------------
1 | 0.1.0
2 | -----
3 |
4 | - Basic functionality
5 |
6 | 0.1.1
7 | -----
8 |
9 | - Sound is now mutable
10 | - Better documentation
11 |
12 | 0.1.2
13 | -----
14 |
15 | - Notifications may be hidden from source
16 | - Timeouts - after certain time notification disappears
17 | - on_timeout now triggers after defined timeout expires and notification is removed
18 | - on_hide now triggers after notification is hidden from code
19 |
20 | 0.2.0
21 | -----
22 |
23 | - New C based module for python with native Windows notification support
24 | - Does not support events yet.
25 |
26 | 04.04.2018
27 | - Script generage_stubs.py is called automatically after build_ext command
28 | - First version of Doxygen documentation
29 | - Changes in WinToastLib namespaces
30 |
31 | 11.04.2018
32 | - New Python class DismissReason
33 | - Working callbacks
34 | - Visual Studio project for C/C++ code
35 | - Use get/set methods instead of multipurpose methods in zroya.Template
36 |
37 | 19. 04. 2018
38 | - Everything seems to work properly
39 | - New documentation for python code available from https://malja.github.io/zroya
40 |
41 | 26. 04. 2018
42 | - Added In Action page to documentation
43 | - Added Committing to zroya page to documentation
44 | - Added version and release variables to zroya.py, which are used in sphinx config and setup.py
45 | - New upload, docs, test, stubs commands in setup.py
46 | - Some changes in stub generating.
47 | - Changed tests for zroya.Template.set*Line to handle TypeError instead ValueError
48 | - Changed tests for zroya.Template.get/setImage to work with absolute paths
49 | - Removed sphinx makefile, since make.bat is much better option which doesn't require make to be installed
50 | - Removed C documentation. It is not ready for production yet.
51 |
52 | 0.2.1
53 | -----
54 |
55 | - Tried to fix https://github.com/malja/zroya/issues/11
56 | - Removed /utf-8 parameter from setup.py
57 |
58 | 0.2.2
59 | -----
60 |
61 | - Tried to fix https://github.com/malja/zroya/issues/11
62 | - Changed setup.py to include all files under /zroya directory
63 |
--------------------------------------------------------------------------------
/docs/.buildinfo:
--------------------------------------------------------------------------------
1 | # Sphinx build info version 1
2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
3 | config: be625054012c59005cd92cdf8ec350c8
4 | tags: 645f666f9bcd5a90fca523b33c5a78b7
5 |
--------------------------------------------------------------------------------
/docs/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/.nojekyll
--------------------------------------------------------------------------------
/docs/_images/example_full_features_action.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_images/example_full_features_action.png
--------------------------------------------------------------------------------
/docs/_images/example_full_features_attribution.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_images/example_full_features_attribution.png
--------------------------------------------------------------------------------
/docs/_images/in_action_multiline_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_images/in_action_multiline_image.png
--------------------------------------------------------------------------------
/docs/_images/in_action_one_line.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_images/in_action_one_line.png
--------------------------------------------------------------------------------
/docs/_images/tutorials_callbacks_final.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_images/tutorials_callbacks_final.gif
--------------------------------------------------------------------------------
/docs/_images/tutorials_first_steps.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_images/tutorials_first_steps.png
--------------------------------------------------------------------------------
/docs/_images/tutorials_first_steps_troubleshooting.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_images/tutorials_first_steps_troubleshooting.gif
--------------------------------------------------------------------------------
/docs/_images/tutorials_template_actions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_images/tutorials_template_actions.png
--------------------------------------------------------------------------------
/docs/_images/tutorials_template_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_images/tutorials_template_image.png
--------------------------------------------------------------------------------
/docs/_images/tutorials_template_three_lines.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_images/tutorials_template_three_lines.png
--------------------------------------------------------------------------------
/docs/_sources/commiting.rst.txt:
--------------------------------------------------------------------------------
1 | Committing to zroya
2 | ===================
3 |
4 | Changes in C files
5 | ------------------
6 |
7 | 1) Build Python extension from C source
8 |
9 | > python setup.py build
10 |
11 | Make sure there are no errors.
12 |
13 | 2) Test it with existing tests
14 |
15 | > python setup.py test
16 |
17 | Make sure all tests passed
18 |
19 | 3) Write your own tests when necessary.
20 |
21 | 4) Change documentation. See Changes in Documentation
22 |
23 | 5) Make stubs
24 |
25 | > python setup.py stubs
26 |
27 | Changes in Python files
28 | -----------------------
29 |
30 | 1) Test your changes with existing tests
31 |
32 | > python setup.py test
33 |
34 | 2) Write your own tests when necessary.
35 |
36 | 3) Change documentation. See Changes in Documentation
37 |
38 | 4) Make stubs
39 |
40 | > python setup.py stubs
41 |
42 | Changes in documentation
43 | ------------------------
44 |
45 | 1) Build html documentation
46 |
47 | > python setup.py docs
48 |
--------------------------------------------------------------------------------
/docs/_sources/committing.rst.txt:
--------------------------------------------------------------------------------
1 | Committing to zroya
2 | ===================
3 |
4 | This page is work in progress.
5 |
6 | Changes in C files
7 | ------------------
8 |
9 | 1. Build Python extension from C source.
10 |
11 | .. code-block:: bash
12 |
13 | python setup.py build
14 |
15 | Make sure there are no errors.
16 |
17 | 2. Run current tests.
18 |
19 | .. code-block:: bash
20 |
21 | python setup.py test
22 |
23 | 3. Write your own tests when necessary.
24 |
25 | 4. Change documentation. See :ref:`changes_in_documentation` section.
26 |
27 | 5. Make stubs
28 |
29 | .. code-block:: bash
30 |
31 | python setup.py stubs
32 |
33 | Changes in Python files
34 | -----------------------
35 |
36 | 1. Test your changes with existing tests
37 |
38 | .. code-block:: bash
39 |
40 | python setup.py test
41 |
42 | 2. Write your own tests when necessary.
43 |
44 | 3. Change documentation. See :ref:`changes_in_documentation` section.
45 |
46 | 4. Make stubs
47 |
48 | .. code-block:: bash
49 |
50 | python setup.py stubs
51 |
52 | .. _changes_in_documentation:
53 |
54 | Changes in documentation
55 | ------------------------
56 |
57 | 1. Build html documentation.
58 |
59 | .. code-block:: bash
60 |
61 | python setup.py docs
62 |
--------------------------------------------------------------------------------
/docs/_sources/content.rst.txt:
--------------------------------------------------------------------------------
1 | Tutorial
2 | ========
3 |
4 | .. toctree::
5 | :maxdepth: 2
6 |
7 | in_action
8 | tutorials/installation
9 | tutorials/index
10 | tutorials/template
11 | tutorials/callbacks
12 | documentation
13 | committing
14 |
--------------------------------------------------------------------------------
/docs/_sources/documentation.rst.txt:
--------------------------------------------------------------------------------
1 | API Documentation
2 | =================
3 |
4 | Functions
5 | ---------
6 | .. automodule:: zroya
7 | :members: init, show, hide
8 |
9 | Template
10 | --------
11 |
12 | .. autoclass:: zroya.Template
13 | :members:
14 |
15 | TemplateType
16 | ^^^^^^^^^^^^
17 |
18 | .. autoclass:: zroya.TemplateType
19 | :members:
20 |
21 | Audio
22 | -----
23 |
24 | .. autoclass:: zroya.Audio
25 | :members:
26 |
27 | AudioMode
28 | ^^^^^^^^^
29 |
30 | .. autoclass:: zroya.AudioMode
31 | :members:
32 |
33 | DismissReason
34 | -------------
35 |
36 | .. autoclass:: zroya.DismissReason
37 | :members:
38 |
--------------------------------------------------------------------------------
/docs/_sources/in_action.rst.txt:
--------------------------------------------------------------------------------
1 | In Action
2 | =========
3 |
4 | This page contains code snippets with summary of zroya's abilities. See :doc:`tutorials/index` for more detailed
5 | introduction.
6 |
7 | Simple Notification
8 | -------------------
9 |
10 | .. code-block:: python
11 |
12 | import zroya
13 |
14 | zroya.init("Python", "a", "b", "c", "d")
15 | t = zroya.Template(zroya.TemplateType.Text1)
16 | t.setFirstLine("Just one bold line")
17 | zroya.show(t)
18 |
19 | .. figure:: _static/in_action_one_line.png
20 | :alt: Notification with one bold line
21 |
22 | Multiline Notification With Image
23 | ---------------------------------
24 |
25 | .. code-block:: python
26 |
27 | import zroya
28 |
29 | zroya.init("Python", "a", "b", "c", "d")
30 | t = zroya.Template(zroya.TemplateType.ImageAndText4)
31 | t.setFirstLine("First bold line")
32 | t.setSecondLine("Second line is in regular font")
33 | t.setImage("./files/image.png")
34 | zroya.show(t)
35 |
36 | .. figure:: _static/in_action_multiline_image.png
37 | :alt: Notification with one bold, one regular line and an image.
38 |
39 | Attaching callbacks
40 | -------------------
41 |
42 | .. code-block:: python
43 |
44 | import zroya
45 | import time
46 |
47 | def onClickHandler(notification_id):
48 | print("Clicked!")
49 |
50 | zroya.init("Python", "a", "b", "c", "d")
51 | t = zroya.Template(zroya.TemplateType.Text1)
52 | t.setFirstLine("Click on me, please!")
53 | zroya.show(t, on_click=onClickHandler)
54 | time.sleep(10)
55 |
--------------------------------------------------------------------------------
/docs/_sources/index.rst.txt:
--------------------------------------------------------------------------------
1 | Welcome to Zroya's documentation!
2 | =================================
3 |
4 | Zroya is a Python extension which allows you to create native Windows notifications.
5 |
6 | Installation
7 | ------------
8 |
9 | Zroya is available from pypi:
10 |
11 | .. code-block:: Bash
12 |
13 | python pip install zroya
14 |
15 | Requirements
16 | ------------
17 |
18 | There are no requirements for zroya at the moment.
19 |
20 | What next?
21 | ----------
22 |
23 | Are you interested? Visit :doc:`in_action` and decide, if it is the right package for you. If so, I recommend you to
24 | take a look at :doc:`tutorials/index`.
25 |
26 | .. include:: content.rst
27 |
28 |
--------------------------------------------------------------------------------
/docs/_sources/tutorials/callbacks.rst.txt:
--------------------------------------------------------------------------------
1 | Callbacks
2 | =========
3 |
4 | In the previous part of the tutorial, action buttons were added. But they did nothing. In this tutorial,
5 | I'll teach you how to make them alive.
6 |
7 | But first I have to introduce you into zroya's callback system. Zroya registers four different events:
8 |
9 | * **onClick** - Fired every time user clicks on notification.
10 | * **onAction** - Activated when action button is clicked.
11 | * **onDismiss** - When the notification is dismissed by user or automatically.
12 | * **onFail** - Something went wrong.
13 |
14 | If you want to be informed, when any of them happens, register event handler with **on_** parameters of
15 | :py:func:`zroya.show`. Event handler is nothing more than a regular function taking one, or two parameters. Number of
16 | parameters depends on the event you register for.
17 |
18 | On Click
19 | ---------
20 |
21 | On click handler takes one parameter and it is notification ID. This is the number you get as a return value from
22 | :py:func:`zroya.show`.
23 |
24 | .. code-block:: python
25 |
26 | def onClickHandler(notification_id):
27 | pass
28 |
29 | On Action
30 | ---------
31 |
32 | On Action handler takes two parameters, notification ID and action ID. Action ID is number returned by
33 | :py:meth:`zroya.Template.addAction`.
34 |
35 | .. code-block:: python
36 |
37 | def onActionHandler(notification_id, action_id):
38 | pass
39 |
40 | On Dismiss
41 | ----------
42 |
43 | On Dismiss handler is function with two parameters. First one is notification ID. The second one is
44 | :py:class:`zroya.DismissReason`.
45 |
46 | .. code-block:: python
47 |
48 | def onDismissHandler(notification_id, reason):
49 | pass
50 |
51 | On Fail
52 | -------
53 |
54 | Last, on fail handler is function with one parameter, the same as on click callback. The parameter is notification ID
55 | returned from :py:func:`zroya.show`.
56 |
57 | .. code-block:: python
58 |
59 | def onFailHandler(notification_id):
60 | pass
61 |
62 | Adding handlers
63 | ---------------
64 |
65 | Let's go back a bit. In :doc:`template`, we created a notification for simple bot asking user "How are you?". Now
66 | we add response to each of the action button.
67 |
68 | .. code-block:: python
69 |
70 | import zroya
71 | import time
72 |
73 | # Initialization is required. But in real usage, check the return code, please.
74 | zroya.init("python", "a", "b", "c", "d")
75 |
76 | # Template for question
77 | ask_template = zroya.Template(zroya.TemplateType.ImageAndText4)
78 | ask_template.setFirstLine("Hi, I am NotifyBot.")
79 | ask_template.setSecondLine("It is nice to meet you.")
80 | ask_template.setThirdLine("How are you?")
81 | ask_template.setImage("./files/image.png")
82 | ask_template.addAction("I'm OK, I guess")
83 | ask_template.addAction("Fine")
84 |
85 | # Response for Fine
86 | fine_template = zroya.Template(zroya.TemplateType.Text1)
87 | fine_template.setFirstLine("Glad to hear that!")
88 |
89 | # Response for OK
90 | ok_template = zroya.Template(zroya.TemplateType.Text1)
91 | ok_template.setFirstLine("I'm sorry to hear that!")
92 |
93 |
94 | # prepare handler
95 | def onAction(nid, action_id):
96 | global fine_template, ok_template
97 |
98 | if action_id == 0:
99 | zroya.show(ok_template)
100 | else:
101 | zroya.show(fine_template)
102 |
103 | # Show question
104 | zroya.show(ask_template, on_action=onAction)
105 |
106 | # Keep application running, unless onAction handler is never executed.
107 | time.sleep(10)
108 |
109 | Adding images to answers with emoticons, changing sounds etc. would take this to whole new level. You can always play
110 | with it as you wish.
111 |
112 | I owe you one more answer. How did I know that "I'm OK", gets action ID 0 and "Fine" is ID 1? See
113 | :py:meth:`zroya.Template.addAction` ;) Now enjoy the result:
114 |
115 | .. figure:: ../_static/tutorials_callbacks_final.gif
116 | :alt: Process of asking "How are you" followed with the response on me clicking on "I'm fine".
117 |
118 | Pretty impressive, isn't it?
119 |
--------------------------------------------------------------------------------
/docs/_sources/tutorials/index.rst.txt:
--------------------------------------------------------------------------------
1 | First steps
2 | ===========
3 |
4 | This tutorial focus only on the basics. It will walk you through setting zroya up, creating template, adding attributes
5 | to it and finally showing a notification.
6 |
7 | Before you follow this tutorial, make sure zroya is installed. See :doc:`installation`.
8 |
9 | .. code-block:: python
10 |
11 | import zroya
12 |
13 | First thing you have to do each time you want to use zroya is to initialize it. This is
14 | required for Windows to associate Python application with notifications.
15 |
16 | .. code-block:: python
17 |
18 | import zroya
19 |
20 | status = zroya.init(
21 | app_name="NotifyBot",
22 | company_name="MyBotCorp",
23 | product_name="NoBo",
24 | sub_product="core",
25 | version="v01"
26 | )
27 |
28 | if not status:
29 | print("Initialization failed")
30 |
31 | Note that all parameters of :py:func:`zroya.init` are required and they have to be strings. As you see,
32 | :py:func:`zroya.init` returns a boolean status. Always make sure that initialization did not fail.
33 |
34 | Notification templates
35 | ----------------------
36 |
37 | Now you are ready to create a notification. Each one is based on a :py:class:`zroya.Template`. It holds
38 | all information about the notification - text, image, sounds, etc.
39 |
40 | There are some predefined template types. Think of them as a form you fill blank fields into. The simplest type is
41 | :py:attr:`zroya.TemplateType.Text1`, which have only one field - first line. Filling anything more will result in
42 | errors.
43 |
44 | All types are defined in :py:class:`zroya.TemplateType` class. Select one of them and we will use it to create a
45 | template.
46 |
47 | .. code-block:: python
48 |
49 | # zroya is imported and initialized at this moment
50 | template = zroya.Template(zroya.TemplateType.Text1)
51 |
52 | As you can see, you pass selected template type as a parameter to constructor of :py:class:`zroya.Template`.
53 |
54 | Set it's text
55 | -------------
56 |
57 | We did create a template. But it does not hold anything. Say you want to show "Hi, how are you?" in it. Following code
58 | will do so:
59 |
60 | .. code-block:: python
61 |
62 | # template is an instance of zroya.Template
63 | template.setFirstLine("Hi, how are you?")
64 |
65 | Show it to the world
66 | --------------------
67 |
68 | We got there, finally. It is time to show the notification. Use :py:func:`zroya.show` function and pass it **template**
69 | as first parameter:
70 |
71 | .. code-block:: python
72 |
73 | # template is an instance of zroya.Template
74 | zroya.show(template)
75 |
76 | :py:func:`zroya.show` has more parameters, but they don't have to bother you at the moment. We will focus on them in
77 | following steps of this tutorial.
78 |
79 | If everything went right, you should register a notification showing up at the right down corner of your screen.
80 |
81 | .. figure:: ../_static/tutorials_first_steps.png
82 | :alt: Image of notification saying "Hi, how are you?"
83 |
84 | Result of our hard work :)
85 |
86 | Troubleshooting
87 | ---------------
88 |
89 | **Calling** :py:func:`zroya.init` **failed**: This shouldn't happen. Please make sure to `report it`_. It helps me a lot
90 | with debugging and serving you the best product.
91 |
92 | **There is no notification!**: Make sure it is allowed for python (or for any app you are using zroya in) to create
93 | notifications.
94 |
95 | Head to *Settings* **=>** *System* **=>** *Notifications and Actions*. Scroll down and find Python. Set Notifications to
96 | On.
97 |
98 | .. figure:: ../_static/tutorials_first_steps_troubleshooting.gif
99 | :alt: Video showing how to enable notifications for python.
100 |
101 | How to enable notifications.
102 |
103 | .. _report it: https://github.com/malja/zroya/issues/new
--------------------------------------------------------------------------------
/docs/_sources/tutorials/installation.rst.txt:
--------------------------------------------------------------------------------
1 | Instalation
2 | ===========
3 |
4 | Installing zroya is pretty straight forward. Just use pypi:
5 |
6 | .. code-block:: bash
7 |
8 | python -m pip install zroya
9 |
10 | Installing from source code
11 | ---------------------------
12 |
13 | For building zroya from source code, Visual C++ Libraries have to be installed in the first place.
14 |
15 | Then clone latest version of zroya:
16 |
17 | .. code-block:: bash
18 |
19 | git clone https://github.com/malja/zroya.git
20 |
21 | And build it with distutils:
22 |
23 | .. code-block:: bash
24 |
25 | python setup.py build
--------------------------------------------------------------------------------
/docs/_sources/tutorials/template.rst.txt:
--------------------------------------------------------------------------------
1 | Further on templates
2 | ====================
3 |
4 | In previous tutorial, we managed to create a notification from template. In this part, we will make the most from
5 | templates.
6 |
7 | Multiple lines
8 | --------------
9 |
10 | As I said in previous tutorial, not each :py:class:`zroya.TemplateType` supports multiple lines of text. So make
11 | sure you pick the right one - for example :py:attr:`zroya.TemplateType.ImageAndText4`. You may set up to three lines of
12 | text to it.
13 |
14 | .. code-block:: python
15 |
16 | # zroya is imported and initialized
17 | template = zroya.Template(zroya.TemplateType.ImageAndText4)
18 | template.setFirstLine("Hi, I am NotifyBot.")
19 | template.setSecondLine("It is nice to meet you.")
20 | template.setThirdLine("How are you?")
21 |
22 | zroya.show(template)
23 |
24 | At the moment, zroya supports up to three lines - each one is set by it's own function -
25 | :py:meth:`zroya.Template.setFirstLine`, :py:meth:`zroya.Template.setSecondLine` and
26 | :py:meth:`zroya.Template.setThirdLine`.
27 |
28 | .. figure:: ../_static/tutorials_template_three_lines.png
29 | :alt: Image with a notification which contains three lines of text. First line is bold.
30 |
31 | Notification with three lines of text
32 |
33 | Getting the text back
34 | ---------------------
35 |
36 | Except functions for setting text, there are functions for getting it back from template. They are named
37 | :py:meth:`zroya.Template.getFirstLine`, :py:meth:`zroya.Template.getSecondLine` and
38 | :py:meth:`zroya.Template.getThirdLine` respectively.
39 |
40 | We will use template from previous example to get second line back:
41 |
42 | .. code-block:: python
43 |
44 | print(template.getSecondLine())
45 | #> "It is nice to meet you."
46 |
47 | If there is no such text, empty string is returned.
48 |
49 | Change sound
50 | ------------
51 |
52 | It is all nice and so, but the sound Windows does when notification is created is sooo boring, right? Let's change it.
53 |
54 | .. code-block:: python
55 |
56 | template.setAudio(zroya.Audio.Call4)
57 |
58 | Sadly, there is no way to play just any sound you want. You can choose from plenty of sounds defined in
59 | :py:class:`zroya.Audio` class. On the other hand, they are available at any Windows station.
60 |
61 | If this is not enough, you can play selected sound in loop until the notification is moved to Action Center,
62 | or until user dismiss it.
63 |
64 | .. code-block:: python
65 |
66 | template.setAudio(zroya.Audio.Call4, zroya.AudioMode.Looping)
67 |
68 | But I wouldn't recommend it. On the other hand, muting notifications may be usable a bit more:
69 |
70 | .. code-block:: python
71 |
72 | template.setAudio(mode=zroya.AudioMode.Silence)
73 |
74 | Expiration time
75 | ---------------
76 |
77 | Notifications will stay in Action Center until you shut the application off or you manually remove them from there.
78 | But some notifications should have shorter lifespan - for example weather reports. There is no use of the old ones.
79 | Beside hiding them from code, :py:meth:`zroya.Template.setExpiration` comes to aid.
80 |
81 | .. code-block:: python
82 |
83 | template.setExpiration(1000)
84 |
85 | It takes a number of milliseconds after which the notification is automatically removed from Action Center.
86 |
87 | Images
88 | ------
89 |
90 | UI is key to user's heart. Let's make bot more friendly. Add image with :py:meth:`zroya.Template.setImage`.
91 |
92 | .. code-block:: python
93 |
94 | template.setImage("./image.png")
95 |
96 | .. figure:: ../_static/tutorials_template_image.png
97 | :alt: Notification with friendly image of bot.
98 |
99 | Isn't he cute :*
100 |
101 | At this point, we make use of that :py:attr:`zroya.TemplateType.ImageAndText4` template type. For example
102 | with :py:attr:`zroya.TemplateType.Text4`, this function would return False every time, because it does not support
103 | this type.
104 |
105 | Actions
106 | -------
107 |
108 | One pretty cool feature is adding actions. Those are buttons which can have attached some action to them. When user
109 | click them, event is fired. See :doc:`callbacks`.
110 |
111 | In this example, we add two buttons to respond question notification is asking. What a wonderful time, answering
112 | your own questions :).
113 |
114 | .. code-block:: python
115 |
116 | template.addAction("I'm OK, I guess")
117 | template.addAction("Fine")
118 |
119 | .. figure:: ../_static/tutorials_template_actions.png
120 | :alt: Notification with buttons for answering the question
121 |
122 | Answer the question, please.
123 |
124 | As you probably noticed, they don't do much now. Just dismiss it. We will do something about it in the next tutorial.
125 |
126 | Troubleshooting
127 | ---------------
128 |
129 | **Actions fail to be added**: Actions are one of Windows 8.1+ features. If you have older system, they won't work.
--------------------------------------------------------------------------------
/docs/_static/ajax-loader.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/ajax-loader.gif
--------------------------------------------------------------------------------
/docs/_static/audio.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
23 |
24 |
25 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/docs/_static/audio/Alarm01.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/audio/Alarm01.wav
--------------------------------------------------------------------------------
/docs/_static/audio/Alarm02.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/audio/Alarm02.wav
--------------------------------------------------------------------------------
/docs/_static/audio/Alarm03.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/audio/Alarm03.wav
--------------------------------------------------------------------------------
/docs/_static/audio/Alarm04.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/audio/Alarm04.wav
--------------------------------------------------------------------------------
/docs/_static/audio/Alarm05.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/audio/Alarm05.wav
--------------------------------------------------------------------------------
/docs/_static/audio/Alarm06.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/audio/Alarm06.wav
--------------------------------------------------------------------------------
/docs/_static/audio/Alarm07.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/audio/Alarm07.wav
--------------------------------------------------------------------------------
/docs/_static/audio/Alarm08.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/audio/Alarm08.wav
--------------------------------------------------------------------------------
/docs/_static/audio/Alarm09.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/audio/Alarm09.wav
--------------------------------------------------------------------------------
/docs/_static/audio/Alarm10.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/audio/Alarm10.wav
--------------------------------------------------------------------------------
/docs/_static/audio/Default.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/audio/Default.wav
--------------------------------------------------------------------------------
/docs/_static/audio/Email.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/audio/Email.wav
--------------------------------------------------------------------------------
/docs/_static/audio/IM.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/audio/IM.wav
--------------------------------------------------------------------------------
/docs/_static/audio/Reminder.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/audio/Reminder.wav
--------------------------------------------------------------------------------
/docs/_static/audio/Ring01.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/audio/Ring01.wav
--------------------------------------------------------------------------------
/docs/_static/audio/Ring02.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/audio/Ring02.wav
--------------------------------------------------------------------------------
/docs/_static/audio/Ring03.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/audio/Ring03.wav
--------------------------------------------------------------------------------
/docs/_static/audio/Ring04.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/audio/Ring04.wav
--------------------------------------------------------------------------------
/docs/_static/audio/Ring05.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/audio/Ring05.wav
--------------------------------------------------------------------------------
/docs/_static/audio/Ring06.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/audio/Ring06.wav
--------------------------------------------------------------------------------
/docs/_static/audio/Ring07.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/audio/Ring07.wav
--------------------------------------------------------------------------------
/docs/_static/audio/Ring08.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/audio/Ring08.wav
--------------------------------------------------------------------------------
/docs/_static/audio/Ring09.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/audio/Ring09.wav
--------------------------------------------------------------------------------
/docs/_static/audio/Ring10.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/audio/Ring10.wav
--------------------------------------------------------------------------------
/docs/_static/comment-bright.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/comment-bright.png
--------------------------------------------------------------------------------
/docs/_static/comment-close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/comment-close.png
--------------------------------------------------------------------------------
/docs/_static/comment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/comment.png
--------------------------------------------------------------------------------
/docs/_static/css/styles.css:
--------------------------------------------------------------------------------
1 | iframe {
2 | border: none;
3 | height: 60px;
4 | }
--------------------------------------------------------------------------------
/docs/_static/custom.css:
--------------------------------------------------------------------------------
1 | /* This file intentionally left blank. */
2 |
--------------------------------------------------------------------------------
/docs/_static/desktop.ini:
--------------------------------------------------------------------------------
1 | [LocalizedFileNames]
2 | Windows Default.wav=@%windir%\system32\mmres.dll,-715
3 |
--------------------------------------------------------------------------------
/docs/_static/documentation_options.js:
--------------------------------------------------------------------------------
1 | var DOCUMENTATION_OPTIONS = {
2 | URL_ROOT: '',
3 | VERSION: '0.2.2',
4 | LANGUAGE: 'None',
5 | COLLAPSE_INDEX: false,
6 | FILE_SUFFIX: '.html',
7 | HAS_SOURCE: true,
8 | SOURCELINK_SUFFIX: '.txt'
9 | };
--------------------------------------------------------------------------------
/docs/_static/down-pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/down-pressed.png
--------------------------------------------------------------------------------
/docs/_static/down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/down.png
--------------------------------------------------------------------------------
/docs/_static/example_full_features.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/example_full_features.png
--------------------------------------------------------------------------------
/docs/_static/example_full_features_action.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/example_full_features_action.png
--------------------------------------------------------------------------------
/docs/_static/example_full_features_attribution.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/example_full_features_attribution.png
--------------------------------------------------------------------------------
/docs/_static/file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/file.png
--------------------------------------------------------------------------------
/docs/_static/in_action_multiline_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/in_action_multiline_image.png
--------------------------------------------------------------------------------
/docs/_static/in_action_one_line.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/in_action_one_line.png
--------------------------------------------------------------------------------
/docs/_static/minus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/minus.png
--------------------------------------------------------------------------------
/docs/_static/plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/plus.png
--------------------------------------------------------------------------------
/docs/_static/pygments.css:
--------------------------------------------------------------------------------
1 | .highlight .hll { background-color: #ffffcc }
2 | .highlight { background: #eeffcc; }
3 | .highlight .c { color: #408090; font-style: italic } /* Comment */
4 | .highlight .err { border: 1px solid #FF0000 } /* Error */
5 | .highlight .k { color: #007020; font-weight: bold } /* Keyword */
6 | .highlight .o { color: #666666 } /* Operator */
7 | .highlight .ch { color: #408090; font-style: italic } /* Comment.Hashbang */
8 | .highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */
9 | .highlight .cp { color: #007020 } /* Comment.Preproc */
10 | .highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */
11 | .highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */
12 | .highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
13 | .highlight .gd { color: #A00000 } /* Generic.Deleted */
14 | .highlight .ge { font-style: italic } /* Generic.Emph */
15 | .highlight .gr { color: #FF0000 } /* Generic.Error */
16 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
17 | .highlight .gi { color: #00A000 } /* Generic.Inserted */
18 | .highlight .go { color: #333333 } /* Generic.Output */
19 | .highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
20 | .highlight .gs { font-weight: bold } /* Generic.Strong */
21 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
22 | .highlight .gt { color: #0044DD } /* Generic.Traceback */
23 | .highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
24 | .highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
25 | .highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
26 | .highlight .kp { color: #007020 } /* Keyword.Pseudo */
27 | .highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
28 | .highlight .kt { color: #902000 } /* Keyword.Type */
29 | .highlight .m { color: #208050 } /* Literal.Number */
30 | .highlight .s { color: #4070a0 } /* Literal.String */
31 | .highlight .na { color: #4070a0 } /* Name.Attribute */
32 | .highlight .nb { color: #007020 } /* Name.Builtin */
33 | .highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
34 | .highlight .no { color: #60add5 } /* Name.Constant */
35 | .highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */
36 | .highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */
37 | .highlight .ne { color: #007020 } /* Name.Exception */
38 | .highlight .nf { color: #06287e } /* Name.Function */
39 | .highlight .nl { color: #002070; font-weight: bold } /* Name.Label */
40 | .highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
41 | .highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */
42 | .highlight .nv { color: #bb60d5 } /* Name.Variable */
43 | .highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */
44 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */
45 | .highlight .mb { color: #208050 } /* Literal.Number.Bin */
46 | .highlight .mf { color: #208050 } /* Literal.Number.Float */
47 | .highlight .mh { color: #208050 } /* Literal.Number.Hex */
48 | .highlight .mi { color: #208050 } /* Literal.Number.Integer */
49 | .highlight .mo { color: #208050 } /* Literal.Number.Oct */
50 | .highlight .sa { color: #4070a0 } /* Literal.String.Affix */
51 | .highlight .sb { color: #4070a0 } /* Literal.String.Backtick */
52 | .highlight .sc { color: #4070a0 } /* Literal.String.Char */
53 | .highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */
54 | .highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
55 | .highlight .s2 { color: #4070a0 } /* Literal.String.Double */
56 | .highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
57 | .highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */
58 | .highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
59 | .highlight .sx { color: #c65d09 } /* Literal.String.Other */
60 | .highlight .sr { color: #235388 } /* Literal.String.Regex */
61 | .highlight .s1 { color: #4070a0 } /* Literal.String.Single */
62 | .highlight .ss { color: #517918 } /* Literal.String.Symbol */
63 | .highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
64 | .highlight .fm { color: #06287e } /* Name.Function.Magic */
65 | .highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
66 | .highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
67 | .highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
68 | .highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */
69 | .highlight .il { color: #208050 } /* Literal.Number.Integer.Long */
--------------------------------------------------------------------------------
/docs/_static/tutorials_callbacks_final.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/tutorials_callbacks_final.gif
--------------------------------------------------------------------------------
/docs/_static/tutorials_first_steps.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/tutorials_first_steps.png
--------------------------------------------------------------------------------
/docs/_static/tutorials_first_steps_troubleshooting.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/tutorials_first_steps_troubleshooting.gif
--------------------------------------------------------------------------------
/docs/_static/tutorials_template_actions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/tutorials_template_actions.png
--------------------------------------------------------------------------------
/docs/_static/tutorials_template_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/tutorials_template_image.png
--------------------------------------------------------------------------------
/docs/_static/tutorials_template_three_lines.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/tutorials_template_three_lines.png
--------------------------------------------------------------------------------
/docs/_static/up-pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/up-pressed.png
--------------------------------------------------------------------------------
/docs/_static/up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/_static/up.png
--------------------------------------------------------------------------------
/docs/commiting.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 | Committing to zroya — Zroya 0.2 documentation
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
Committing to zroya
35 |
36 |
Changes in C files
37 |
38 | Build Python extension from C source
39 |
40 | > python setup.py build
41 |
Make sure there are no errors.
42 |
43 |
44 | Test it with existing tests
45 |
46 | > python setup.py test
47 |
Make sure all tests passed
48 |
49 |
50 | Write your own tests when necessary.
51 |
52 | Change documentation. See Changes in Documentation
53 |
54 | Make stubs
55 |
56 | > python setup.py stubs
57 |
58 |
59 |
60 |
61 |
62 |
Changes in Python files
63 |
64 | Test your changes with existing tests
65 |
66 | > python setup.py test
67 |
68 |
69 | Write your own tests when necessary.
70 |
71 | Change documentation. See Changes in Documentation
72 |
73 | Make stubs
74 |
75 | > python setup.py stubs
76 |
77 |
78 |
79 |
80 |
81 |
Changes in documentation
82 |
83 | Build html documentation
84 |
85 | > python setup.py docs
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
134 |
135 |
136 |
147 |
148 |
149 |
150 |
151 |
152 |
--------------------------------------------------------------------------------
/docs/committing.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 | Committing to zroya — Zroya 0.2.2 documentation
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
Committing to zroya
36 |
This page is work in progress.
37 |
38 |
Changes in C files
39 |
40 | Build Python extension from C source.
41 |
42 |
python setup.py build
43 |
44 |
45 |
Make sure there are no errors.
46 |
47 | Run current tests.
48 |
49 |
python setup.py test
50 |
51 |
52 |
53 | Write your own tests when necessary.
54 | Change documentation. See Changes in documentation section.
55 | Make stubs
56 |
57 |
python setup.py stubs
58 |
59 |
60 |
61 |
62 |
Changes in Python files
63 |
64 | Test your changes with existing tests
65 |
66 |
python setup.py test
67 |
68 |
69 |
70 | Write your own tests when necessary.
71 | Change documentation. See Changes in documentation section.
72 | Make stubs
73 |
74 |
python setup.py stubs
75 |
76 |
77 |
78 |
79 |
Changes in documentation
80 |
81 | Build html documentation.
82 |
83 |
python setup.py docs
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
139 |
140 |
141 |
152 |
153 |
154 |
155 |
156 |
157 |
--------------------------------------------------------------------------------
/docs/content.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 | Tutorial — Zroya 0.2.2 documentation
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
135 |
146 |
147 |
148 |
149 |
150 |
151 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 | Welcome to Zroya’s documentation! — Zroya 0.2.2 documentation
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
Welcome to Zroya’s documentation!
36 |
Zroya is a Python extension which allows you to create native Windows notifications.
37 |
38 |
Installation
39 |
Zroya is available from pypi:
40 |
python pip install zroya
41 |
42 |
43 |
44 |
45 |
Requirements
46 |
There are no requirements for zroya at the moment.
47 |
48 |
49 |
What next?
50 |
Are you interested? Visit In Action and decide, if it is the right package for you. If so, I recommend you to
51 | take a look at First steps .
52 |
53 |
54 |
109 |
110 |
111 |
112 |
113 |
114 |
155 |
156 |
157 |
168 |
169 |
170 |
171 |
172 |
173 |
--------------------------------------------------------------------------------
/docs/objects.inv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs/objects.inv
--------------------------------------------------------------------------------
/docs/py-modindex.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 | Python Module Index — Zroya 0.2.2 documentation
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
Python Module Index
42 |
43 |
46 |
47 |
48 |
49 |
50 | z
51 |
52 |
53 |
54 | zroya
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
95 |
96 |
97 |
105 |
106 |
107 |
108 |
109 |
110 |
--------------------------------------------------------------------------------
/docs/search.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 | Search — Zroya 0.2.2 documentation
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
Search
42 |
43 |
44 |
45 | Please activate JavaScript to enable the search
46 | functionality.
47 |
48 |
49 |
50 | From here you can search these documents. Enter your search
51 | words into the box below and click "search". Note that the search
52 | function will automatically search for all of the words. Pages
53 | containing fewer words won't appear in the result list.
54 |
55 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
89 |
90 |
91 |
99 |
100 |
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/docs/searchindex.js:
--------------------------------------------------------------------------------
1 | Search.setIndex({docnames:["committing","content","documentation","in_action","index","tutorials/callbacks","tutorials/index","tutorials/installation","tutorials/template"],envversion:53,filenames:["committing.rst","content.rst","documentation.rst","in_action.rst","index.rst","tutorials\\callbacks.rst","tutorials\\index.rst","tutorials\\installation.rst","tutorials\\template.rst"],objects:{"":{zroya:[2,0,0,"-"]},"zroya.Audio":{Alarm10:[2,2,1,""],Alarm2:[2,2,1,""],Alarm3:[2,2,1,""],Alarm4:[2,2,1,""],Alarm5:[2,2,1,""],Alarm6:[2,2,1,""],Alarm7:[2,2,1,""],Alarm8:[2,2,1,""],Alarm9:[2,2,1,""],Alarm:[2,2,1,""],Call10:[2,2,1,""],Call2:[2,2,1,""],Call3:[2,2,1,""],Call4:[2,2,1,""],Call5:[2,2,1,""],Call6:[2,2,1,""],Call7:[2,2,1,""],Call8:[2,2,1,""],Call9:[2,2,1,""],Call:[2,2,1,""],Default:[2,2,1,""],IM:[2,2,1,""],Mail:[2,2,1,""],Reminder:[2,2,1,""]},"zroya.AudioMode":{Default:[2,2,1,""],Loop:[2,2,1,""],Silence:[2,2,1,""]},"zroya.DismissReason":{App:[2,2,1,""],Expired:[2,2,1,""],User:[2,2,1,""]},"zroya.Template":{addAction:[2,3,1,""],getAttribution:[2,3,1,""],getAudio:[2,3,1,""],getAudioMode:[2,3,1,""],getExpiration:[2,3,1,""],getFirstLine:[2,3,1,""],getImage:[2,3,1,""],getSecondLine:[2,3,1,""],getThirdLine:[2,3,1,""],setAttribution:[2,3,1,""],setAudio:[2,3,1,""],setExpiration:[2,3,1,""],setFirstLine:[2,3,1,""],setImage:[2,3,1,""],setSecondLine:[2,3,1,""],setThirdLine:[2,3,1,""]},"zroya.TemplateType":{ImageAndText1:[2,2,1,""],ImageAndText2:[2,2,1,""],ImageAndText3:[2,2,1,""],ImageAndText4:[2,2,1,""],Text1:[2,2,1,""],Text2:[2,2,1,""],Text3:[2,2,1,""],Text4:[2,2,1,""]},zroya:{Audio:[2,1,1,""],AudioMode:[2,1,1,""],DismissReason:[2,1,1,""],Template:[2,1,1,""],TemplateType:[2,1,1,""],hide:[2,4,1,""],init:[2,4,1,""],show:[2,4,1,""]}},objnames:{"0":["py","module","Python module"],"1":["py","class","Python class"],"2":["py","attribute","Python attribute"],"3":["py","method","Python method"],"4":["py","function","Python function"]},objtypes:{"0":"py:module","1":"py:class","2":"py:attribute","3":"py:method","4":"py:function"},terms:{"boolean":6,"case":2,"class":[2,6,8],"default":2,"final":6,"function":[1,4,5,6,8],"import":[3,5,6,8],"int":2,"new":5,"return":[2,5,6,8],"true":2,Adding:[1,4],And:7,Are:4,But:[5,6,8],For:[7,8],One:[2,8],The:[2,5,6],Then:7,There:[4,6,8],Use:6,With:[1,4],abil:3,about:[6,8],accept:2,across:2,action:[1,2,4,6],action_id:5,activ:[2,5],add:[2,5,8],addact:[2,5,8],added:[5,8],adding:[6,8],after:8,aid:8,alarm10:2,alarm2:2,alarm3:2,alarm4:2,alarm5:2,alarm6:2,alarm7:2,alarm8:2,alarm9:2,alarm:2,aliv:5,all:[2,6,8],allow:[4,6],alwai:[5,6],ani:[2,5,6,8],annoi:[],answer:[5,8],anyth:6,api:[1,4],app:[2,6],app_nam:[2,6],applic:[2,5,6,8],arg:2,ask:[5,8],ask_templ:5,associ:6,attach:[1,4,8],attempt:2,attent:2,attribut:[2,6],audio:[1,4,8],audiomod:8,automat:[5,8],avail:[2,4,8],back:[1,2,4,5],base:[2,6],basic:6,becaus:8,befor:[2,6],being:2,besid:8,best:6,bit:[5,8],blank:6,bold:[2,3],bool:2,bore:8,bot:[5,8],bother:6,bright:[],build:[0,7],button:[2,5,8],call10:2,call2:2,call3:2,call4:[2,8],call5:2,call6:2,call7:2,call8:2,call9:2,call:[2,6],callabl:2,callback:[1,2,4,8],can:[2,5,6,8],caus:2,center:[2,8],chang:[1,4,5],check:5,choos:8,click:[1,2,3,4,8],clone:7,code:[1,3,4,5,6,8],com:7,come:8,commit:[1,4],company_nam:[2,6],compar:2,complet:2,configur:2,constructor:[2,6],contain:[2,3],cool:8,core:6,corner:6,correspond:2,count:2,creat:[2,4,5,6,8],current:[0,2],cute:8,debug:6,decid:4,def:[3,5],defin:[2,6,8],depend:5,descript:2,detail:3,did:[5,6],differ:[2,5],dismiss:[1,2,4,8],dismissreason:[1,4,5],distutil:7,doc:0,document:1,doe:[2,6,8],don:[6,8],down:6,due:2,each:[2,5,6,8],either:2,els:5,emoticon:5,empti:[2,8],enabl:6,enjoi:5,enough:8,enumer:2,error:[0,2,6],etc:[5,6],even:2,event:[2,5,8],everi:[5,8],everyth:6,exampl:[2,8],except:8,execut:5,exist:[0,2],expir:[1,2,4],explicit:2,explicitli:2,extens:[0,4],fail:[1,4,6,8],fals:[2,8],fart:[],featur:[2,8],field:6,file:[1,3,4,5],filenotfounderror:2,fill:6,find:6,fine:[5,8],fine_templ:5,fire:[2,5,8],first:[1,2,3,4,5,7],focu:6,follow:[2,6],font:3,form:6,forward:7,four:5,friendli:8,from:[0,1,2,4,5,8],further:[1,4,5],gener:2,get:[1,2,4,5],getattribut:2,getaudio:2,getaudiomod:2,getexpir:2,getfirstlin:[2,8],getimag:2,getsecondlin:[2,8],getthirdlin:[2,8],git:7,github:7,glad:5,global:5,got:[2,6],guess:[5,8],hand:[2,8],handler:[1,2,4],happen:[5,6],hard:6,has:[2,6],have:[5,6,7,8],head:6,hear:5,heart:8,help:6,hid:2,hidden:2,hide:[2,8],highlight:2,hold:[2,6],how:[2,5,6,8],html:0,http:7,imag:[1,2,4,5,6],imageandtext1:2,imageandtext2:2,imageandtext3:2,imageandtext4:[2,3,5,8],impress:5,index:2,inform:[5,6],init:[2,3,5,6],initi:[2,5,6,8],instal:[1,6],instanc:[2,6],interest:4,introduc:5,introduct:3,isn:[5,8],its:2,just:[3,7,8],keep:5,kei:8,know:5,label:2,larg:2,last:5,latest:7,leav:2,let:[5,8],level:5,librari:7,lifespan:8,line:[1,2,3,4,6],look:4,loop:[2,8],lot:6,mai:[2,8],mail:2,make:[0,5,6,8],malja:7,manag:8,manipul:2,manual:8,mean:2,meet:[5,8],method:2,millisecond:[2,8],mode:[2,8],modern:2,modul:2,moment:[4,6,8],more:[3,5,6,8],most:8,move:[2,8],much:8,multilin:[1,4],multipl:[1,4],mute:8,mybotcorp:6,name:[2,8],nativ:4,necessari:0,never:5,newer:2,next:8,nice:[5,8],nid:[2,5],nobo:6,note:[2,6],noth:5,notic:8,notif:[1,2,4,5,8],notification_id:[3,5],notifybot:[5,6,8],now:[5,6,8],number:[2,5,8],obtain:2,occur:2,off:8,ok_templ:5,old:8,older:8,on_:[2,5],on_act:[2,5],on_click:[2,3],on_dismiss:2,on_fail:2,onact:[2,5],onactionhandl:5,onc:2,onclick:[2,5],onclickhandl:[3,5],ondismiss:[2,5],ondismisshandl:5,one:[2,3,5,6,8],ones:8,onfail:[2,5],onfailhandl:5,onli:[2,6],other:[2,8],otherwis:2,our:6,owe:5,own:[0,2,8],packag:4,page:[0,3],paramet:[2,5,6],part:[2,5,8],pass:[2,5,6],path:2,pick:8,pip:[4,7],place:7,plai:[2,5,8],playback:2,pleas:[3,5,6,8],plenti:8,png:[3,5,8],point:8,posit:2,possibl:2,predefin:[2,6],prepar:5,pretti:[5,7,8],previou:[5,8],print:[2,3,6,8],probabl:8,product:6,product_nam:[2,6],progress:0,pypi:[4,7],python:[1,3,4,5,6,7],question:[5,8],rage:[],rais:2,randomli:2,readi:6,real:5,reason:[2,5],recommend:[4,8],record:[],regist:[2,5,6],regular:[2,3,5],remind:2,remov:[2,8],report:[6,8],repres:2,requir:[2,5,6],respect:8,respond:8,respons:5,result:[5,6],right:[4,6,8],run:[0,5],sadli:8,sai:6,said:8,same:5,screen:[2,6],scroll:6,second:[2,3,5,8],section:0,see:[0,2,3,5,6,8],select:[2,6,8],serv:6,set:[1,2,4,8],setattribut:2,setaudio:[2,8],setexpir:[2,8],setfirstlin:[2,3,5,6,8],setimag:[2,3,5,8],setsecondlin:[2,3,5,8],setthirdlin:[2,5,8],setup:[0,7],shorter:8,should:[2,6,8],shouldn:6,show:[1,2,3,4,5,8],shown:2,shut:8,side:[],silenc:[2,8],simpl:[1,4,5],simplest:6,singl:2,sleep:[3,5],snippet:3,some:[6,8],someth:[5,8],sooo:8,sorri:5,sound:[1,2,4,5,6],sourc:[0,1,4],stai:8,station:8,statu:6,step:[1,3,4],str:2,straight:7,string:[2,6,8],stub:0,sub_product:[2,6],success:2,summari:3,support:[2,8],sure:[0,6,8],system:[2,5,6,8],take:[4,5,8],teach:5,templat:[1,3,4,5],templatetyp:[3,5,6,8],test:0,text1:[2,3,5,6],text2:2,text3:2,text4:[2,8],text:[1,2,4],than:5,thei:[5,6,8],them:[5,6,8],thi:[0,2,3,5,6,8],thing:6,think:6,third:2,those:8,three:[2,8],through:[2,6],time:[1,2,3,4,5,6],toast:2,touch:2,trigger:2,troubleshoot:[1,4],tutori:[5,6,8],two:[2,5,8],type:[2,6,8],typeerror:2,uniqu:2,unless:5,unsupport:2,until:[2,8],usabl:8,usag:5,use:[6,7,8],used:2,user:[2,5,8],using:[2,6],v01:6,valid:2,valu:[2,5],vari:2,version:[2,6,7],visit:4,visual:7,wai:8,walk:6,want:[5,6,8],weather:8,went:[5,6],were:5,what:8,when:[0,2,5,8],which:[4,6,8],whole:5,window:[2,4,6,8],winsoundev:2,wish:5,won:8,wonder:8,work:[0,6,8],world:[1,4],would:[5,8],wouldn:8,wrap:2,write:0,wrong:5,yesterdai:[],you:[2,4,5,6,8],your:[0,6,8],zero:2,zroya:[1,2,3,5,6,7,8]},titles:["Committing to zroya","Tutorial","API Documentation","In Action","Welcome to Zroya\u2019s documentation!","Callbacks","First steps","Instalation","Further on templates"],titleterms:{"function":2,Adding:5,With:3,action:[3,5,8],api:2,attach:3,audio:2,audiomod:2,back:8,callback:[3,5],chang:[0,8],click:5,code:7,commit:0,dismiss:5,dismissreason:2,document:[0,2,4],expir:8,fail:5,file:0,first:6,from:7,further:8,get:8,handler:5,imag:[3,8],instal:[4,7],line:8,multilin:3,multipl:8,next:4,notif:[3,6],python:0,requir:4,set:6,show:6,simpl:3,sound:8,sourc:7,step:6,templat:[2,6,8],templatetyp:2,text:[6,8],time:8,troubleshoot:[6,8],tutori:[1,4],welcom:4,what:4,world:6,zroya:[0,4]}})
--------------------------------------------------------------------------------
/docs/tutorials/installation.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 | Instalation — Zroya 0.2.2 documentation
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
Instalation
37 |
Installing zroya is pretty straight forward. Just use pypi:
38 |
python -m pip install zroya
39 |
40 |
41 |
42 |
Installing from source code
43 |
For building zroya from source code, Visual C++ Libraries have to be installed in the first place.
44 |
Then clone latest version of zroya:
45 |
git clone https://github.com/malja/zroya.git
46 |
47 |
48 |
And build it with distutils:
49 |
python setup.py build
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
104 |
105 |
106 |
117 |
118 |
119 |
120 |
121 |
122 |
--------------------------------------------------------------------------------
/docs_source/sphinx/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=source
11 | set BUILDDIR=build
12 | set SPHINXPROJ=Zroya
13 |
14 | if "%1" == "" goto help
15 |
16 | %SPHINXBUILD% >NUL 2>NUL
17 | if errorlevel 9009 (
18 | echo.
19 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
20 | echo.installed, then set the SPHINXBUILD environment variable to point
21 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
22 | echo.may add the Sphinx directory to PATH.
23 | echo.
24 | echo.If you don't have Sphinx installed, grab it from
25 | echo.http://sphinx-doc.org/
26 | exit /b 1
27 | )
28 |
29 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
30 | goto end
31 |
32 | :help
33 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
34 |
35 | :end
36 | popd
37 |
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/audio.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
23 |
24 |
25 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/audio/Alarm01.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/audio/Alarm01.wav
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/audio/Alarm02.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/audio/Alarm02.wav
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/audio/Alarm03.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/audio/Alarm03.wav
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/audio/Alarm04.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/audio/Alarm04.wav
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/audio/Alarm05.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/audio/Alarm05.wav
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/audio/Alarm06.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/audio/Alarm06.wav
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/audio/Alarm07.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/audio/Alarm07.wav
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/audio/Alarm08.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/audio/Alarm08.wav
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/audio/Alarm09.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/audio/Alarm09.wav
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/audio/Alarm10.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/audio/Alarm10.wav
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/audio/Default.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/audio/Default.wav
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/audio/Email.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/audio/Email.wav
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/audio/IM.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/audio/IM.wav
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/audio/Reminder.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/audio/Reminder.wav
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/audio/Ring01.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/audio/Ring01.wav
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/audio/Ring02.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/audio/Ring02.wav
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/audio/Ring03.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/audio/Ring03.wav
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/audio/Ring04.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/audio/Ring04.wav
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/audio/Ring05.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/audio/Ring05.wav
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/audio/Ring06.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/audio/Ring06.wav
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/audio/Ring07.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/audio/Ring07.wav
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/audio/Ring08.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/audio/Ring08.wav
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/audio/Ring09.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/audio/Ring09.wav
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/audio/Ring10.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/audio/Ring10.wav
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/css/styles.css:
--------------------------------------------------------------------------------
1 | iframe {
2 | border: none;
3 | height: 60px;
4 | }
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/desktop.ini:
--------------------------------------------------------------------------------
1 | [LocalizedFileNames]
2 | Windows Default.wav=@%windir%\system32\mmres.dll,-715
3 |
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/example_full_features.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/example_full_features.png
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/example_full_features_action.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/example_full_features_action.png
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/example_full_features_attribution.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/example_full_features_attribution.png
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/in_action_multiline_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/in_action_multiline_image.png
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/in_action_one_line.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/in_action_one_line.png
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/tutorials_callbacks_final.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/tutorials_callbacks_final.gif
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/tutorials_first_steps.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/tutorials_first_steps.png
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/tutorials_first_steps_troubleshooting.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/tutorials_first_steps_troubleshooting.gif
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/tutorials_template_actions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/tutorials_template_actions.png
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/tutorials_template_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/tutorials_template_image.png
--------------------------------------------------------------------------------
/docs_source/sphinx/source/_static/tutorials_template_three_lines.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/docs_source/sphinx/source/_static/tutorials_template_three_lines.png
--------------------------------------------------------------------------------
/docs_source/sphinx/source/committing.rst:
--------------------------------------------------------------------------------
1 | Committing to zroya
2 | ===================
3 |
4 | This page is work in progress.
5 |
6 | Changes in C files
7 | ------------------
8 |
9 | 1. Build Python extension from C source.
10 |
11 | .. code-block:: bash
12 |
13 | python setup.py build
14 |
15 | Make sure there are no errors.
16 |
17 | 2. Run current tests.
18 |
19 | .. code-block:: bash
20 |
21 | python setup.py test
22 |
23 | 3. Write your own tests when necessary.
24 |
25 | 4. Change documentation. See :ref:`changes_in_documentation` section.
26 |
27 | 5. Make stubs
28 |
29 | .. code-block:: bash
30 |
31 | python setup.py stubs
32 |
33 | Changes in Python files
34 | -----------------------
35 |
36 | 1. Test your changes with existing tests
37 |
38 | .. code-block:: bash
39 |
40 | python setup.py test
41 |
42 | 2. Write your own tests when necessary.
43 |
44 | 3. Change documentation. See :ref:`changes_in_documentation` section.
45 |
46 | 4. Make stubs
47 |
48 | .. code-block:: bash
49 |
50 | python setup.py stubs
51 |
52 | .. _changes_in_documentation:
53 |
54 | Changes in documentation
55 | ------------------------
56 |
57 | 1. Build html documentation.
58 |
59 | .. code-block:: bash
60 |
61 | python setup.py docs
62 |
--------------------------------------------------------------------------------
/docs_source/sphinx/source/conf.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import sys
4 | import os
5 | sys.path.append(os.path.abspath("../../../zroya"))
6 |
7 | import version as zroya_version
8 |
9 | #
10 | # Configuration file for the Sphinx documentation builder.
11 | #
12 | # This file does only contain a selection of the most common options. For a
13 | # full list see the documentation:
14 | # http://www.sphinx-doc.org/en/stable/config
15 |
16 | # -- Path setup --------------------------------------------------------------
17 |
18 | # If extensions (or modules to document with autodoc) are in another directory,
19 | # add these directories to sys.path here. If the directory is relative to the
20 | # documentation root, use os.path.abspath to make it absolute, like shown here.
21 | #
22 | # import os
23 | # import sys
24 | # sys.path.insert(0, os.path.abspath('.'))
25 |
26 |
27 | # -- Project information -----------------------------------------------------
28 |
29 | project = 'Zroya'
30 | copyright = '2018, Jan Malčák'
31 | author = 'Jan Malčák'
32 |
33 | # The short X.Y version
34 | version = zroya_version.__version__
35 | # The full version, including alpha/beta/rc tags
36 | release = zroya_version.__release__
37 |
38 |
39 | # -- General configuration ---------------------------------------------------
40 |
41 | # If your documentation needs a minimal Sphinx version, state it here.
42 | #
43 | # needs_sphinx = '1.0'
44 |
45 | # Add any Sphinx extension module names here, as strings. They can be
46 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
47 | # ones.
48 | extensions = [
49 | 'sphinx.ext.autodoc',
50 | 'sphinx.ext.coverage',
51 | 'sphinxcontrib.fulltoc',
52 | ]
53 |
54 | # Add any paths that contain templates here, relative to this directory.
55 | templates_path = ['_templates']
56 |
57 | # The suffix(es) of source filenames.
58 | # You can specify multiple suffix as a list of string:
59 | #
60 | # source_suffix = ['.rst', '.md']
61 | source_suffix = '.rst'
62 |
63 | # The master toctree document.
64 | master_doc = 'index'
65 |
66 | # The language for content autogenerated by Sphinx. Refer to documentation
67 | # for a list of supported languages.
68 | #
69 | # This is also used if you do content translation via gettext catalogs.
70 | # Usually you set "language" from the command line for these cases.
71 | language = None
72 |
73 | # List of patterns, relative to source directory, that match files and
74 | # directories to ignore when looking for source files.
75 | # This pattern also affects html_static_path and html_extra_path .
76 | exclude_patterns = []
77 |
78 | # The name of the Pygments (syntax highlighting) style to use.
79 | pygments_style = 'sphinx'
80 |
81 |
82 | # -- Options for HTML output -------------------------------------------------
83 |
84 | # The theme to use for HTML and HTML Help pages. See the documentation for
85 | # a list of builtin themes.
86 | #
87 | html_theme = 'alabaster'
88 |
89 | # Theme options are theme-specific and customize the look and feel of a theme
90 | # further. For a list of options available for each theme, see the
91 | # documentation.
92 | #
93 | # html_theme_options = {}
94 |
95 | # Add any paths that contain custom static files (such as style sheets) here,
96 | # relative to this directory. They are copied after the builtin static files,
97 | # so a file named "default.css" will overwrite the builtin "default.css".
98 | html_static_path = ['_static']
99 |
100 | # Custom sidebar templates, must be a dictionary that maps document names
101 | # to template names.
102 | #
103 | # The default sidebars (for documents that don't match any pattern) are
104 | # defined by theme itself. Builtin themes are using these templates by
105 | # default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
106 | # 'searchbox.html']``.
107 | #
108 | # html_sidebars = {}
109 |
110 |
111 | # -- Options for HTMLHelp output ---------------------------------------------
112 |
113 | # Output file base name for HTML help builder.
114 | htmlhelp_basename = 'Zroyadoc'
115 |
116 |
117 | # -- Options for LaTeX output ------------------------------------------------
118 |
119 | latex_elements = {
120 | # The paper size ('letterpaper' or 'a4paper').
121 | #
122 | # 'papersize': 'letterpaper',
123 |
124 | # The font size ('10pt', '11pt' or '12pt').
125 | #
126 | # 'pointsize': '10pt',
127 |
128 | # Additional stuff for the LaTeX preamble.
129 | #
130 | # 'preamble': '',
131 |
132 | # Latex figure (float) alignment
133 | #
134 | # 'figure_align': 'htbp',
135 | }
136 |
137 | # Grouping the document tree into LaTeX files. List of tuples
138 | # (source start file, target name, title,
139 | # author, documentclass [howto, manual, or own class]).
140 | latex_documents = [
141 | (master_doc, 'Zroya.tex', 'Zroya Documentation',
142 | 'Jan Malčák', 'manual'),
143 | ]
144 |
145 |
146 | # -- Options for manual page output ------------------------------------------
147 |
148 | # One entry per manual page. List of tuples
149 | # (source start file, name, description, authors, manual section).
150 | man_pages = [
151 | (master_doc, 'zroya', 'Zroya Documentation',
152 | [author], 1)
153 | ]
154 |
155 |
156 | # -- Options for Texinfo output ----------------------------------------------
157 |
158 | # Grouping the document tree into Texinfo files. List of tuples
159 | # (source start file, target name, title, author,
160 | # dir menu entry, description, category)
161 | texinfo_documents = [
162 | (master_doc, 'Zroya', 'Zroya Documentation',
163 | author, 'Zroya', 'One line description of project.',
164 | 'Miscellaneous'),
165 | ]
166 |
167 |
168 | # -- Extension configuration -------------------------------------------------
169 |
170 | def setup(app):
171 | app.add_stylesheet("css/styles.css")
172 |
--------------------------------------------------------------------------------
/docs_source/sphinx/source/content.rst:
--------------------------------------------------------------------------------
1 | Tutorial
2 | ========
3 |
4 | .. toctree::
5 | :maxdepth: 2
6 |
7 | in_action
8 | tutorials/installation
9 | tutorials/index
10 | tutorials/template
11 | tutorials/callbacks
12 | documentation
13 | committing
14 |
--------------------------------------------------------------------------------
/docs_source/sphinx/source/documentation.rst:
--------------------------------------------------------------------------------
1 | API Documentation
2 | =================
3 |
4 | Functions
5 | ---------
6 | .. automodule:: zroya
7 | :members: init, show, hide
8 |
9 | Template
10 | --------
11 |
12 | .. autoclass:: zroya.Template
13 | :members:
14 |
15 | TemplateType
16 | ^^^^^^^^^^^^
17 |
18 | .. autoclass:: zroya.TemplateType
19 | :members:
20 |
21 | Audio
22 | -----
23 |
24 | .. autoclass:: zroya.Audio
25 | :members:
26 |
27 | AudioMode
28 | ^^^^^^^^^
29 |
30 | .. autoclass:: zroya.AudioMode
31 | :members:
32 |
33 | DismissReason
34 | -------------
35 |
36 | .. autoclass:: zroya.DismissReason
37 | :members:
38 |
--------------------------------------------------------------------------------
/docs_source/sphinx/source/in_action.rst:
--------------------------------------------------------------------------------
1 | In Action
2 | =========
3 |
4 | This page contains code snippets with summary of zroya's abilities. See :doc:`tutorials/index` for more detailed
5 | introduction.
6 |
7 | Simple Notification
8 | -------------------
9 |
10 | .. code-block:: python
11 |
12 | import zroya
13 |
14 | zroya.init("Python", "a", "b", "c", "d")
15 | t = zroya.Template(zroya.TemplateType.Text1)
16 | t.setFirstLine("Just one bold line")
17 | zroya.show(t)
18 |
19 | .. figure:: _static/in_action_one_line.png
20 | :alt: Notification with one bold line
21 |
22 | Multiline Notification With Image
23 | ---------------------------------
24 |
25 | .. code-block:: python
26 |
27 | import zroya
28 |
29 | zroya.init("Python", "a", "b", "c", "d")
30 | t = zroya.Template(zroya.TemplateType.ImageAndText4)
31 | t.setFirstLine("First bold line")
32 | t.setSecondLine("Second line is in regular font")
33 | t.setImage("./files/image.png")
34 | zroya.show(t)
35 |
36 | .. figure:: _static/in_action_multiline_image.png
37 | :alt: Notification with one bold, one regular line and an image.
38 |
39 | Attaching callbacks
40 | -------------------
41 |
42 | .. code-block:: python
43 |
44 | import zroya
45 | import time
46 |
47 | def onClickHandler(notification_id):
48 | print("Clicked!")
49 |
50 | zroya.init("Python", "a", "b", "c", "d")
51 | t = zroya.Template(zroya.TemplateType.Text1)
52 | t.setFirstLine("Click on me, please!")
53 | zroya.show(t, on_click=onClickHandler)
54 | time.sleep(10)
55 |
--------------------------------------------------------------------------------
/docs_source/sphinx/source/index.rst:
--------------------------------------------------------------------------------
1 | Welcome to Zroya's documentation!
2 | =================================
3 |
4 | Zroya is a Python extension which allows you to create native Windows notifications.
5 |
6 | Installation
7 | ------------
8 |
9 | Zroya is available from pypi:
10 |
11 | .. code-block:: Bash
12 |
13 | python pip install zroya
14 |
15 | Requirements
16 | ------------
17 |
18 | There are no requirements for zroya at the moment.
19 |
20 | What next?
21 | ----------
22 |
23 | Are you interested? Visit :doc:`in_action` and decide, if it is the right package for you. If so, I recommend you to
24 | take a look at :doc:`tutorials/index`.
25 |
26 | .. include:: content.rst
27 |
28 |
--------------------------------------------------------------------------------
/docs_source/sphinx/source/tutorials/callbacks.rst:
--------------------------------------------------------------------------------
1 | Callbacks
2 | =========
3 |
4 | In the previous part of the tutorial, action buttons were added. But they did nothing. In this tutorial,
5 | I'll teach you how to make them alive.
6 |
7 | But first I have to introduce you into zroya's callback system. Zroya registers four different events:
8 |
9 | * **onClick** - Fired every time user clicks on notification.
10 | * **onAction** - Activated when action button is clicked.
11 | * **onDismiss** - When the notification is dismissed by user or automatically.
12 | * **onFail** - Something went wrong.
13 |
14 | If you want to be informed, when any of them happens, register event handler with **on_** parameters of
15 | :py:func:`zroya.show`. Event handler is nothing more than a regular function taking one, or two parameters. Number of
16 | parameters depends on the event you register for.
17 |
18 | On Click
19 | ---------
20 |
21 | On click handler takes one parameter and it is notification ID. This is the number you get as a return value from
22 | :py:func:`zroya.show`.
23 |
24 | .. code-block:: python
25 |
26 | def onClickHandler(notification_id):
27 | pass
28 |
29 | On Action
30 | ---------
31 |
32 | On Action handler takes two parameters, notification ID and action ID. Action ID is number returned by
33 | :py:meth:`zroya.Template.addAction`.
34 |
35 | .. code-block:: python
36 |
37 | def onActionHandler(notification_id, action_id):
38 | pass
39 |
40 | On Dismiss
41 | ----------
42 |
43 | On Dismiss handler is function with two parameters. First one is notification ID. The second one is
44 | :py:class:`zroya.DismissReason`.
45 |
46 | .. code-block:: python
47 |
48 | def onDismissHandler(notification_id, reason):
49 | pass
50 |
51 | On Fail
52 | -------
53 |
54 | Last, on fail handler is function with one parameter, the same as on click callback. The parameter is notification ID
55 | returned from :py:func:`zroya.show`.
56 |
57 | .. code-block:: python
58 |
59 | def onFailHandler(notification_id):
60 | pass
61 |
62 | Adding handlers
63 | ---------------
64 |
65 | Let's go back a bit. In :doc:`template`, we created a notification for simple bot asking user "How are you?". Now
66 | we add response to each of the action button.
67 |
68 | .. code-block:: python
69 |
70 | import zroya
71 | import time
72 |
73 | # Initialization is required. But in real usage, check the return code, please.
74 | zroya.init("python", "a", "b", "c", "d")
75 |
76 | # Template for question
77 | ask_template = zroya.Template(zroya.TemplateType.ImageAndText4)
78 | ask_template.setFirstLine("Hi, I am NotifyBot.")
79 | ask_template.setSecondLine("It is nice to meet you.")
80 | ask_template.setThirdLine("How are you?")
81 | ask_template.setImage("./files/image.png")
82 | ask_template.addAction("I'm OK, I guess")
83 | ask_template.addAction("Fine")
84 |
85 | # Response for Fine
86 | fine_template = zroya.Template(zroya.TemplateType.Text1)
87 | fine_template.setFirstLine("Glad to hear that!")
88 |
89 | # Response for OK
90 | ok_template = zroya.Template(zroya.TemplateType.Text1)
91 | ok_template.setFirstLine("I'm sorry to hear that!")
92 |
93 |
94 | # prepare handler
95 | def onAction(nid, action_id):
96 | global fine_template, ok_template
97 |
98 | if action_id == 0:
99 | zroya.show(ok_template)
100 | else:
101 | zroya.show(fine_template)
102 |
103 | # Show question
104 | zroya.show(ask_template, on_action=onAction)
105 |
106 | # Keep application running, unless onAction handler is never executed.
107 | time.sleep(10)
108 |
109 | Adding images to answers with emoticons, changing sounds etc. would take this to whole new level. You can always play
110 | with it as you wish.
111 |
112 | I owe you one more answer. How did I know that "I'm OK", gets action ID 0 and "Fine" is ID 1? See
113 | :py:meth:`zroya.Template.addAction` ;) Now enjoy the result:
114 |
115 | .. figure:: ../_static/tutorials_callbacks_final.gif
116 | :alt: Process of asking "How are you" followed with the response on me clicking on "I'm fine".
117 |
118 | Pretty impressive, isn't it?
119 |
--------------------------------------------------------------------------------
/docs_source/sphinx/source/tutorials/index.rst:
--------------------------------------------------------------------------------
1 | First steps
2 | ===========
3 |
4 | This tutorial focus only on the basics. It will walk you through setting zroya up, creating template, adding attributes
5 | to it and finally showing a notification.
6 |
7 | Before you follow this tutorial, make sure zroya is installed. See :doc:`installation`.
8 |
9 | .. code-block:: python
10 |
11 | import zroya
12 |
13 | First thing you have to do each time you want to use zroya is to initialize it. This is
14 | required for Windows to associate Python application with notifications.
15 |
16 | .. code-block:: python
17 |
18 | import zroya
19 |
20 | status = zroya.init(
21 | app_name="NotifyBot",
22 | company_name="MyBotCorp",
23 | product_name="NoBo",
24 | sub_product="core",
25 | version="v01"
26 | )
27 |
28 | if not status:
29 | print("Initialization failed")
30 |
31 | Note that all parameters of :py:func:`zroya.init` are required and they have to be strings. As you see,
32 | :py:func:`zroya.init` returns a boolean status. Always make sure that initialization did not fail.
33 |
34 | Notification templates
35 | ----------------------
36 |
37 | Now you are ready to create a notification. Each one is based on a :py:class:`zroya.Template`. It holds
38 | all information about the notification - text, image, sounds, etc.
39 |
40 | There are some predefined template types. Think of them as a form you fill blank fields into. The simplest type is
41 | :py:attr:`zroya.TemplateType.Text1`, which have only one field - first line. Filling anything more will result in
42 | errors.
43 |
44 | All types are defined in :py:class:`zroya.TemplateType` class. Select one of them and we will use it to create a
45 | template.
46 |
47 | .. code-block:: python
48 |
49 | # zroya is imported and initialized at this moment
50 | template = zroya.Template(zroya.TemplateType.Text1)
51 |
52 | As you can see, you pass selected template type as a parameter to constructor of :py:class:`zroya.Template`.
53 |
54 | Set it's text
55 | -------------
56 |
57 | We did create a template. But it does not hold anything. Say you want to show "Hi, how are you?" in it. Following code
58 | will do so:
59 |
60 | .. code-block:: python
61 |
62 | # template is an instance of zroya.Template
63 | template.setFirstLine("Hi, how are you?")
64 |
65 | Show it to the world
66 | --------------------
67 |
68 | We got there, finally. It is time to show the notification. Use :py:func:`zroya.show` function and pass it **template**
69 | as first parameter:
70 |
71 | .. code-block:: python
72 |
73 | # template is an instance of zroya.Template
74 | zroya.show(template)
75 |
76 | :py:func:`zroya.show` has more parameters, but they don't have to bother you at the moment. We will focus on them in
77 | following steps of this tutorial.
78 |
79 | If everything went right, you should register a notification showing up at the right down corner of your screen.
80 |
81 | .. figure:: ../_static/tutorials_first_steps.png
82 | :alt: Image of notification saying "Hi, how are you?"
83 |
84 | Result of our hard work :)
85 |
86 | Troubleshooting
87 | ---------------
88 |
89 | **Calling** :py:func:`zroya.init` **failed**: This shouldn't happen. Please make sure to `report it`_. It helps me a lot
90 | with debugging and serving you the best product.
91 |
92 | **There is no notification!**: Make sure it is allowed for python (or for any app you are using zroya in) to create
93 | notifications.
94 |
95 | Head to *Settings* **=>** *System* **=>** *Notifications and Actions*. Scroll down and find Python. Set Notifications to
96 | On.
97 |
98 | .. figure:: ../_static/tutorials_first_steps_troubleshooting.gif
99 | :alt: Video showing how to enable notifications for python.
100 |
101 | How to enable notifications.
102 |
103 | .. _report it: https://github.com/malja/zroya/issues/new
--------------------------------------------------------------------------------
/docs_source/sphinx/source/tutorials/installation.rst:
--------------------------------------------------------------------------------
1 | Instalation
2 | ===========
3 |
4 | Installing zroya is pretty straight forward. Just use pypi:
5 |
6 | .. code-block:: bash
7 |
8 | python -m pip install zroya
9 |
10 | Installing from source code
11 | ---------------------------
12 |
13 | For building zroya from source code, Visual C++ Libraries have to be installed in the first place.
14 |
15 | Then clone latest version of zroya:
16 |
17 | .. code-block:: bash
18 |
19 | git clone https://github.com/malja/zroya.git
20 |
21 | And build it with distutils:
22 |
23 | .. code-block:: bash
24 |
25 | python setup.py build
--------------------------------------------------------------------------------
/docs_source/sphinx/source/tutorials/template.rst:
--------------------------------------------------------------------------------
1 | Further on templates
2 | ====================
3 |
4 | In previous tutorial, we managed to create a notification from template. In this part, we will make the most from
5 | templates.
6 |
7 | Multiple lines
8 | --------------
9 |
10 | As I said in previous tutorial, not each :py:class:`zroya.TemplateType` supports multiple lines of text. So make
11 | sure you pick the right one - for example :py:attr:`zroya.TemplateType.ImageAndText4`. You may set up to three lines of
12 | text to it.
13 |
14 | .. code-block:: python
15 |
16 | # zroya is imported and initialized
17 | template = zroya.Template(zroya.TemplateType.ImageAndText4)
18 | template.setFirstLine("Hi, I am NotifyBot.")
19 | template.setSecondLine("It is nice to meet you.")
20 | template.setThirdLine("How are you?")
21 |
22 | zroya.show(template)
23 |
24 | At the moment, zroya supports up to three lines - each one is set by it's own function -
25 | :py:meth:`zroya.Template.setFirstLine`, :py:meth:`zroya.Template.setSecondLine` and
26 | :py:meth:`zroya.Template.setThirdLine`.
27 |
28 | .. figure:: ../_static/tutorials_template_three_lines.png
29 | :alt: Image with a notification which contains three lines of text. First line is bold.
30 |
31 | Notification with three lines of text
32 |
33 | Getting the text back
34 | ---------------------
35 |
36 | Except functions for setting text, there are functions for getting it back from template. They are named
37 | :py:meth:`zroya.Template.getFirstLine`, :py:meth:`zroya.Template.getSecondLine` and
38 | :py:meth:`zroya.Template.getThirdLine` respectively.
39 |
40 | We will use template from previous example to get second line back:
41 |
42 | .. code-block:: python
43 |
44 | print(template.getSecondLine())
45 | #> "It is nice to meet you."
46 |
47 | If there is no such text, empty string is returned.
48 |
49 | Change sound
50 | ------------
51 |
52 | It is all nice and so, but the sound Windows does when notification is created is sooo boring, right? Let's change it.
53 |
54 | .. code-block:: python
55 |
56 | template.setAudio(zroya.Audio.Call4)
57 |
58 | Sadly, there is no way to play just any sound you want. You can choose from plenty of sounds defined in
59 | :py:class:`zroya.Audio` class. On the other hand, they are available at any Windows station.
60 |
61 | If this is not enough, you can play selected sound in loop until the notification is moved to Action Center,
62 | or until user dismiss it.
63 |
64 | .. code-block:: python
65 |
66 | template.setAudio(zroya.Audio.Call4, zroya.AudioMode.Looping)
67 |
68 | But I wouldn't recommend it. On the other hand, muting notifications may be usable a bit more:
69 |
70 | .. code-block:: python
71 |
72 | template.setAudio(mode=zroya.AudioMode.Silence)
73 |
74 | Expiration time
75 | ---------------
76 |
77 | Notifications will stay in Action Center until you shut the application off or you manually remove them from there.
78 | But some notifications should have shorter lifespan - for example weather reports. There is no use of the old ones.
79 | Beside hiding them from code, :py:meth:`zroya.Template.setExpiration` comes to aid.
80 |
81 | .. code-block:: python
82 |
83 | template.setExpiration(1000)
84 |
85 | It takes a number of milliseconds after which the notification is automatically removed from Action Center.
86 |
87 | Images
88 | ------
89 |
90 | UI is key to user's heart. Let's make bot more friendly. Add image with :py:meth:`zroya.Template.setImage`.
91 |
92 | .. code-block:: python
93 |
94 | template.setImage("./image.png")
95 |
96 | .. figure:: ../_static/tutorials_template_image.png
97 | :alt: Notification with friendly image of bot.
98 |
99 | Isn't he cute :*
100 |
101 | At this point, we make use of that :py:attr:`zroya.TemplateType.ImageAndText4` template type. For example
102 | with :py:attr:`zroya.TemplateType.Text4`, this function would return False every time, because it does not support
103 | this type.
104 |
105 | Actions
106 | -------
107 |
108 | One pretty cool feature is adding actions. Those are buttons which can have attached some action to them. When user
109 | click them, event is fired. See :doc:`callbacks`.
110 |
111 | In this example, we add two buttons to respond question notification is asking. What a wonderful time, answering
112 | your own questions :).
113 |
114 | .. code-block:: python
115 |
116 | template.addAction("I'm OK, I guess")
117 | template.addAction("Fine")
118 |
119 | .. figure:: ../_static/tutorials_template_actions.png
120 | :alt: Notification with buttons for answering the question
121 |
122 | Answer the question, please.
123 |
124 | As you probably noticed, they don't do much now. Just dismiss it. We will do something about it in the next tutorial.
125 |
126 | Troubleshooting
127 | ---------------
128 |
129 | **Actions fail to be added**: Actions are one of Windows 8.1+ features. If you have older system, they won't work.
--------------------------------------------------------------------------------
/generate_stubs.py:
--------------------------------------------------------------------------------
1 | import inspect
2 | import sys
3 |
4 | # This script generates zroya stub file from documentation zroya C/C++ code.
5 | # Stub file is a hint for IDE. It contains a list of all functions and methods in zroya with docstrings.
6 |
7 | # TODO: Find better way for output formatting than this
8 |
9 |
10 | def GenerateStubFile(path_to_pyd, path_to_python_files):
11 |
12 | # Add Path to .pyd file with zroya to import path
13 | sys.path.append(path_to_pyd)
14 | sys.path.append(path_to_python_files)
15 |
16 | # Import zroya module
17 | import _zroya
18 | import template_enums
19 | import dismiss_reason
20 |
21 | modules = [
22 | _zroya,
23 | template_enums,
24 | dismiss_reason
25 | ]
26 |
27 | # Generate .pyi file for zroya module
28 | with open("./zroya/zroya.pyi", "w", encoding="utf8") as output:
29 |
30 | for module in modules:
31 |
32 | # Get all classes/functions in zroya package
33 | for name, obj in inspect.getmembers(module):
34 |
35 | # TODO: Do not expose Enum class at all
36 | if "Enum" in name:
37 | continue
38 |
39 | # Is it a package function
40 | if inspect.isbuiltin(obj):
41 |
42 | # Print def ():
43 | output.write("def {}{}:\n".format(name, inspect.signature(obj)))
44 | # Print functions docstring
45 | output.write("\t\"\"\"\n\t{}\n\t\"\"\"\n\tpass\n\n".format(inspect.getdoc(obj).replace("\n", "\n\t")))
46 |
47 | # Is it a class
48 | if inspect.isclass(obj):
49 |
50 | # Print class :
51 | output.write("class {}:\n".format(name))
52 | # Print class docstring
53 | output.write("\t\"\"\"{}\"\"\"\n\n".format(obj.__doc__))
54 |
55 | # Get all attributes of class
56 | for member_name, member_value in inspect.getmembers(obj):
57 |
58 | # Ignore zroya members
59 | if member_name[0] != "_":
60 | # Is it zroya enum?
61 | if hasattr(member_value, "value"):
62 | member_value = member_value.value
63 |
64 | # Is value string
65 | if isinstance( member_value, str):
66 | # Put " and " around value
67 | output.write("\t{} = \"{}\"\n\n".format(member_name, member_value))
68 | elif isinstance( member_value, int):
69 | # Print number
70 | output.write("\t{} = {}\n\n".format(member_name, member_value))
71 |
72 | # Get all methods from class
73 | for cname, cobj in inspect.getmembers(obj):
74 | # Is it a method? Ignoring those starting with undercore, because zroya does not set them.
75 | if inspect.ismethoddescriptor(cobj) and cname[0] != "_":
76 | # Get method signature. Replace leading and trailing bracket, because I have to add self parameter
77 |
78 | signature = str(inspect.signature(cobj)).replace("(", "").replace(")", "")
79 | # Print: def (self, ):
80 |
81 | if len(signature) == 0:
82 | output.write("\tdef {}(self):\n".format(cname))
83 | else:
84 | output.write("\tdef {}(self, {}):\n".format(cname, signature))
85 |
86 | # Print methods docstring
87 | output.write("\t\t\"\"\"\n\t\t{}\n\t\t\"\"\"\n\t\tpass\n\n".format(inspect.getdoc(cobj).replace("\n", "\n\t\t")))
--------------------------------------------------------------------------------
/module/event_handler.cpp:
--------------------------------------------------------------------------------
1 | #include "event_handler.h"
2 |
3 | void zroya::EventHandler::toastActivated(INT64 notificationID) const {
4 | std::cout << "Cpp: EventHandler: Activated: " << notificationID << std::endl;
5 |
6 | auto it = this->callbacks.find(notificationID);
7 | if (it != this->callbacks.end()) {
8 |
9 | std::cout << "Cpp: EventHandler: Activated: Event found" << std::endl;
10 |
11 | PyObject *onClicked = it->second->clicked;
12 |
13 | if (onClicked) {
14 |
15 | std::cout << "Cpp: EventHandler: Activated: Event handler is set" << std::endl;
16 |
17 | if (PyCallable_Check(onClicked)) {
18 |
19 | std::cout << "Cpp: EventHandler: Activated: Event handler is callable" << std::endl;
20 |
21 | PyGILState_STATE gstate;
22 | gstate = PyGILState_Ensure();
23 |
24 | PyObject *args = Py_BuildValue("(L)", notificationID);
25 |
26 | PyObject_CallObject(onClicked, args);
27 |
28 | PyGILState_Release(gstate);
29 | }
30 | }
31 | }
32 | }
33 |
34 | void zroya::EventHandler::toastActivated(int actionIndex, INT64 notificationID) const {
35 | std::cout << "Cpp: EventHandler: Activated2: " << notificationID << std::endl;
36 |
37 | auto it = this->callbacks.find(notificationID);
38 | if (it != this->callbacks.end()) {
39 |
40 | std::cout << "Cpp: EventHandler: Activated2: Event found" << std::endl;
41 |
42 | PyObject *onAction = it->second->action;
43 |
44 | if (onAction) {
45 |
46 | std::cout << "Cpp: EventHandler: Activated2: Event handler is set" << std::endl;
47 |
48 | if (PyCallable_Check(onAction)) {
49 |
50 | std::cout << "Cpp: EventHandler: Activated2: Event handler is callable" << std::endl;
51 |
52 | PyGILState_STATE gstate;
53 | gstate = PyGILState_Ensure();
54 |
55 | PyObject *args = Py_BuildValue("(L, i)", notificationID, actionIndex);
56 |
57 | PyObject_CallObject(onAction, args);
58 |
59 | PyGILState_Release(gstate);
60 | }
61 | }
62 | }
63 | }
64 |
65 | void zroya::EventHandler::toastDismissed(WinToastLib::IWinToastHandler::WinToastDismissalReason state, INT64 notificationID) const {
66 | std::cout << "Cpp: EventHandler: Dismiss: " << notificationID << std::endl;
67 |
68 | auto it = this->callbacks.find(notificationID);
69 | if (it != this->callbacks.end()) {
70 |
71 | std::cout << "Cpp: EventHandler: Dismiss: Event found" << std::endl;
72 |
73 | PyObject *onDismiss = it->second->dismissed;
74 |
75 | if (onDismiss) {
76 |
77 | std::cout << "Cpp: EventHandler: Dismiss: Event handler is set" << std::endl;
78 |
79 | if (PyCallable_Check(onDismiss)) {
80 |
81 | std::cout << "Cpp: EventHandler: Dismiss: Event handler is callable" << std::endl;
82 |
83 | PyGILState_STATE gstate;
84 | gstate = PyGILState_Ensure();
85 |
86 | PyObject *zroya_module = PyImport_ImportModule("zroya");
87 | if (!zroya_module) {
88 | std::cout << "no zroya module" << std::endl;
89 | return;
90 | }
91 |
92 | PyObject *zroya_DissmissReason = PyObject_GetAttrString(zroya_module, "DismissReason");
93 | if (!zroya_DissmissReason) {
94 | std::cout << "No dismiss reason class" << std::endl;
95 | return;
96 | }
97 |
98 | PyObject* zroya_DismissReason_instance = PyObject_CallFunction(zroya_DissmissReason, "i", (int)state);
99 | PyObject *args = Py_BuildValue("(L, O)", notificationID, zroya_DismissReason_instance);
100 | //PyObject *args = Py_BuildValue("(L, i)", notificationID, (int)state );
101 |
102 | PyObject_CallObject(onDismiss, args);
103 |
104 | PyGILState_Release(gstate);
105 | }
106 | }
107 | }
108 | }
109 |
110 | void zroya::EventHandler::toastFailed(INT64 notificationID) const {
111 | std::cout << "Cpp: EventHandler: Failed: " << notificationID << std::endl;
112 |
113 | auto it = this->callbacks.find(notificationID);
114 | if (it != this->callbacks.end()) {
115 |
116 | std::cout << "Cpp: EventHandler: Failed: Event found" << std::endl;
117 |
118 | PyObject *onFailed = it->second->failed;
119 |
120 | if (onFailed) {
121 |
122 | std::cout << "Cpp: EventHandler: Failed: Event handler is set" << std::endl;
123 |
124 | if (PyCallable_Check(onFailed)) {
125 |
126 | std::cout << "Cpp: EventHandler: Failed: Event handler is callable" << std::endl;
127 |
128 | PyGILState_STATE gstate;
129 | gstate = PyGILState_Ensure();
130 |
131 | PyObject *args = Py_BuildValue("(L)", notificationID);
132 |
133 | PyObject_CallObject(onFailed, args);
134 |
135 | PyGILState_Release(gstate);
136 | }
137 | }
138 | }
139 | }
140 |
141 | void zroya::EventHandler::addCallbacks(INT64 notificationID, PyObject *clicked, PyObject *action, PyObject *dismissed, PyObject *failed) {
142 |
143 | this->callbacks.insert(
144 | std::pair(
145 | notificationID,
146 | new Event(clicked, action, dismissed, failed)
147 | )
148 | );
149 | }
--------------------------------------------------------------------------------
/module/event_handler.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "wintoastlib.h"
4 | #include
5 |
6 | namespace zroya {
7 |
8 | /**
9 | * Notification handler. Each of toast* methods is called by WinToastLib when corresponding
10 | * event fires. Event handler get a notification ID and looks if it has registered callback.
11 | * If so, it is called.
12 | */
13 | class EventHandler : public WinToastLib::IWinToastHandler {
14 |
15 | enum EventType {
16 | Activated,
17 | Action,
18 | Dismissed,
19 | Failed
20 | };
21 |
22 | class Event {
23 |
24 | public:
25 | PyObject *clicked;
26 | PyObject *action;
27 | PyObject *failed;
28 | PyObject *dismissed;
29 |
30 | Event(PyObject *clicked, PyObject *action, PyObject *dismissed, PyObject *failed) {
31 | this->clicked = clicked;
32 | this->action = action;
33 | this->dismissed = dismissed;
34 | this->failed = failed;
35 | }
36 |
37 | ~Event() {
38 | Py_XDECREF(this->clicked);
39 | Py_XDECREF(this->action);
40 | Py_XDECREF(this->dismissed);
41 | Py_XDECREF(this->failed);
42 | }
43 |
44 | };
45 |
46 | public:
47 | void toastActivated(INT64 notificationID) const;
48 | void toastActivated(int actionIndex, INT64 notificationID) const;
49 | void toastDismissed(WinToastDismissalReason state, INT64 notificationID) const;
50 | void toastFailed(INT64 notificationID) const;
51 |
52 | void addCallbacks(INT64 notificationID, PyObject *activated, PyObject *action = nullptr, PyObject *dismissed = nullptr, PyObject *failed = nullptr);
53 |
54 | ~EventHandler() {
55 | for (auto it = callbacks.begin(); it != callbacks.end(); it++) {
56 | delete it->second;
57 | }
58 | }
59 |
60 | protected:
61 |
62 | std::map callbacks;
63 | };
64 | }
--------------------------------------------------------------------------------
/module/init.cpp:
--------------------------------------------------------------------------------
1 | #include "wintoastlib.h"
2 | #include "utils.h"
3 | #include "init.h"
4 |
5 | bool zroya::init(const std::string &app_name, const std::string &company_name, const std::string &product_name, const std::string &sub_product, const std::string &version) {
6 |
7 | // Set application name
8 | WinToastLib::WinToast::instance()->setAppName(
9 | convert(app_name)
10 | );
11 |
12 | // Setup new application ID
13 | WinToastLib::WinToast::instance()->setAppUserModelId(
14 | WinToastLib::WinToast::configureAUMI(
15 | convert(company_name), convert(product_name), convert(sub_product), convert(version)
16 | )
17 | );
18 |
19 | // Init WinToast library
20 | if (!WinToastLib::WinToast::instance()->initialize()) {
21 | return false;
22 | }
23 |
24 | return true;
25 | }
26 |
27 | /**
28 | * Initialize library with random strings as company_name, product_name, sub_product and version. This version
29 | * will be called when user does not call init explicitly.
30 | */
31 | bool zroya::init() {
32 | return zroya::init(
33 | std::string("python"),
34 | random_string(5),
35 | random_string(5),
36 | random_string(5),
37 | random_string(5)
38 | );
39 | }
--------------------------------------------------------------------------------
/module/init.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | namespace zroya {
5 |
6 | /**
7 | * Initialize WinToastLib with provided parameters.
8 | */
9 | bool init(const std::string &app_name, const std::string &company_name, const std::string &product_name, const std::string &sub_product, const std::string &version);
10 |
11 | /**
12 | * Initialize WinToastLib with random parameters. Used for automatical init when user does not call init function explicitly.
13 | */
14 | bool init();
15 | }
--------------------------------------------------------------------------------
/module/module.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.27428.2002
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "module", "module\module.vcxproj", "{52FB84A8-EA34-4C64-9E80-84CC1436FB40}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x64 = Debug|x64
11 | Debug|x86 = Debug|x86
12 | Release|x64 = Release|x64
13 | Release|x86 = Release|x86
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {52FB84A8-EA34-4C64-9E80-84CC1436FB40}.Debug|x64.ActiveCfg = Debug|x64
17 | {52FB84A8-EA34-4C64-9E80-84CC1436FB40}.Debug|x64.Build.0 = Debug|x64
18 | {52FB84A8-EA34-4C64-9E80-84CC1436FB40}.Debug|x86.ActiveCfg = Debug|Win32
19 | {52FB84A8-EA34-4C64-9E80-84CC1436FB40}.Debug|x86.Build.0 = Debug|Win32
20 | {52FB84A8-EA34-4C64-9E80-84CC1436FB40}.Release|x64.ActiveCfg = Release|x64
21 | {52FB84A8-EA34-4C64-9E80-84CC1436FB40}.Release|x64.Build.0 = Release|x64
22 | {52FB84A8-EA34-4C64-9E80-84CC1436FB40}.Release|x86.ActiveCfg = Release|Win32
23 | {52FB84A8-EA34-4C64-9E80-84CC1436FB40}.Release|x86.Build.0 = Release|Win32
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {CBED5592-BA13-438B-B356-0BB71AEF144C}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/module/module/module.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 15.0
23 | {52FB84A8-EA34-4C64-9E80-84CC1436FB40}
24 | module
25 | 10.0.16299.0
26 |
27 |
28 |
29 | Application
30 | true
31 | v141
32 | MultiByte
33 |
34 |
35 | Application
36 | false
37 | v141
38 | true
39 | MultiByte
40 |
41 |
42 | Application
43 | true
44 | v141
45 | MultiByte
46 |
47 |
48 | Application
49 | false
50 | v141
51 | true
52 | MultiByte
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | C:\Users\janma\AppData\Local\Programs\Python\Python36-32\include;$(IncludePath)
74 | C:\Users\janma\AppData\Local\Programs\Python\Python36-32\Lib;$(LibraryPath)
75 |
76 |
77 |
78 | Level3
79 | Disabled
80 | true
81 | true
82 |
83 |
84 |
85 |
86 | Level3
87 | Disabled
88 | true
89 | true
90 |
91 |
92 |
93 |
94 | Level3
95 | MaxSpeed
96 | true
97 | true
98 | true
99 | true
100 |
101 |
102 | true
103 | true
104 |
105 |
106 |
107 |
108 | Level3
109 | MaxSpeed
110 | true
111 | true
112 | true
113 | true
114 |
115 |
116 | true
117 | true
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
--------------------------------------------------------------------------------
/module/module/module.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 | {d272300f-f419-40cd-8f71-f1119be73907}
18 |
19 |
20 | {ffb50eb8-b1cc-4703-aeaf-7ebdce10240b}
21 |
22 |
23 | {aada2f26-b8b7-46bf-8a62-6798194d9d2a}
24 |
25 |
26 | {2e5f86c2-90ab-416e-8103-62b3c3011206}
27 |
28 |
29 |
30 |
31 | Hlavičkové soubory
32 |
33 |
34 | Hlavičkové soubory
35 |
36 |
37 | Hlavičkové soubory
38 |
39 |
40 | Hlavičkové soubory\python
41 |
42 |
43 | Hlavičkové soubory\python
44 |
45 |
46 | Hlavičkové soubory\python
47 |
48 |
49 | Hlavičkové soubory\python
50 |
51 |
52 | Hlavičkové soubory\wintoast
53 |
54 |
55 |
56 |
57 | Zdrojové soubory
58 |
59 |
60 | Zdrojové soubory
61 |
62 |
63 | Zdrojové soubory
64 |
65 |
66 | Zdrojové soubory\python
67 |
68 |
69 | Zdrojové soubory\python
70 |
71 |
72 | Zdrojové soubory\python
73 |
74 |
75 | Zdrojové soubory\python
76 |
77 |
78 | Zdrojové soubory\wintoast
79 |
80 |
81 |
--------------------------------------------------------------------------------
/module/module/module.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/module/py_init.cpp:
--------------------------------------------------------------------------------
1 | #include "py_init.h"
2 | #include "init.h"
3 | #include "utils.h"
4 | #include "wintoastlib.h"
5 | #include "py_template.h"
6 | #include "event_handler.h"
7 |
8 | #include
9 |
10 | PyObject *zroya_init(PyObject *module, PyObject *args, PyObject *kwargs) {
11 |
12 | // List of all parameters this function may get
13 | static char *keywords[] = { (char*)"app_name", (char*)"company_name", (char*)"product_name", (char*)"sub_product", (char*)"version", nullptr };
14 |
15 | const char* app_name, *company_name, *product_name, *sub_product, *version;
16 |
17 | // Parse arguments
18 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sssss", keywords, &app_name, &company_name, &product_name, &sub_product, &version)) {
19 | PyErr_SetString(PyExc_ValueError, "all parameters must be string");
20 | return nullptr;
21 | }
22 |
23 | if (strlen(app_name) == 0 ||
24 | strlen(company_name) == 0 ||
25 | strlen(product_name) == 0 ||
26 | strlen(sub_product) == 0 ||
27 | strlen(version) == 0) {
28 | PyErr_SetString(PyExc_ValueError, "empty parameters are not allowed");
29 | return nullptr;
30 | }
31 |
32 | // Initialize underlying library with provided parameters.
33 | bool retcode = zroya::init(
34 | std::string(app_name),
35 | std::string(company_name),
36 | std::string(product_name),
37 | std::string(sub_product),
38 | std::string(version)
39 | );
40 |
41 | if (retcode) {
42 | Py_INCREF(Py_True);
43 | return Py_True;
44 | }
45 | else {
46 | Py_INCREF(Py_False);
47 | return Py_False;
48 | }
49 |
50 | }
51 |
52 | PyObject *zroya_show(PyObject *module, PyObject *args, PyObject *kwargs) {
53 |
54 | // List of all parameters thsi function accept
55 | static char *keywords[] = { (char*)"template", (char*)"on_click", (char*)"on_action", (char*)"on_dismiss", (char*)"on_fail", nullptr };
56 |
57 | PyObject *toast = nullptr, *on_click = nullptr, *on_action = nullptr, *on_dismiss = nullptr, *on_fail = nullptr;
58 |
59 | // Parse arguments
60 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOOO", keywords, &toast, &on_click, &on_action, &on_dismiss, &on_fail)) {
61 | return nullptr;
62 | }
63 |
64 | // Make sure template parameter is of zroya.Template type
65 | if (strcmp(toast->ob_type->tp_name, "zroya.Template") != 0) {
66 | PyErr_SetString(PyExc_ValueError, "first parameter must be of zroya.Template type.");
67 | return nullptr;
68 | }
69 |
70 | // Make sure WinToastLib is initialized
71 | if (!WinToastLib::WinToast::instance()->isInitialized()) {
72 | if (!zroya::init()) {
73 | PyErr_SetString(PyExc_SystemError, "initialization failed");
74 | return nullptr;
75 | }
76 | }
77 |
78 | zroya_State *state = static_cast(PyModule_GetState(module));
79 |
80 | // Try to show notification and save its ID
81 | INT64 notificationID = WinToastLib::WinToast::instance()->showToast(*(((zroya_Template*)toast)->_template), static_cast(PyModule_GetState(module))->_handler );
82 |
83 | if (notificationID > 0) {
84 | Py_XINCREF(on_click);
85 | Py_XINCREF(on_action);
86 | Py_XINCREF(on_dismiss);
87 | Py_XINCREF(on_fail);
88 |
89 | state->_handler->addCallbacks(notificationID, on_click, on_action, on_dismiss, on_fail);
90 | }
91 |
92 | return PyLong_FromLongLong(notificationID);
93 | }
94 |
95 | PyObject *zroya_hide(PyObject *module, PyObject *arg, PyObject *kwarg) {
96 |
97 | static char *keywords[] = { (char*)"nid" };
98 |
99 | PyObject *notificationID = nullptr;
100 |
101 | if (!PyArg_ParseTupleAndKeywords(arg, kwarg, "O", keywords, ¬ificationID )) {
102 | return nullptr;
103 | }
104 |
105 |
106 | /*
107 | // Parse arguments
108 | if (!PyTuple_Check(arg)) {
109 | PyErr_SetString(PyExc_TypeError, "function takes tuple as parameter.");
110 | return nullptr;
111 | }
112 |
113 | // Exactly one parameter is required
114 | if (PyTuple_Size(arg) != 1) {
115 | PyErr_SetString(PyExc_ValueError, "function requires only one parameter.");
116 | return nullptr;
117 | }*/
118 |
119 | INT64 nID = -1;
120 |
121 | /*
122 | // Get number from PyObject representing tuple
123 | PyObject *tuple = PyTuple_GetItem(arg, 0);
124 | notificationID = PyLong_AsLongLong(tuple);
125 | */
126 |
127 | // Check if parameter is integer
128 | if (!PyLong_Check(notificationID)) {
129 | PyErr_SetString(PyExc_ValueError, "nid parameter is required to be an integer.");
130 | return nullptr;
131 | }
132 |
133 | // Get notification ID as integer
134 | nID = PyLong_AsLongLong(notificationID);
135 |
136 | // Ignore unvalid values
137 | if (nID < 0) {
138 | PyErr_SetString(PyExc_ValueError, "nid may not be negative.");
139 | return nullptr;
140 | }
141 |
142 | if (WinToastLib::WinToast::instance()->hideToast(nID)) {
143 | Py_INCREF(Py_True);
144 | return Py_True;
145 | } else {
146 | Py_INCREF(Py_False);
147 | return Py_False;
148 | }
149 |
150 |
151 | }
152 |
--------------------------------------------------------------------------------
/module/py_init.h:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "wintoastlib.h"
4 | #include "event_handler.h"
5 |
6 | #ifdef __cplusplus
7 | extern "C" {
8 | #endif
9 |
10 | /**
11 | * This file defines few core functions required for zroya module.
12 | */
13 |
14 | /// Zroya global state
15 | typedef struct {
16 | /// Underhood library for notifications
17 | WinToastLib::WinToast *_win_toast;
18 | /// My custom event handler
19 | zroya::EventHandler *_handler;
20 | } zroya_State;
21 |
22 | PyDoc_STRVAR(zroya_init__doc__,
23 | "init(app_name, company_name, product_name, sub_product, version)\n"
24 | "--\n\n"
25 | "Initialize Zroya module. \n"
26 | "\n"
27 | "**Note**: You should call this function before any other manipulation with this module. \n"
28 | "If you do not call this function explicitely, randomly generated strings will be used as default parameters. \n"
29 | "\n"
30 | "Args: \n"
31 | "\tapp_name (str): Application name. \n\n"
32 | "\tcompany_name (str): Part of unique ID created for this application. \n\n"
33 | "\tproduct_name (str): Part of unique ID created for this application. \n\n"
34 | "\tsub_product (str): Part of unique ID created for this application. \n\n"
35 | "\tstr version (str): Part of unique ID created for this application. \n\n"
36 | "\n"
37 | "Returns: \n"
38 | "\tbool: True if initialization is completed, False otherwise."
39 | );
40 | PyObject *zroya_init(PyObject *self, PyObject *args, PyObject *kwargs);
41 |
42 | PyDoc_STRVAR(zroya_show__doc__,
43 | "show(template, on_click=None, on_action=None, on_dismiss=None, on_fail=None)\n"
44 | "--\n\n"
45 | "Create instance of notification template and show it. If any of on_* parameter is set, corresponding event is registered. See :doc:`tutorials/callbacks`.\n"
46 | "\n"
47 | "Args: \n"
48 | "\ttemplate (:py:class:`zroya.Template`): Template instance. \n\n"
49 | "\ton_click (callable): Callback for onClick event. Occurs when user activates a toast notification through a click or touch. \n\n"
50 | "\ton_action (callable): Callback for onAction event. Occurs when user click on action button. \n\n"
51 | "\ton_dismiss (callable): Callback for onDismiss event. Occurs when the notification leaves the screen, either by expiring or being explicitly dismissed by the user. \n\n"
52 | "\ton_fail (callable): Callback for onFail event. Occurs when an error is caused when Windows attempts to raise a toast notification. \n\n"
53 | "\n"
54 | "Returns: \n"
55 | "\tbool: Notification ID if notification was shown. False otherwise."
56 | );
57 | PyObject *zroya_show(PyObject *module, PyObject *args, PyObject *kwargs);
58 |
59 | PyDoc_STRVAR(zroya_hide__doc__,
60 | "hide(nid)\n"
61 | "--\n\n"
62 | "Hide notification by ID. This will trigger onDismiss event.\n"
63 | "\n"
64 | "Args: \n"
65 | "\tnid (int): Notification ID obtained from :py:func:`zroya.show` function. \n"
66 | "\n"
67 | "Returns: \n"
68 | "\tbool: True if notification was hidden, false otherwise."
69 | );
70 | PyObject *zroya_hide(PyObject *module, PyObject *arg, PyObject *kwarg);
71 |
72 | #ifdef __cplusplus
73 | }
74 | #endif
--------------------------------------------------------------------------------
/module/py_module.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "py_module.h"
4 | #include "wintoastlib.h"
5 |
6 | /// Clear zroya module
7 | int zroya_clear(PyObject *self) {
8 | zroya_State* state = static_cast(PyModule_GetState(self));
9 |
10 | // Free
11 | state->_win_toast = nullptr;
12 | delete state->_handler;
13 |
14 | return 0;
15 | }
16 |
17 | /// List of all module functions.
18 | struct PyMethodDef zroya_module_functions[] = {
19 | { "init", (PyCFunction)zroya_init, METH_VARARGS | METH_KEYWORDS, zroya_init__doc__ },
20 | { "show", (PyCFunction)zroya_show, METH_VARARGS | METH_KEYWORDS, zroya_show__doc__ },
21 | { "hide", (PyCFunction)zroya_hide, METH_VARARGS | METH_KEYWORDS, zroya_hide__doc__ },
22 | { nullptr, nullptr, 0, nullptr }
23 | };
24 |
25 | /// Module definition
26 | struct PyModuleDef zroya_module_definition = {
27 | PyModuleDef_HEAD_INIT, /* Always start definition with this :) */
28 | "zroya", /* Module name */
29 | zroya__doc__, /*DOCSTRING*/
30 | sizeof(zroya_State), /* Set module state as global. */
31 | zroya_module_functions, /* Module functions */
32 | nullptr, /* Slots for multi-phase initialization */
33 | nullptr, /* travelsal function */
34 | zroya_clear, /* Clean function */
35 | nullptr /* Free function */
36 | };
37 |
38 | /// Module entry point.
39 | PyMODINIT_FUNC PyInit__zroya() {
40 |
41 | // Check if there is zroya module configuration
42 | if (PyType_Ready(&zroya_template_type) < 0) {
43 | return nullptr;
44 | }
45 |
46 | // Create new module named zroya
47 | PyObject *module = PyModule_Create(&zroya_module_definition);
48 | if (!module) {
49 | return nullptr;
50 | }
51 |
52 | // Add Template class to zroya module
53 | if (PyModule_AddObject(module, "Template", (PyObject*)&zroya_template_type) < 0) {
54 | return nullptr;
55 | }
56 |
57 | PyObject *template_dict = zroya_template_type.tp_dict;
58 |
59 | // WinToast singleton should be accessible from anywhere, but keeping instance
60 | // should prevent from unwanted destroying.
61 | zroya_State *state = (zroya_State*)PyModule_GetState(module);
62 | state->_win_toast = WinToastLib::WinToast::instance();
63 | state->_handler = new zroya::EventHandler;
64 |
65 | if (!PyEval_ThreadsInitialized()) {
66 | PyEval_InitThreads();
67 | }
68 |
69 | return module;
70 | }
71 |
--------------------------------------------------------------------------------
/module/py_module.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "py_init.h"
4 | #include "py_template.h"
5 | #include "event_handler.h"
6 | #include "py_utils.h"
7 |
8 | #ifdef __cplusplus
9 | extern "C" {
10 | #endif
11 |
12 | /**
13 | * This file sets a new python module - zroya. Coresponding Cpp file contains module
14 | * entry point and all required function for creation and destruction of this module.
15 | */
16 |
17 | PyDoc_STRVAR(zroya__doc__,
18 | "zroya\n"
19 | "--\n\n"
20 | "Library for creating native Windows 8, Window 9 and Windows 10 notifications. \n"
21 | );
22 |
23 | #ifdef __cplusplus
24 | }
25 | #endif
--------------------------------------------------------------------------------
/module/py_utils.cpp:
--------------------------------------------------------------------------------
1 | #include "py_utils.h"
2 |
3 | bool file_exists(PyObject *file_name) {
4 |
5 | Py_XINCREF(file_name);
6 |
7 | PyObject *import_name = PyUnicode_FromString("os.path");
8 |
9 | if (!import_name) {
10 |
11 | Py_XDECREF(file_name);
12 | return false;
13 | }
14 |
15 | PyObject *module = PyImport_Import(import_name);
16 |
17 | if (!module) {
18 |
19 | Py_XDECREF(file_name);
20 | Py_XDECREF(import_name);
21 | return false;
22 | }
23 |
24 | PyObject *path_isfile = PyObject_GetAttrString(module, "isfile");
25 | if (!path_isfile) {
26 |
27 | Py_XDECREF(file_name);
28 | Py_XDECREF(import_name);
29 | Py_XDECREF(module);
30 | return false;
31 | }
32 |
33 | PyObject *arguments = PyTuple_Pack(1, file_name);
34 |
35 | if (!arguments) {
36 | Py_XDECREF(file_name);
37 | Py_XDECREF(import_name);
38 | Py_XDECREF(module);
39 | Py_XDECREF(path_isfile);
40 | return false;
41 | }
42 |
43 | PyObject *ret_val = PyObject_CallObject(path_isfile, arguments);
44 | if (!ret_val) {
45 | Py_XDECREF(file_name);
46 | Py_XDECREF(import_name);
47 | Py_XDECREF(module);
48 | Py_XDECREF(path_isfile);
49 | Py_XDECREF(arguments);
50 | return false;
51 | }
52 |
53 | int result = PyObject_IsTrue(ret_val);
54 |
55 | // Clean up
56 | Py_XDECREF(file_name);
57 | Py_XDECREF(import_name);
58 | Py_XDECREF(module);
59 | Py_XDECREF(path_isfile);
60 | Py_XDECREF(arguments);
61 | Py_XDECREF(ret_val);
62 |
63 | return result == 1;
64 | }
65 |
66 | PyObject *abspath(PyObject *relpath) {
67 | Py_XINCREF(relpath);
68 |
69 | PyObject *import_name = PyUnicode_FromString("os.path");
70 |
71 | if (!import_name) {
72 | Py_XDECREF(relpath);
73 |
74 | Py_XINCREF(Py_False);
75 | return Py_False;
76 | }
77 |
78 | PyObject *module = PyImport_Import(import_name);
79 |
80 | if (!module) {
81 | Py_XDECREF(relpath);
82 | Py_XDECREF(import_name);
83 |
84 | Py_XINCREF(Py_False);
85 | return Py_False;
86 | }
87 |
88 | PyObject *path_abspath = PyObject_GetAttrString(module, "abspath");
89 | if (!path_abspath) {
90 | Py_XDECREF(relpath);
91 | Py_XDECREF(import_name);
92 | Py_XDECREF(module);
93 |
94 | Py_XINCREF(Py_False);
95 | return Py_False;
96 | }
97 |
98 | PyObject *arguments = PyTuple_Pack(1, relpath);
99 |
100 | if (!arguments) {
101 | Py_XDECREF(relpath);
102 | Py_XDECREF(import_name);
103 | Py_XDECREF(module);
104 | Py_XDECREF(path_abspath);
105 |
106 | Py_XINCREF(Py_False);
107 | return Py_False;
108 | }
109 |
110 | PyObject *ret_obj = PyObject_CallObject(path_abspath, arguments);
111 | if (!ret_obj) {
112 | Py_XDECREF(relpath);
113 | Py_XDECREF(import_name);
114 | Py_XDECREF(module);
115 | Py_XDECREF(path_abspath);
116 | Py_XDECREF(arguments);
117 |
118 | Py_XINCREF(Py_False);
119 | return false;
120 | }
121 |
122 | // Clean up
123 | Py_XDECREF(relpath);
124 | Py_XDECREF(import_name);
125 | Py_XDECREF(module);
126 | Py_XDECREF(path_abspath);
127 | Py_XDECREF(arguments);
128 |
129 | return ret_obj;
130 | }
--------------------------------------------------------------------------------
/module/py_utils.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #ifdef __cplusplus
6 | extern "C" {
7 | #endif
8 |
9 | /**
10 | * File with some utilities for zroya module.
11 | */
12 |
13 | /// Call python os.path.isfile to ensure file 'file_name' exists.
14 | bool file_exists(PyObject *file_name);
15 |
16 | /// Call Python function os.path.abspath to get absolute path from 'relpath'.
17 | /// Returns Py_False on error.
18 | PyObject *abspath(PyObject *relpath);
19 |
20 | #ifdef __cplusplus
21 | }
22 | #endif
--------------------------------------------------------------------------------
/module/utils.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #include "utils.h"
7 |
8 | std::wstring zroya::convert(const char* text) {
9 | static std::wstring_convert> converter;
10 | return std::wstring(converter.from_bytes(text));
11 | }
12 |
13 | std::wstring zroya::convert(const std::string &text) {
14 | std::wostringstream convert;
15 | convert << text.c_str();
16 | return std::wstring(convert.str());
17 | }
18 |
19 | std::string zroya::random_string(int max_length) {
20 |
21 | std::string possible_characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
22 | std::random_device rd;
23 | std::mt19937 engine(rd());
24 | std::uniform_int_distribution<> dist(0, possible_characters.size() - 1);
25 | std::string ret = "";
26 |
27 | for (int i = 0; i < max_length; i++) {
28 | int random_index = dist(engine); //get index between 0 and possible_characters.size()-1
29 | ret += possible_characters[random_index];
30 | }
31 |
32 | return ret;
33 | }
--------------------------------------------------------------------------------
/module/utils.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | namespace zroya {
5 |
6 | /**
7 | * Convert const char* to std::wstring.
8 | */
9 | std::wstring convert(const char* text);
10 |
11 | /**
12 | * Convert std::string to std::wstring.
13 | */
14 | std::wstring convert(const std::string &text);
15 |
16 | /**
17 | * Generate random string of selected length.
18 | */
19 | std::string random_string(int max_length);
20 |
21 | }
--------------------------------------------------------------------------------
/module/wintoastlib.h:
--------------------------------------------------------------------------------
1 | #ifndef WINTOASTLIB_H
2 | #define WINTOASTLIB_H
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | using namespace Microsoft::WRL;
22 | using namespace ABI::Windows::Data::Xml::Dom;
23 | using namespace ABI::Windows::Foundation;
24 | using namespace ABI::Windows::UI::Notifications;
25 | using namespace Windows::Foundation;
26 |
27 | #define DEFAULT_SHELL_LINKS_PATH L"\\Microsoft\\Windows\\Start Menu\\Programs\\"
28 | #define DEFAULT_LINK_FORMAT L".lnk"
29 | namespace WinToastLib {
30 |
31 | class IWinToastHandler {
32 | public:
33 | enum WinToastDismissalReason {
34 | UserCanceled = ToastDismissalReason::ToastDismissalReason_UserCanceled,
35 | ApplicationHidden = ToastDismissalReason::ToastDismissalReason_ApplicationHidden,
36 | TimedOut = ToastDismissalReason::ToastDismissalReason_TimedOut
37 | };
38 | virtual void toastActivated(INT64 notificationID) const = 0;
39 | virtual void toastActivated(int actionIndex, INT64 notificationID) const = 0;
40 | virtual void toastDismissed(WinToastDismissalReason state, INT64 notificationID) const = 0;
41 | virtual void toastFailed(INT64 notificationID) const = 0;
42 | };
43 |
44 | class WinToastTemplate {
45 | public:
46 | enum AudioOption { Default = 0, Silent = 1, Loop = 2 };
47 | enum TextField { FirstLine = 0, SecondLine, ThirdLine };
48 | enum WinToastTemplateType {
49 | ImageAndText01 = ToastTemplateType::ToastTemplateType_ToastImageAndText01,
50 | ImageAndText02 = ToastTemplateType::ToastTemplateType_ToastImageAndText02,
51 | ImageAndText03 = ToastTemplateType::ToastTemplateType_ToastImageAndText03,
52 | ImageAndText04 = ToastTemplateType::ToastTemplateType_ToastImageAndText04,
53 | Text01 = ToastTemplateType::ToastTemplateType_ToastText01,
54 | Text02 = ToastTemplateType::ToastTemplateType_ToastText02,
55 | Text03 = ToastTemplateType::ToastTemplateType_ToastText03,
56 | Text04 = ToastTemplateType::ToastTemplateType_ToastText04,
57 | WinToastTemplateTypeCount
58 | };
59 |
60 | WinToastTemplate(_In_ WinToastTemplateType type = ImageAndText02);
61 | ~WinToastTemplate();
62 |
63 | void setTextField(_In_ const std::wstring& txt, _In_ TextField pos);
64 | void setImagePath(_In_ const std::wstring& imgPath);
65 | void setAudioPath(_In_ const std::wstring& audioPath);
66 | void setAudioOption(_In_ const WinToastTemplate::AudioOption& audioOption);
67 | void setAttributionText(_In_ const std::wstring & attributionText);
68 | void addAction(_In_ const std::wstring& label);
69 | inline void setExpiration(_In_ INT64 millisecondsFromNow) { _expiration = millisecondsFromNow; }
70 | inline int textFieldsCount() const { return static_cast(_textFields.size()); }
71 | inline int actionsCount() const { return static_cast(_actions.size()); }
72 | inline bool hasImage() const { return _type < Text01; }
73 | inline std::vector textFields() const { return _textFields; }
74 | inline std::wstring textField(_In_ TextField pos) const { return _textFields[pos]; }
75 | inline std::wstring actionLabel(_In_ int pos) const { return _actions[pos]; }
76 | inline std::wstring imagePath() const { return _imagePath; }
77 | inline std::wstring audioPath() const { return _audioPath; }
78 | inline std::wstring attributionText() const { return _attributionText; }
79 | inline INT64 expiration() const { return _expiration; }
80 | inline WinToastTemplateType type() const { return _type; }
81 | inline WinToastTemplate::AudioOption audioOption() const { return _audioOption; }
82 |
83 | private:
84 | std::vector _textFields;
85 | std::wstring _imagePath;
86 | std::wstring _audioPath;
87 | std::vector _actions;
88 | INT64 _expiration;
89 | WinToastTemplateType _type;
90 | WinToastTemplate::AudioOption _audioOption = WinToastTemplate::AudioOption::Default;
91 | std::wstring _attributionText;
92 | };
93 |
94 | class WinToast {
95 | public:
96 | WinToast(void);
97 | virtual ~WinToast();
98 | static WinToast* instance();
99 | static bool isCompatible();
100 | static bool supportModernFeatures();
101 | static std::wstring configureAUMI(_In_ const std::wstring& companyName,
102 | _In_ const std::wstring& productName,
103 | _In_ const std::wstring& subProduct = std::wstring(),
104 | _In_ const std::wstring& versionInformation = std::wstring()
105 | );
106 | virtual bool initialize();
107 | virtual bool isInitialized() const { return _isInitialized; }
108 | virtual INT64 showToast(_In_ const WinToastTemplate& toast, _In_ IWinToastHandler* handler);
109 | virtual bool hideToast(_In_ INT64 id);
110 | virtual void clear();
111 | inline std::wstring appName() const { return _appName; }
112 | inline std::wstring appUserModelId() const { return _aumi; }
113 | void setAppUserModelId(_In_ const std::wstring& appName);
114 | void setAppName(_In_ const std::wstring& appName);
115 |
116 | enum ShortcutResult {
117 | SHORTCUT_UNCHANGED = 0,
118 | SHORTCUT_WAS_CHANGED = 1,
119 | SHORTCUT_WAS_CREATED = 2,
120 |
121 | SHORTCUT_MISSING_PARAMETERS = -1,
122 | SHORTCUT_INCOMPATIBLE_OS = -2,
123 | SHORTCUT_COM_INIT_FAILURE = -3,
124 | SHORTCUT_CREATE_FAILED = -4
125 | };
126 | virtual enum ShortcutResult createShortcut();
127 | protected:
128 | bool _isInitialized;
129 | bool _hasCoInitialized;
130 | std::wstring _appName;
131 | std::wstring _aumi;
132 | std::map> _buffer;
133 |
134 | HRESULT validateShellLinkHelper(_Out_ bool& wasChanged);
135 | HRESULT createShellLinkHelper();
136 | HRESULT setImageFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& path);
137 | HRESULT setAudioFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& path, _In_opt_ WinToastTemplate::AudioOption option = WinToastTemplate::AudioOption::Default);
138 | HRESULT setTextFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& text, _In_ int pos);
139 | HRESULT setAttributionTextFieldHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& text);
140 | HRESULT addActionHelper(_In_ IXmlDocument *xml, _In_ const std::wstring& action, _In_ const std::wstring& arguments);
141 | ComPtr notifier(_In_ bool* succeded) const;
142 | };
143 | }
144 | #endif // WINTOASTLIB_H
145 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | from shutil import rmtree
4 | from setuptools import setup, Extension, Command
5 | from setuptools.command.test import test
6 | from setuptools.command.build_ext import build_ext
7 | import generate_stubs
8 | import os
9 | import sys
10 |
11 | sys.path.append(os.path.abspath("./zroya/"))
12 |
13 | import version
14 |
15 | here = os.path.abspath(os.path.dirname(__file__))
16 |
17 | # Include path for _zroya module
18 | includes_list = ["./module"]
19 |
20 | # List of all *.cpp files in ./module directory
21 | sources_list = []
22 | for root, dirs, files in os.walk("./module"):
23 | for f in files:
24 | if os.path.splitext(f)[1] == ".cpp":
25 | sources_list.append(os.path.join(root, f))
26 |
27 | # Python C/CPP Api extension configuration
28 | ext_modules = [
29 | Extension("_zroya",
30 | sources=sources_list,
31 | include_dirs=includes_list
32 | )
33 | ]
34 |
35 |
36 | def discover_and_run_tests():
37 | import unittest
38 |
39 | # use the default shared TestLoader instance
40 | test_loader = unittest.defaultTestLoader
41 |
42 | # use the basic test runner that outputs to sys.stderr
43 | test_runner = unittest.TextTestRunner()
44 |
45 | # automatically discover all tests
46 | # NOTE: only works for python 2.7 and later
47 | test_suite = test_loader.discover( os.path.join(here, "tests"))
48 |
49 | # run the test suite
50 | test_runner.run(test_suite)
51 |
52 |
53 | def find_pyd_file():
54 | """
55 | Return path to .pyd after successful build command.
56 | :return: Path to .pyd file or None.
57 | """
58 |
59 | if not os.path.isdir("./build"):
60 | raise NotADirectoryError
61 |
62 | for path, dirs, files in os.walk("./build"):
63 | for file_name in files:
64 | file_name_parts = os.path.splitext(file_name)
65 | if file_name_parts[1] == ".pyd":
66 | return path
67 | return None
68 |
69 |
70 | class StubsCommand(build_ext):
71 |
72 | description = "Generate python stubs with documentation from C code."
73 |
74 | def run(self):
75 | build_ext.run(self)
76 |
77 | print("running stubs")
78 | # Generate .pyd file for this module
79 | generate_stubs.GenerateStubFile(find_pyd_file(), os.path.abspath("./zroya/"))
80 |
81 |
82 | class DocumentationCommand(Command):
83 |
84 | description = "Generate documentation from /docs_source directory."
85 | user_options = []
86 |
87 | def initialize_options(self):
88 | pass
89 |
90 | def finalize_options(self):
91 | pass
92 |
93 | def run(self):
94 | os.system("{} {}".format(os.path.join(os.path.abspath("./docs_source/sphinx/"), "make.bat"), "html"))
95 | sys.exit()
96 |
97 |
98 | class UploadCommand(Command):
99 |
100 | description = 'Build and publish the package.'
101 | user_options = [
102 | (
103 | "pypi=",
104 | "p",
105 | "Set PyPi repository in which should be distribution uploaded. Valid values are 'test' for TestPyPi or \
106 | 'standard' for regular PyPi."
107 | )
108 | ]
109 |
110 | @staticmethod
111 | def status(s):
112 | """Prints things in bold."""
113 | print('\033[1m{0}\033[0m'.format(s))
114 |
115 | def initialize_options(self):
116 | self.pypi = "standard"
117 |
118 | def finalize_options(self):
119 | assert(self.pypi == "standard" or self.pypi == "test")
120 |
121 | def run(self):
122 | try:
123 | self.status('Removing previous builds…')
124 | rmtree(os.path.join(here, 'dist'))
125 | except OSError:
126 | pass
127 |
128 | self.status('Building Source and Wheel (universal) distribution…')
129 | os.system('{0} setup.py sdist bdist_wheel --universal'.format(sys.executable))
130 |
131 | self.status('Uploading the package to PyPi via Twine…')
132 |
133 | if self.pypi == "standard":
134 | os.system('twine upload --repository pypi dist/*')
135 | else:
136 | os.system('twine upload --repository testpypi dist/*')
137 |
138 | sys.exit()
139 |
140 |
141 | class DiscoverTest(test):
142 | """
143 | Discover and run tests.
144 | See: https://stackoverflow.com/questions/17001010/how-to-run-unittest-discover-from-python-setup-py-test
145 | """
146 |
147 | description = "Run tests in /tests folder with unittest."
148 |
149 | def finalize_options(self):
150 | test.finalize_options(self)
151 | self.test_args = []
152 | self.test_suite = True
153 |
154 | def run_tests(self):
155 | discover_and_run_tests()
156 |
157 |
158 | setup(name='zroya',
159 | version=version.__version__,
160 | description='Python library for creating native Windows notifications.',
161 | long_description=open("README.md").read(),
162 |
163 | author='Jan Malčák',
164 | author_email='looorin@gmail.com',
165 |
166 | license='MIT',
167 | url='https://malja.github.io/zroya',
168 |
169 | keywords=["notifications", "windows", "toast"],
170 | classifiers=[
171 | "Development Status :: 4 - Beta",
172 | "Environment :: Win32 (MS Windows)",
173 | "License :: OSI Approved :: MIT License",
174 | "Operating System :: Microsoft :: Windows",
175 | "Programming Language :: C",
176 | "Programming Language :: C++",
177 | "Programming Language :: Python :: 3",
178 | "Topic :: Software Development :: User Interfaces"
179 | ],
180 |
181 | ext_modules=ext_modules,
182 | test_suite="tests",
183 | packages=["zroya"],
184 | cmdclass={
185 | "stubs": StubsCommand,
186 | 'upload': UploadCommand,
187 | "docs": DocumentationCommand,
188 | "test": DiscoverTest,
189 | }
190 | )
191 |
--------------------------------------------------------------------------------
/tests/files/Readme.txt:
--------------------------------------------------------------------------------
1 | Follows list of all used files and link to their author. Thank you for sharing them ;)
2 |
3 | https://www.iconfinder.com/iconsets/essential-app-2
4 | - image.png
5 |
--------------------------------------------------------------------------------
/tests/files/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/malja/zroya/41830133a54528e9cd9ef43d9637a576ac849c11/tests/files/image.png
--------------------------------------------------------------------------------
/tests/test_actions.py:
--------------------------------------------------------------------------------
1 | import zroya
2 | import time
3 | import unittest
4 |
5 |
6 | def action_handler(notification_index, action_index):
7 | """
8 | This is a callback function for onAction event. It is called when user clicks on an action button attached to the
9 | notification.
10 |
11 | :param notification_index: Index of notification in which event occurred.
12 | :param action_index: Index of clicked action. Indexes start from zero (first action) and increase as you add more
13 | actions.
14 | """
15 |
16 | print("Notification with ID={} was activated. User clicked on action with index={}.".format(
17 | notification_index, action_index
18 | ))
19 |
20 |
21 | class TestTemplateActions(unittest.TestCase):
22 |
23 | def test_basic_action_handler(self):
24 |
25 | # Make sure zroya is initialized
26 | status = zroya.init(app_name="a", company_name="b", product_name="c", sub_product="d", version="e")
27 |
28 | self.assertTrue(status)
29 |
30 | # Create a template with two lines of text
31 | template = zroya.Template(zroya.TemplateType.Text1)
32 |
33 | self.assertIsInstance(template, zroya.Template)
34 |
35 | # Add text to it
36 | template.setFirstLine("My first line is there")
37 | template.setSecondLine("My second line is super catchy.")
38 |
39 | # Add actions
40 | first_action_index = template.addAction("Click me!")
41 | second_action_index = template.addAction("Don't click me!")
42 |
43 | self.assertEqual(first_action_index, 0)
44 | self.assertEqual(second_action_index, 1)
45 |
46 | print("Index first index={}, second index={}".format(first_action_index, second_action_index))
47 |
48 | # Create a notification with on_action callback attached.
49 | status = zroya.show(template, on_action=action_handler)
50 |
51 | self.assertTrue(status)
52 |
53 | # Make sure application runs for a while
54 | time.sleep(5)
55 |
56 | if __name__ == "__main__":
57 | unittest.main()
58 |
--------------------------------------------------------------------------------
/tests/test_callbacks.py:
--------------------------------------------------------------------------------
1 | import zroya
2 | import time
3 |
4 | def onclick(data):
5 | print("Onclick event zroya handler {}".format(data))
6 |
7 | def ondismiss(data, reason):
8 | print("Dismiss event zroya handler {}, reason {}".format(data, reason))
9 | print(reason == zroya.DismissReason.User)
10 |
11 | zroya.init("zroya", "a", "b", "c", "d")
12 |
13 | t = zroya.Template(zroya.TemplateType.Text1)
14 | t.setFirstLine("Ahoj")
15 |
16 |
17 | d = zroya.show(t, on_click=onclick, on_dismiss=ondismiss)
18 | print("Status: {}".format(d))
19 |
20 | time.sleep(2)
--------------------------------------------------------------------------------
/tests/test_hide.py:
--------------------------------------------------------------------------------
1 | import zroya
2 | import unittest
3 |
4 | class zroya_hide(unittest.TestCase):
5 |
6 | def test_NoParam(self):
7 | self.assertRaises(TypeError, lambda: zroya.hide())
8 |
9 | def test_BadType(self):
10 | self.assertRaises(ValueError, lambda: zroya.hide("test"))
11 |
12 | def test_NegativeId(self):
13 | self.assertRaises(ValueError, lambda: zroya.hide(-1))
14 |
15 | def test_ProperParam(self):
16 | t = zroya.Template(zroya.TemplateType.Text1)
17 | nid = zroya.show(t)
18 | self.assertTrue(zroya.hide(nid))
19 |
20 | def test_ProperParamKeywords(self):
21 | t = zroya.Template(zroya.TemplateType.Text1)
22 | notID = zroya.show(t)
23 | self.assertTrue(zroya.hide(nid=notID))
24 |
25 |
26 | if __name__ == "__main__":
27 | unittest.main()
28 |
--------------------------------------------------------------------------------
/tests/test_init.py:
--------------------------------------------------------------------------------
1 | import zroya
2 | import unittest
3 |
4 | class zroya_init(unittest.TestCase):
5 |
6 | def test_NoParam(self):
7 | self.assertRaises(ValueError, lambda: zroya.init())
8 |
9 | def test_FewParams(self):
10 | self.assertRaises(ValueError, lambda: zroya.init("a", "b"))
11 |
12 | def test_FewParamsKeywords(self):
13 | self.assertRaises(ValueError, lambda: zroya.init(app_name="a", company_name="b"))
14 |
15 | def test_EmptyParams(self):
16 | self.assertRaises(ValueError, lambda: zroya.init("", "", "", "", ""))
17 |
18 | def test_EmptyParamsKeywoards(self):
19 | self.assertRaises(ValueError, lambda: zroya.init(
20 | app_name="", company_name="", product_name="", sub_product="", version="")
21 | )
22 |
23 | def test_ProperInit(self):
24 | self.assertTrue(zroya.init("a", "b", "c", "d", "e"))
25 |
26 | def test_ProperInitKeywords(self):
27 | self.assertTrue(zroya.init(app_name="a", company_name="b", product_name="c", sub_product="d", version="e"))
28 |
29 | if __name__ == "__main__":
30 | unittest.main()
31 |
32 |
--------------------------------------------------------------------------------
/tests/test_show.py:
--------------------------------------------------------------------------------
1 | import zroya
2 | import unittest
3 | import time
4 |
5 |
6 | def on_click(id):
7 | pass
8 |
9 |
10 | class zroya_show(unittest.TestCase):
11 |
12 | def test_NoParam(self):
13 | self.assertRaises(TypeError, lambda: zroya.show())
14 |
15 | def test_FewParams(self):
16 | self.assertRaises(TypeError, lambda: zroya.show(on_click=on_click))
17 |
18 | def test_BadType(self):
19 | self.assertRaises(ValueError, lambda: zroya.show(None))
20 |
21 | def test_ProperParams(self):
22 | t = zroya.Template(zroya.TemplateType.ImageAndText1)
23 | self.assertIsInstance(zroya.show(t), int)
24 |
25 | if __name__ == "__main__":
26 | unittest.main()
27 |
--------------------------------------------------------------------------------
/tests/test_template.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | import os
3 | import zroya
4 |
5 | class zroya_Template(unittest.TestCase):
6 |
7 | ### CONSTRUCTOR
8 |
9 | def test_constructor_EmptyParams(self):
10 |
11 | self.assertRaises(ValueError, lambda: zroya.Template())
12 |
13 | def test_constructor_InvalidParams(self):
14 | self.assertRaises(ValueError, lambda: zroya.Template(-1))
15 |
16 | def test_constructor_InvalidParams2(self):
17 | self.assertRaises(ValueError, lambda: zroya.Template(50))
18 |
19 | def test_constructor_ProperParams(self):
20 | self.assertIsInstance(zroya.Template(zroya.TemplateType.Text1), zroya.Template)
21 |
22 | ### FIRST LINE
23 |
24 | def test_setFirstLine_EmptyParams(self):
25 | template = zroya.Template(zroya.TemplateType.Text1)
26 | self.assertRaises(TypeError, lambda: template.setFirstLine())
27 |
28 | def test_setFirstLine_InvalidParams(self):
29 | template = zroya.Template(zroya.TemplateType.Text1)
30 | self.assertRaises(TypeError, lambda: template.setFirstLine(-1))
31 |
32 | def test_setFirstLine_ProperParams(self):
33 | template = zroya.Template(zroya.TemplateType.Text1)
34 | self.assertTrue(template.setFirstLine("Test"))
35 |
36 | def test_getFirstLine_ProperParams(self):
37 | template = zroya.Template(zroya.TemplateType.Text1)
38 | template.setFirstLine("Test")
39 | self.assertEqual(template.getFirstLine(), "Test")
40 |
41 | ### SECOND LINE
42 |
43 | def test_setSecondLine_EmptyParams(self):
44 | template = zroya.Template(zroya.TemplateType.Text2)
45 | self.assertRaises(TypeError, lambda: template.setSecondLine())
46 |
47 | def test_setSecondLine_InvalidParams(self):
48 | template = zroya.Template(zroya.TemplateType.Text2)
49 | self.assertRaises(TypeError, lambda: template.setSecondLine(-1))
50 |
51 | def test_setSecondLine_ProperParams(self):
52 | template = zroya.Template(zroya.TemplateType.Text2)
53 | template.setFirstLine("Test")
54 | self.assertTrue(template.setSecondLine("Test Line 2"))
55 |
56 | def test_getSecondLine_ProperParams(self):
57 | template = zroya.Template(zroya.TemplateType.Text2)
58 | template.setFirstLine("Test")
59 | template.setSecondLine("Test Line 2")
60 | self.assertEqual(template.getSecondLine(), "Test Line 2")
61 |
62 | def test_setSecondLine_UnsuportedTemplateType(self):
63 | template = zroya.Template(zroya.TemplateType.Text1)
64 | self.assertFalse(template.setSecondLine("Test Line 2"))
65 |
66 | ### THIRD LINE
67 | def test_setThirdLine_EmptyParams(self):
68 | template = zroya.Template(zroya.TemplateType.Text4)
69 | self.assertRaises(TypeError, lambda: template.setThirdLine())
70 |
71 | def test_setThirdLine_InvalidParams(self):
72 | template = zroya.Template(zroya.TemplateType.Text4)
73 | self.assertRaises(TypeError, lambda: template.setThirdLine(-1))
74 |
75 | def test_setThirdLine_ProperParams(self):
76 | template = zroya.Template(zroya.TemplateType.Text4)
77 | template.setFirstLine("Test")
78 | template.setSecondLine("Test2")
79 | self.assertTrue(template.setThirdLine("Test Line 3"))
80 |
81 | def test_getThirdLine_ProperParams(self):
82 | template = zroya.Template(zroya.TemplateType.Text4)
83 | template.setThirdLine("Test Line 3")
84 | self.assertEqual(template.getThirdLine(), "Test Line 3")
85 |
86 | def test_thirdLine_UnsuportedTemplateType(self):
87 | template = zroya.Template(zroya.TemplateType.Text1)
88 | self.assertFalse(template.setThirdLine("Test Line 2"))
89 |
90 | ### Expire
91 |
92 | def test_setExpiration_InvalidParams(self):
93 | template = zroya.Template(zroya.TemplateType.Text1)
94 | self.assertRaises(TypeError, lambda: template.setExpiration("Test"))
95 |
96 | def test_setExpiration_EmptyParams(self):
97 | template = zroya.Template(zroya.TemplateType.Text1)
98 | self.assertRaises(TypeError, lambda: template.setExpiration())
99 |
100 | def test_setExpire_ProperParams(self):
101 | template = zroya.Template(zroya.TemplateType.Text1)
102 | self.assertTrue(template.setExpiration(10))
103 |
104 | def test_getExpiration_ProperParams(self):
105 | template = zroya.Template(zroya.TemplateType.Text1)
106 | template.setExpiration(10)
107 | self.assertEqual(template.getExpiration(), 10)
108 |
109 | ### AUDIO
110 |
111 | def test_setAudio_InvalidParams(self):
112 | template = zroya.Template(zroya.TemplateType.Text1)
113 | self.assertRaises(ValueError, lambda: template.setAudio(-1))
114 |
115 | def test_setAudio_EmptyParams(self):
116 | template = zroya.Template(zroya.TemplateType.Text1)
117 | self.assertRaises(TypeError, lambda: template.setAudio())
118 |
119 | def test_setAudio_ProperParams(self):
120 | template = zroya.Template(zroya.TemplateType.Text1)
121 | self.assertTrue(template.setAudio(zroya.Audio.Mail))
122 |
123 | def test_setAudio_ProperParams2(self):
124 | template = zroya.Template(zroya.TemplateType.Text1)
125 | self.assertTrue(template.setAudio(audio=zroya.Audio.Mail, mode=zroya.AudioMode.Loop))
126 |
127 | def test_getAudio_ProperParams(self):
128 | template = zroya.Template(zroya.TemplateType.Text1)
129 | template.setAudio(zroya.Audio.IM, zroya.AudioMode.Silence)
130 | self.assertEqual(template.getAudio(), zroya.Audio.IM)
131 |
132 | ### IMAGE
133 |
134 | def test_setImage_InvalidParams(self):
135 | template = zroya.Template(zroya.TemplateType.ImageAndText1)
136 | self.assertRaises(ValueError, lambda: template.setImage(-1))
137 |
138 | def test_setImage_EmptyParams(self):
139 | template = zroya.Template(zroya.TemplateType.ImageAndText1)
140 | self.assertRaises(TypeError, lambda: template.setImage())
141 |
142 | def test_setImage_FileDoesNotExist(self):
143 | template = zroya.Template(zroya.TemplateType.ImageAndText1)
144 | self.assertRaises(FileNotFoundError, lambda: template.setImage("./non_existing_file.png"))
145 |
146 | def test_setImage_ProperParams(self):
147 | template = zroya.Template(zroya.TemplateType.ImageAndText1)
148 | self.assertTrue(template.setImage("./tests/files/image.png"))
149 |
150 | def test_getImage_ProperParams(self):
151 | template = zroya.Template(zroya.TemplateType.ImageAndText1)
152 | path = os.path.abspath("./tests/files/image.png")
153 | template.setImage(path)
154 | self.assertEqual(template.getImage(), path)
155 |
--------------------------------------------------------------------------------
/zroya/__init__.py:
--------------------------------------------------------------------------------
1 | from _zroya import *
2 | from .template_enums import *
3 | from .dismiss_reason import *
4 | from .version import *
5 |
--------------------------------------------------------------------------------
/zroya/dismiss_reason.py:
--------------------------------------------------------------------------------
1 | class DismissReason(object):
2 |
3 | """
4 | This class represents a notification dismiss reason. It is passed to callback registered in on_dismiss parameter
5 | of :py:func:`zroya.show` function.
6 |
7 | You can print it to get a reason description or compare it with any of following attributes.
8 | """
9 |
10 | User = 0
11 | """
12 | The user dismissed the toast.
13 | """
14 |
15 | App = 1
16 | """
17 | The application hid the toast using :py:func:`zroya.hide`.
18 | """
19 |
20 | Expired = 2
21 | """
22 | The toast has expired.
23 | """
24 |
25 | def __init__(self, reason):
26 | """
27 | Create an instance of dismiss reason. Zroya uses this class to return a dismiss reason of notification back to
28 | zroya callback. For instance, when you create a notification with on_dismiss callback set:
29 |
30 | .. code-block:: python
31 |
32 | def myDismissCallback(notificationID, reason):
33 | print("Notification {} was dismissed by user. Reason: {}.".format(notificationID, reason))
34 |
35 | # t is an instance of zroya.Template
36 | zroya.show(t, on_dismiss = myCallback)
37 |
38 | this class will be used as a second parameter 'reason'. Since this is kind of C->Python bridge class, you
39 | will probably never create an instance of it.
40 |
41 | Args:
42 | reason (int): Integer representation of C dismiss reason.
43 | """
44 |
45 | self._reason = reason
46 |
47 | def __str__(self):
48 |
49 | # Make sure, numbers corresponds with actual dismiss reasons from Windows core:
50 | # Search ToastDismissalReason::ToastDismissalReason_UserCanceled in wintoastlib.h
51 |
52 | if self._reason == DismissReason.User:
53 | return "The user dismissed the toast."
54 | if self._reason == DismissReason.App:
55 | return "The application hid the toast using zroya.hide."
56 | if self._reason == DismissReason.Expired:
57 | return "The toast has expired."
58 |
59 | return "Unknown dismiss reason. If you are seeing this, please report it as a bug. Thank you."
60 |
61 | def __eq__(self, other):
62 | if isinstance(other, int):
63 | return other == self._reason
64 |
65 | return False
66 |
67 | def __ne__(self, other):
68 | return not other == self
69 |
--------------------------------------------------------------------------------
/zroya/template_enums.py:
--------------------------------------------------------------------------------
1 | from enum import IntEnum, Enum
2 |
3 |
4 | class AudioMode(IntEnum):
5 | """
6 | AudioMode is enumeration holds all valid parameters accepted by :py:meth:`zroya.Template.setAudio` method's `mode`
7 | parameter.
8 |
9 | Example:
10 | .. code-block:: python
11 |
12 | # t is an instance of zroya.Template
13 | t.setAudio( mode=zroya.AudioMode.Silence )
14 |
15 | """
16 |
17 | Default = 0
18 | """
19 | Selected audio will be played only once.
20 | """
21 |
22 | Silence = 1
23 | """
24 | No audio is played at all.
25 | """
26 |
27 | Loop = 2
28 | """
29 | Play audio in loop until it is moved to Action Center. This time may vary due to different user
30 | configuration.
31 | """
32 |
33 |
34 | class Audio(Enum):
35 | """
36 | Audio enumeration contains values for accepted values for `audio` parameter of :py:meth:`zroya.Template.setAudio`
37 | method.
38 |
39 | Example:
40 | .. code-block:: python
41 |
42 | # t is an instance of zroya.Template
43 | t.setAudio( audio=zroya.Audio.IM )
44 |
45 | """
46 |
47 | Default = "ms-winsoundevent:Notification.Default"
48 | """
49 | .. raw:: html
50 |
51 |
52 |
53 | """
54 |
55 | IM = "ms-winsoundevent:Notification.IM"
56 | """
57 | .. raw:: html
58 |
59 |
60 |
61 | """
62 |
63 | Mail = "ms-winsoundevent:Notification.Mail"
64 | """
65 | .. raw:: html
66 |
67 |
68 |
69 | """
70 |
71 | Reminder = "ms-winsoundevent:Notification.Reminder"
72 | """
73 | .. raw:: html
74 |
75 |
76 |
77 | """
78 |
79 | SMS = "ms-winsoundevent:Notification.SMS"
80 | Alarm = "ms-winsoundevent:Notification.Looping.Alarm"
81 | """
82 | .. raw:: html
83 |
84 |
85 |
86 | """
87 |
88 | Alarm2 = "ms-winsoundevent:Notification.Looping.Alarm2"
89 | """
90 | .. raw:: html
91 |
92 |
93 |
94 | """
95 |
96 | Alarm3 = "ms-winsoundevent:Notification.Looping.Alarm3"
97 | """
98 | .. raw:: html
99 |
100 |
101 |
102 | """
103 |
104 | Alarm4 = "ms-winsoundevent:Notification.Looping.Alarm4"
105 | """
106 | .. raw:: html
107 |
108 |
109 |
110 | """
111 |
112 | Alarm5 = "ms-winsoundevent:Notification.Looping.Alarm5"
113 | """
114 | .. raw:: html
115 |
116 |
117 |
118 | """
119 |
120 | Alarm6 = "ms-winsoundevent:Notification.Looping.Alarm6"
121 | """
122 | .. raw:: html
123 |
124 |
125 |
126 | """
127 |
128 | Alarm7 = "ms-winsoundevent:Notification.Looping.Alarm7"
129 | """
130 | .. raw:: html
131 |
132 |
133 |
134 | """
135 |
136 | Alarm8 = "ms-winsoundevent:Notification.Looping.Alarm8"
137 | """
138 | .. raw:: html
139 |
140 |
141 |
142 | """
143 |
144 | Alarm9 = "ms-winsoundevent:Notification.Looping.Alarm9"
145 | """
146 | .. raw:: html
147 |
148 |
149 |
150 | """
151 |
152 | Alarm10 = "ms-winsoundevent:Notification.Looping.Alarm10"
153 | """
154 | .. raw:: html
155 |
156 |
157 |
158 | """
159 |
160 | Call = "ms-winsoundevent:Notification.Looping.Call"
161 | """
162 | .. raw:: html
163 |
164 |
165 |
166 | """
167 |
168 | Call2 = "ms-winsoundevent:Notification.Looping.Call2"
169 | """
170 | .. raw:: html
171 |
172 |
173 |
174 | """
175 |
176 | Call3 = "ms-winsoundevent:Notification.Looping.Call3"
177 | """
178 | .. raw:: html
179 |
180 |
181 |
182 | """
183 |
184 | Call4 = "ms-winsoundevent:Notification.Looping.Call4"
185 | """
186 | .. raw:: html
187 |
188 |
189 |
190 | """
191 |
192 | Call5 = "ms-winsoundevent:Notification.Looping.Call5"
193 | """
194 | .. raw:: html
195 |
196 |
197 |
198 | """
199 |
200 | Call6 = "ms-winsoundevent:Notification.Looping.Call6"
201 | """
202 | .. raw:: html
203 |
204 |
205 |
206 | """
207 |
208 | Call7 = "ms-winsoundevent:Notification.Looping.Call7"
209 | """
210 | .. raw:: html
211 |
212 |
213 |
214 | """
215 |
216 | Call8 = "ms-winsoundevent:Notification.Looping.Call8"
217 | """
218 | .. raw:: html
219 |
220 |
221 |
222 | """
223 |
224 | Call9 = "ms-winsoundevent:Notification.Looping.Call9"
225 | """
226 | .. raw:: html
227 |
228 |
229 |
230 | """
231 |
232 | Call10 = "ms-winsoundevent:Notification.Looping.Call10"
233 | """
234 | .. raw:: html
235 |
236 |
237 |
238 | """
239 |
240 |
241 | class TemplateType(IntEnum):
242 | """
243 | All possible values for :py:class:`zroya.Template` constructor.
244 |
245 | Example:
246 | .. code-block:: python
247 |
248 | zroya.Template(zroya.TemplateType.ImageAndText2)
249 |
250 | """
251 |
252 | ImageAndText1 = 0
253 | """
254 | A large image and a single string wrapped across three lines of text.
255 | """
256 |
257 | ImageAndText2 = 1
258 | """
259 | A large image, one string of bold text on the first line, one string of regular text wrapped across the
260 | second and third lines.
261 | """
262 |
263 | ImageAndText3 = 2
264 | """
265 | A large image, one string of bold text wrapped across the first two lines, one string of regular text on
266 | the third line.
267 | """
268 |
269 | ImageAndText4 = 3
270 | """
271 | A large image, one string of bold text on the first line, one string of regular text on the second line,
272 | one string of regular text on the third line.
273 | """
274 |
275 | Text1 = 4
276 | """
277 | Single string wrapped across three lines of text.
278 | """
279 |
280 | Text2 = 5
281 | """
282 | One string of bold text on the first line, one string of regular text wrapped across the second and third
283 | lines.
284 | """
285 |
286 | Text3 = 6
287 | """
288 | One string of bold text wrapped across the first two lines, one string of regular text on the third line.
289 | """
290 |
291 | Text4 = 7
292 | """
293 | One string of bold text on the first line, one string of regular text on the second line, one string of
294 | regular text on the third line.
295 | """
296 |
--------------------------------------------------------------------------------
/zroya/version.py:
--------------------------------------------------------------------------------
1 | __version__ = "0.2.4"
2 | __release__ = "0.2.4"
3 |
--------------------------------------------------------------------------------