Passed
Push — master ( d0a81e...75aabf )
by Alexander
01:29
created

things3.things3_app.on_closed()   A

Complexity

Conditions 1

Size

Total Lines 14
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 13
nop 0
dl 0
loc 14
rs 9.75
c 0
b 0
f 0
1
#!/usr/bin/env python3
2
# -*- coding: utf-8 -*-
3
4
"""KanbanView (app) for Things 3."""
5
6
from __future__ import print_function
7
8
# pylint: disable=duplicate-code
9
__author__ = "Alexander Willner"
10
__copyright__ = "Copyright 2020 Alexander Willner"
11
__credits__ = ["Luc Beaulieu", "Alexander Willner"]
12
__license__ = "Apache License 2.0"
13
__version__ = "2.6.1.dev0"
14
__maintainer__ = "Alexander Willner"
15
__email__ = "[email protected]"
16
__status__ = "Development"
17
18
import sys
19
import signal
20
from os import system
21
from threading import Thread
22
import webview  # type: ignore
0 ignored issues
show
introduced by
Unable to import 'webview'
Loading history...
23
import objc  # type: ignore # pylint: disable=unused-import # noqa F401
0 ignored issues
show
introduced by
Unable to import 'objc'
Loading history...
24
import pkg_resources.py2_warn  # type: ignore # pylint: disable=unused-import # noqa F401
0 ignored issues
show
introduced by
third party import "import pkg_resources.py2_warn" should be placed before "import webview"
Loading history...
25
import things3.things3_api as things3_api
26
27
28
class Things3App():
29
    """App wrapper for simple read-only API for Things 3."""
30
31
    database = None
32
    FILE = "kanban.html"
33
    api = None
34
    api_thread = None
35
36
    def open_api(self):
37
        """Delay opening the browser."""
38
        print(f"Using database 2: {self.database}")
39
        self.api.main()
40
41
    def __init__(self, database=None):
42
        self.database = database
43
        self.api = things3_api.Things3API(database=self.database)
44
45
    def sigterm_handler(self, _signo, _stack_frame):
46
        """Make sure the server shuts down."""
47
        print("Sigterm...")
48
        self.api.flask_context.shutdown()
49
50
    def main(self):
51
        """Run the app."""
52
        # kill possible zombie processes; can't use psutil in py2app context
53
        system('lsof -nti:' + str(things3_api.Things3API.port) +
54
               ' | xargs kill -9')
55
56
        # Make sure the server shuts down
57
        signal.signal(signal.SIGTERM, self.sigterm_handler)
58
59
        print(f"Using database 1: {self.database}")
60
61
        window = webview.create_window(
62
            title='KanbanView',
63
            url=f'http://{things3_api.Things3API.host}:' +
64
            f'{things3_api.Things3API.port}/{self.FILE}',
65
            width=1280, height=650,
66
            min_size=(1280, 650),
67
            frameless=True)
68
        window.closed += on_closed
69
        self.api_thread = Thread(target=self.open_api)
70
71
        try:
72
            self.api_thread.start()
73
            webview.start()  # blocking
74
            self.api.flask_context.shutdown()
75
            self.api_thread.join()
76
        except KeyboardInterrupt:
77
            print("Shutting down...")
78
            self.api.flask_context.shutdown()
79
            self.api_thread.join()
80
            sys.exit(0)
81
82
83
def on_closed():
84
    """Show a hint to buy the app"""
85
    text = "Thank you for using KanbanView! " +\
86
        "If you enjoy using it, please consider buying the app."
87
    title = "KanbanView"
88
    url = "https://kanbanview.app"
89
    system("""osascript -e ' """ +
90
           f"""set dialog to (display dialog "{text}" """ +
91
           """buttons {"Buy", "Later"} default button 1 """ +
92
           f"""giving up after 10 """ +
93
           f"""with title "{title}" """ +
94
           f"""with icon POSIX file "resources/icon.icns")' """ +
95
           f"""-e 'if the button returned of the result is "Buy" then' """ +
96
           f"""-e 'do shell script "open {url}"' -e 'end if'""")
97
98
99
def main():
100
    """Main entry point for CLI installation"""
101
    Things3App().main()
102
103
104
if __name__ == "__main__":
105
    main()
106