1# This file is part of the Frescobaldi project, http://www.frescobaldi.org/ 2# 3# Copyright (c) 2008 - 2014 by Wilbert Berendsen 4# 5# This program is free software; you can redistribute it and/or 6# modify it under the terms of the GNU General Public License 7# as published by the Free Software Foundation; either version 2 8# of the License, or (at your option) any later version. 9# 10# This program is distributed in the hope that it will be useful, 11# but WITHOUT ANY WARRANTY; without even the implied warranty of 12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13# GNU General Public License for more details. 14# 15# You should have received a copy of the GNU General Public License 16# along with this program; if not, write to the Free Software 17# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18# See http://www.gnu.org/licenses/ for more information. 19 20""" 21Store meta information about documents. 22""" 23 24 25import time 26 27from PyQt5.QtCore import QSettings, QUrl 28 29import app 30import plugin 31import document 32 33 34__all__ = ["info", "define"] 35 36 37# This dictionary store the default values: "name": [default, readfunc] 38_defaults = {} 39 40 41def info(doc): 42 """Returns a MetaInfo object for the Document.""" 43 return MetaInfo.instance(doc) 44 45 46def define(name, default, readfunc=None): 47 """Define a variable and its default value to be stored in the metainfo. 48 49 Should be defined before it is requested or set. 50 If readfunc is not given it defaults to a suitable function for bool or int types. 51 52 """ 53 if readfunc is None: 54 if isinstance(default, bool): 55 if default: 56 readfunc = lambda v: v not in ('false', False) 57 else: 58 readfunc = lambda v: v not in ('true', True) 59 elif isinstance(default, int): 60 readfunc = int 61 else: 62 readfunc = lambda v: v 63 _defaults[name] = [default, readfunc] 64 65 # read this value for already loaded metainfo items 66 for minfo in MetaInfo.instances(): 67 minfo.loadValue(name) 68 69 70class MetaInfo(plugin.DocumentPlugin): 71 """Stores meta-information for a Document.""" 72 def __init__(self, doc): 73 self.load() 74 if doc.__class__ == document.EditorDocument: 75 doc.loaded.connect(self.load, -999) # before all others 76 doc.closed.connect(self.save, 999) # after all others 77 78 def settingsGroup(self): 79 url = self.document().url() 80 if not url.isEmpty(): 81 s = app.settings('metainfo') 82 s.beginGroup(url.toString().replace('\\', '_').replace('/', '_')) 83 return s 84 85 def load(self): 86 s = self.settingsGroup() 87 for name in _defaults: 88 self.loadValue(name, s) 89 90 def loadValue(self, name, settings=None): 91 s = settings or self.settingsGroup() 92 default, readfunc = _defaults[name] 93 if s and QSettings().value("metainfo", True, bool): 94 self.__dict__[name] = readfunc(s.value(name, default)) 95 else: 96 self.__dict__[name] = default 97 98 def save(self): 99 s = self.settingsGroup() 100 if s: 101 s.setValue("time", time.time()) 102 for name in _defaults: 103 value = self.__dict__[name] 104 s.remove(name) if value == _defaults[name][0] else s.setValue(name, value) 105 106 107@app.aboutToQuit.connect 108def prune(): 109 """Prune old info.""" 110 s = app.settings('metainfo') 111 month_ago = time.time() - 31 * 24 * 3600 112 for key in s.childGroups(): 113 if s.value(key + "/time", 0.0, float) < month_ago: 114 s.remove(key) 115