18
18
# indicator-stickynotes. If not, see <http://www.gnu.org/licenses/>.
20
20
from stickynotes.backend import Note, NoteSet
21
from stickynotes.gui import StickyNote
21
from stickynotes.gui import *
22
import stickynotes.info
22
23
from stickynotes.info import MO_DIR, LOCALE_DOMAIN
26
gi.require_version('Gtk', '3.0')
27
gi.require_version('GtkSource', '3.0')
28
gi.require_version('AppIndicator3', '0.1')
24
29
from gi.repository import Gtk, Gdk
25
30
from gi.repository import AppIndicator3 as appindicator
29
35
from locale import gettext as _
30
36
from functools import wraps
37
from shutil import copyfile, SameFileError
32
42
def save_required(f):
33
43
"""Wrapper for functions that require a save after execution"""
41
51
class IndicatorStickyNotes:
52
def __init__(self, args = None):
54
# use development data file if requested
55
isdev = args and args.d
56
self.data_file = stickynotes.info.DEBUG_SETTINGS_FILE if isdev \
57
else stickynotes.info.SETTINGS_FILE
43
58
# Initialize NoteSet
44
self.nset = NoteSet(StickyNote)
59
self.nset = NoteSet(StickyNote, self.data_file, self)
62
except FileNotFoundError:
63
self.nset.load_fresh()
64
except Exception as e:
65
err = _("Error reading data file. Do you want to "
66
"backup the current data?")
67
winError = Gtk.MessageDialog(None, None, Gtk.MessageType.ERROR,
68
Gtk.ButtonsType.NONE, err)
69
winError.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.REJECT,
70
_("Backup"), Gtk.ResponseType.ACCEPT)
71
winError.set_title(_("Indicator Stickynotes"))
74
if resp == Gtk.ResponseType.ACCEPT:
75
self.backup_datafile()
77
self.nset.load_fresh()
79
# If all notes were visible previously, show them now
80
if self.nset.properties.get("all_visible", True):
47
82
# Create App Indicator
48
83
self.ind = appindicator.Indicator.new(
49
84
"Sticky Notes", "indicator-stickynotes",
93
128
self.menu.append(s)
131
self.mExport = Gtk.MenuItem(_("Export Data"))
132
self.menu.append(self.mExport)
133
self.mExport.connect("activate", self.export_datafile, None)
136
self.mImport = Gtk.MenuItem(_("Import Data"))
137
self.menu.append(self.mImport)
138
self.mImport.connect("activate", self.import_datafile, None)
141
s = Gtk.SeparatorMenuItem.new()
145
self.mAbout = Gtk.MenuItem(_("About"))
146
self.menu.append(self.mAbout)
147
self.mAbout.connect("activate", self.show_about, None)
150
self.mSettings = Gtk.MenuItem(_("Settings"))
151
self.menu.append(self.mSettings)
152
self.mSettings.connect("activate", self.show_settings, None)
153
self.mSettings.show()
155
s = Gtk.SeparatorMenuItem.new()
96
159
self.mQuit = Gtk.MenuItem(_("Quit"))
97
160
self.menu.append(self.mQuit)
98
161
self.mQuit.connect("activate", Gtk.main_quit, None)
100
163
# Connect Indicator to menu
101
164
self.ind.set_menu(self.menu)
166
# Define secondary action (middle click)
167
self.connect_secondary_activate()
103
169
def new_note(self, *args):
106
172
def showall(self, *args):
107
173
self.nset.showall(*args)
174
self.connect_secondary_activate()
109
176
def hideall(self, *args):
110
177
self.nset.hideall()
178
self.connect_secondary_activate()
180
def connect_secondary_activate(self):
181
"""Define action of secondary action (middle click) depending
182
on visibility state of notes."""
183
if self.nset.properties["all_visible"] == True:
184
self.ind.set_secondary_activate_target(self.mHideAll)
186
self.ind.set_secondary_activate_target(self.mShowAll)
113
190
def lockall(self, *args):
114
191
for note in self.nset.notes:
115
note.gui.set_locked_state(True)
192
note.set_locked_state(True)
118
195
def unlockall(self, *args):
119
196
for note in self.nset.notes:
120
note.gui.set_locked_state(False)
197
note.set_locked_state(False)
199
def backup_datafile(self):
200
winChoose = Gtk.FileChooserDialog(_("Export Data"), None,
201
Gtk.FileChooserAction.SAVE, (Gtk.STOCK_CANCEL,
202
Gtk.ResponseType.CANCEL, Gtk.STOCK_SAVE,
203
Gtk.ResponseType.ACCEPT))
204
winChoose.set_do_overwrite_confirmation(True)
205
response = winChoose.run()
207
if response == Gtk.ResponseType.ACCEPT:
208
backupfile = winChoose.get_filename()
212
copyfile(os.path.expanduser(self.data_file), backupfile)
213
except SameFileError:
214
err = _("Please choose a different "
215
"destination for the backup file.")
216
winError = Gtk.MessageDialog(None, None,
217
Gtk.MessageType.ERROR, Gtk.ButtonsType.CLOSE, err)
220
self.backup_datafile()
222
def export_datafile(self, *args):
223
self.backup_datafile()
225
def import_datafile(self, *args):
226
winChoose = Gtk.FileChooserDialog(_("Import Data"), None,
227
Gtk.FileChooserAction.OPEN, (Gtk.STOCK_CANCEL,
228
Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN,
229
Gtk.ResponseType.ACCEPT))
230
response = winChoose.run()
232
if response == Gtk.ResponseType.ACCEPT:
233
backupfile = winChoose.get_filename()
237
with open(backupfile, encoding="utf-8") as fsock:
238
self.nset.merge(fsock.read())
239
except Exception as e:
240
err = _("Error importing data.")
241
winError = Gtk.MessageDialog(None, None,
242
Gtk.MessageType.ERROR, Gtk.ButtonsType.CLOSE, err)
246
def show_about(self, *args):
249
def show_settings(self, *args):
250
wSettings = SettingsDialog(self.nset)
256
# Avoid duplicate process
257
# From https://stackoverflow.com/questions/788411/check-to-see-if-python-script-is-running
258
procLock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
260
procLock.bind('\0' + 'indicator-stickynotes')
262
print('Indicator stickynotes already running.')
128
266
locale.setlocale(locale.LC_ALL, '')