~umang/indicator-stickynotes/trunk

24 by Umang Varma
Added .desktop and setup.py files.
1
#!/usr/bin/python3
2
# 
67 by Umang Varma
Release 0.3.2
3
# Copyright © 2012-2013 Umang Varma <umang.me@gmail.com>
24 by Umang Varma
Added .desktop and setup.py files.
4
# 
5
# This file is part of indicator-stickynotes.
6
# 
7
# indicator-stickynotes is free software: you can redistribute it and/or
8
# modify it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation, either version 3 of the License, or (at your
10
# option) any later version.
11
# 
12
# indicator-stickynotes is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14
# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15
# more details.
16
# 
17
# You should have received a copy of the GNU General Public License along with
18
# indicator-stickynotes.  If not, see <http://www.gnu.org/licenses/>.
19
20
from stickynotes.backend import Note, NoteSet
127 by Umang Varma
Prompt backup when error reading data file
21
from stickynotes.gui import *
62 by Umang Varma
Added -d parameter for development data file
22
import stickynotes.info
36 by Umang Varma
Start using python's locale for l10n
23
from stickynotes.info import MO_DIR, LOCALE_DOMAIN
32 by Umang Varma
Save more often so changes aren't lost
24
24 by Umang Varma
Added .desktop and setup.py files.
25
from gi.repository import Gtk, Gdk
26
from gi.repository import AppIndicator3 as appindicator
32 by Umang Varma
Save more often so changes aren't lost
27
30 by Umang Varma
Added ubuntu-mono themed icons.
28
import os.path
36 by Umang Varma
Start using python's locale for l10n
29
import locale
62 by Umang Varma
Added -d parameter for development data file
30
import argparse
36 by Umang Varma
Start using python's locale for l10n
31
from locale import gettext as _
32 by Umang Varma
Save more often so changes aren't lost
32
from functools import wraps
127 by Umang Varma
Prompt backup when error reading data file
33
from shutil import copyfile, SameFileError
32 by Umang Varma
Save more often so changes aren't lost
34
35
def save_required(f):
36
    """Wrapper for functions that require a save after execution"""
37
    @wraps(f)
38
    def _wrapper(self, *args, **kwargs):
39
        ret = f(self, *args, **kwargs)
40
        self.save()
41
        return ret
42
    return _wrapper
24 by Umang Varma
Added .desktop and setup.py files.
43
44
class IndicatorStickyNotes:
62 by Umang Varma
Added -d parameter for development data file
45
    def __init__(self, args = None):
46
        self.args = args
47
        # use development data file if requested
48
        isdev = args and args.d
127 by Umang Varma
Prompt backup when error reading data file
49
        self.data_file = stickynotes.info.DEBUG_SETTINGS_FILE if isdev \
50
                else stickynotes.info.SETTINGS_FILE
24 by Umang Varma
Added .desktop and setup.py files.
51
        # Initialize NoteSet
127 by Umang Varma
Prompt backup when error reading data file
52
        self.nset = NoteSet(StickyNote, self.data_file, self)
53
        try:
54
            self.nset.open()
55
        except FileNotFoundError:
56
            self.nset.load_fresh()
57
        except Exception as e:
58
            err = _("Error reading data file. Do you want to "
59
                "backup the current data?")
60
            winError = Gtk.MessageDialog(None, None, Gtk.MessageType.ERROR,
61
                    Gtk.ButtonsType.NONE, err)
62
            winError.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.REJECT,
63
                    _("Backup"), Gtk.ResponseType.ACCEPT)
64
            resp = winError.run()
65
            winError.hide()
66
            if resp == Gtk.ResponseType.ACCEPT:
67
                self.backup_datafile()
68
            winError.destroy()
69
            self.nset.load_fresh()
70
102 by Umang Varma
Don't initialize gui just before hiding window
71
        # If all notes were visible previously, show them now
58 by Umang Varma
Remember hidden state on startup
72
        if self.nset.properties.get("all_visible", True):
73
            self.nset.showall()
24 by Umang Varma
Added .desktop and setup.py files.
74
        # Create App Indicator
75
        self.ind = appindicator.Indicator.new(
76
                "Sticky Notes", "indicator-stickynotes",
77
                appindicator.IndicatorCategory.APPLICATION_STATUS)
30 by Umang Varma
Added ubuntu-mono themed icons.
78
        # Delete/modify the following file when distributing as a package
79
        self.ind.set_icon_theme_path(os.path.abspath(os.path.join(
80
            os.path.dirname(__file__), 'Icons')))
81
        self.ind.set_icon("indicator-stickynotes")
24 by Umang Varma
Added .desktop and setup.py files.
82
        self.ind.set_status(appindicator.IndicatorStatus.ACTIVE)
36 by Umang Varma
Start using python's locale for l10n
83
        self.ind.set_title(_("Sticky Notes"))
24 by Umang Varma
Added .desktop and setup.py files.
84
        # Create Menu
85
        self.menu = Gtk.Menu()
36 by Umang Varma
Start using python's locale for l10n
86
        self.mNewNote = Gtk.MenuItem(_("New Note"))
24 by Umang Varma
Added .desktop and setup.py files.
87
        self.menu.append(self.mNewNote)
88
        self.mNewNote.connect("activate", self.new_note, None)
89
        self.mNewNote.show()
90
91
        s = Gtk.SeparatorMenuItem.new()
92
        self.menu.append(s)
93
        s.show()
94
36 by Umang Varma
Start using python's locale for l10n
95
        self.mShowAll = Gtk.MenuItem(_("Show All"))
24 by Umang Varma
Added .desktop and setup.py files.
96
        self.menu.append(self.mShowAll)
97
        self.mShowAll.connect("activate", self.showall, None)
98
        self.mShowAll.show()
99
36 by Umang Varma
Start using python's locale for l10n
100
        self.mHideAll = Gtk.MenuItem(_("Hide All"))
24 by Umang Varma
Added .desktop and setup.py files.
101
        self.menu.append(self.mHideAll)
102
        self.mHideAll.connect("activate", self.hideall, None)
103
        self.mHideAll.show()
104
105
        s = Gtk.SeparatorMenuItem.new()
106
        self.menu.append(s)
107
        s.show()
108
36 by Umang Varma
Start using python's locale for l10n
109
        self.mLockAll = Gtk.MenuItem(_("Lock All"))
24 by Umang Varma
Added .desktop and setup.py files.
110
        self.menu.append(self.mLockAll)
111
        self.mLockAll.connect("activate", self.lockall, None)
112
        self.mLockAll.show()
113
36 by Umang Varma
Start using python's locale for l10n
114
        self.mUnlockAll = Gtk.MenuItem(_("Unlock All"))
24 by Umang Varma
Added .desktop and setup.py files.
115
        self.menu.append(self.mUnlockAll)
116
        self.mUnlockAll.connect("activate", self.unlockall, None)
117
        self.mUnlockAll.show()
118
119
        s = Gtk.SeparatorMenuItem.new()
120
        self.menu.append(s)
121
        s.show()
122
128 by Umang Varma
Implement import/export feature
123
        self.mExport = Gtk.MenuItem(_("Export Data"))
124
        self.menu.append(self.mExport)
125
        self.mExport.connect("activate", self.export_datafile, None)
126
        self.mExport.show()
127
128
        self.mImport = Gtk.MenuItem(_("Import Data"))
129
        self.menu.append(self.mImport)
130
        self.mImport.connect("activate", self.import_datafile, None)
131
        self.mImport.show()
132
133
        s = Gtk.SeparatorMenuItem.new()
134
        self.menu.append(s)
135
        s.show()
136
41 by Umang Varma
Added about dialog
137
        self.mAbout = Gtk.MenuItem(_("About"))
138
        self.menu.append(self.mAbout)
139
        self.mAbout.connect("activate", self.show_about, None)
140
        self.mAbout.show()
141
47 by Umang Varma
Added settings dialog, which controls bgcolor
142
        self.mSettings = Gtk.MenuItem(_("Settings"))
143
        self.menu.append(self.mSettings)
144
        self.mSettings.connect("activate", self.show_settings, None)
145
        self.mSettings.show()
146
41 by Umang Varma
Added about dialog
147
        s = Gtk.SeparatorMenuItem.new()
148
        self.menu.append(s)
149
        s.show()
150
36 by Umang Varma
Start using python's locale for l10n
151
        self.mQuit = Gtk.MenuItem(_("Quit"))
24 by Umang Varma
Added .desktop and setup.py files.
152
        self.menu.append(self.mQuit)
153
        self.mQuit.connect("activate", Gtk.main_quit, None)
154
        self.mQuit.show()
155
        # Connect Indicator to menu
156
        self.ind.set_menu(self.menu)
157
63 by Umang Varma
Middle-click toggles Show/Hide All.
158
        # Define secondary action (middle click)
159
        self.connect_secondary_activate()
160
24 by Umang Varma
Added .desktop and setup.py files.
161
    def new_note(self, *args):
162
        self.nset.new()
163
164
    def showall(self, *args):
165
        self.nset.showall(*args)
63 by Umang Varma
Middle-click toggles Show/Hide All.
166
        self.connect_secondary_activate()
24 by Umang Varma
Added .desktop and setup.py files.
167
168
    def hideall(self, *args):
169
        self.nset.hideall()
63 by Umang Varma
Middle-click toggles Show/Hide All.
170
        self.connect_secondary_activate()
171
172
    def connect_secondary_activate(self):
173
        """Define action of secondary action (middle click) depending
174
        on visibility state of notes."""
175
        if self.nset.properties["all_visible"] == True:
176
            self.ind.set_secondary_activate_target(self.mHideAll)
177
        else:
178
            self.ind.set_secondary_activate_target(self.mShowAll)
179
24 by Umang Varma
Added .desktop and setup.py files.
180
32 by Umang Varma
Save more often so changes aren't lost
181
    @save_required
24 by Umang Varma
Added .desktop and setup.py files.
182
    def lockall(self, *args):
183
        for note in self.nset.notes:
104 by Umang Varma
Fix some issues with gui = None
184
            note.set_locked_state(True)
24 by Umang Varma
Added .desktop and setup.py files.
185
        
32 by Umang Varma
Save more often so changes aren't lost
186
    @save_required
24 by Umang Varma
Added .desktop and setup.py files.
187
    def unlockall(self, *args):
188
        for note in self.nset.notes:
104 by Umang Varma
Fix some issues with gui = None
189
            note.set_locked_state(False)
24 by Umang Varma
Added .desktop and setup.py files.
190
128 by Umang Varma
Implement import/export feature
191
    def backup_datafile(self):
192
        winChoose = Gtk.FileChooserDialog(_("Export Data"), None,
193
                Gtk.FileChooserAction.SAVE, (Gtk.STOCK_CANCEL,
194
                    Gtk.ResponseType.CANCEL, Gtk.STOCK_SAVE,
195
                    Gtk.ResponseType.ACCEPT))
196
        winChoose.set_do_overwrite_confirmation(True)
197
        response = winChoose.run()
198
        backupfile = None
199
        if response == Gtk.ResponseType.ACCEPT:
200
            backupfile =  winChoose.get_filename()
201
        winChoose.destroy()
202
        if backupfile:
203
            try:
204
                copyfile(os.path.expanduser(self.data_file), backupfile)
205
            except SameFileError:
206
                err = _("Please choose a different "
207
                    "destination for the backup file.")
208
                winError = Gtk.MessageDialog(None, None,
209
                        Gtk.MessageType.ERROR, Gtk.ButtonsType.CLOSE, err)
210
                winError.run()
211
                winError.destroy()
212
                self.backup_datafile()
213
214
    def export_datafile(self, *args):
215
        self.backup_datafile()
216
217
    def import_datafile(self, *args):
218
        winChoose = Gtk.FileChooserDialog(_("Import Data"), None,
219
                Gtk.FileChooserAction.OPEN, (Gtk.STOCK_CANCEL,
220
                    Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN,
221
                    Gtk.ResponseType.ACCEPT))
222
        response = winChoose.run()
223
        backupfile = None
224
        if response == Gtk.ResponseType.ACCEPT:
225
            backupfile =  winChoose.get_filename()
226
        winChoose.destroy()
227
        if backupfile:
228
            try:
229
                with open(backupfile, encoding="utf-8") as fsock:
230
                    self.nset.merge(fsock.read())
231
            except Exception as e:
232
                err = _("Error importing data.")
233
                winError = Gtk.MessageDialog(None, None,
234
                        Gtk.MessageType.ERROR, Gtk.ButtonsType.CLOSE, err)
235
                winError.run()
236
                winError.destroy()
237
41 by Umang Varma
Added about dialog
238
    def show_about(self, *args):
239
        show_about_dialog()
240
47 by Umang Varma
Added settings dialog, which controls bgcolor
241
    def show_settings(self, *args):
242
        wSettings = SettingsDialog(self.nset)
243
24 by Umang Varma
Added .desktop and setup.py files.
244
    def save(self):
245
        self.nset.save()
246
247
248
def main():
36 by Umang Varma
Start using python's locale for l10n
249
    try:
250
        locale.setlocale(locale.LC_ALL, '')
251
    except:
252
        locale.setlocale(locale.LC_ALL, 'C')
253
    # If we're running from /usr, then .mo files are not in MO_DIR.
254
    if os.path.abspath(__file__)[:4] == '/usr':
255
        # Fallback to default
256
        locale_dir = None
257
    else:
39 by Umang Varma
Find locale_dir correctly
258
        locale_dir = os.path.join(os.path.dirname(__file__), MO_DIR)
36 by Umang Varma
Start using python's locale for l10n
259
    locale.bindtextdomain(LOCALE_DOMAIN, locale_dir)
260
    locale.textdomain(LOCALE_DOMAIN)
62 by Umang Varma
Added -d parameter for development data file
261
77 by Umang Varma
Updated pot file and some strings
262
    parser = argparse.ArgumentParser(description=_("Sticky Notes"))
62 by Umang Varma
Added -d parameter for development data file
263
    parser.add_argument("-d", action='store_true', help="use the development"
264
            " data file")
265
    args = parser.parse_args()
266
267
    indicator = IndicatorStickyNotes(args)
46 by Umang Varma
Notes can now change color.
268
    # Load global css for the first time.
269
    load_global_css()
24 by Umang Varma
Added .desktop and setup.py files.
270
    Gtk.main()
271
    indicator.save()
272
273
if __name__ == "__main__":
274
    main()