def getStateList(order): global states global statekeys if not len(worldList): populateWorld() # else: # print len(worldList['c']) if order == 0: if not len(statekeys[0]): if config['debug'] > 3: printPretty([__name__,lineno(),worldList]) for state in worldList['s']: statename = None if len(state) > 0: statename = getStateName(state) if statename: if config['debug'] > 3: print "%s %s" % (lineno(),statename) statekeys[0][state] = statename pushLoc(state,statename) return statekeys[0] elif order == 1: if not len(statekeys[0]): getStateList(0) if not len(statekeys[1]): for state in statekeys[0]: statename = None if len(state) > 0: statename = getStateName(state) if statename: statekeys[1]["%s" % statename] = state return statekeys[1]
def saveRealm(fi): if not defaults.get("set",False): setDefaults() lines = [] if fi is None or fi == "": fi = "default" print "Saving realm %s"% fi fi = "realms/%s.rlm"% fi line = getline(fi,1) comp = {} matchlike = config.get("matchlike",False) if "likerealm" in line: values = [a.strip() for a in line.split('=')] comp = loadRealm("realms/%s.rlm"% values[1]) lines.append(line) write = False for key in config.keys(): if key in rlmkeys and config[key] != defaults.get(key): write = False if matchlike == 2: write = True elif matchlike == 1 and config.get(key) != comp.get(key): write = True elif matchlike == 0 and key in rlmsavekeys: write = True if write: lines.append("%s = %s\n" % (key,config[key])) try: f = open(os.path.abspath(fi), 'w') if config['debug'] > 0: printPretty(lines) f.writelines(lines) except IOError as e: print " Could not write configuration file: %s" % e finally: f.close()
def tabdestroyed(caller,fileid): """Deletes the person's fileid key from people dict so the person can be reloaded.""" global people try: del people[fileid] except KeyError: printPretty(people) raise
def tabdestroyed(caller, fileid): """Deletes the place's fileid key from places dict so the place can be reloaded.""" global cities try: del cities[fileid] except KeyError: printPretty(cities) raise
def listRealms(): rlist = os.listdir("realms/") olist = [] for r in rlist: if ".rlm" in r: olist.append(r[:-4]) if config['debug'] > 2: printPretty(olist) return olist
def askCityBox(parent): if parent == "?": parent = mainWin row = gtk.HBox() row.show() label = gtk.Label("Location:") label.set_width_chars(7) label.set_alignment(1,0.5) choices = backends.getCityList() loc = gtk.combo_box_new_text() loc.set_size_request(200,32) keys = [] i = 0 for key in sorted(choices.keys()): if choices.get(key) and choices[key][0] and choices[key][2]: loc.append_text("%s, %s" % (choices[key][0],choices[key][2])) keys.append(key) i += 1 askBox = None if len(keys) > 0: askbox = gtk.MessageDialog(parent,gtk.DIALOG_DESTROY_WITH_PARENT,gtk.MESSAGE_QUESTION,gtk.BUTTONS_OK_CANCEL) else: askbox = gtk.MessageDialog(parent,gtk.DIALOG_DESTROY_WITH_PARENT,gtk.MESSAGE_WARNING,gtk.BUTTONS_OK) if len(keys) > 0: askbox.set_markup("Choose a city:") label.show() row.pack_start(label,False,False,2) loc.show() row.pack_start(loc,True,True,2) else: askbox.format_secondary_markup("Please create at least one city and state before using this dialog.") askbox.vbox.pack_end(row,True,True,0) width, height = askbox.get_size() askbox.move((gtk.gdk.screen_width() / 2) - (width / 2),(gtk.gdk.screen_height() / 2) - (height / 2)) askbox.move((gtk.gdk.screen_width() / 2) - (width / 2),(gtk.gdk.screen_height() / 2) - (height / 2)) askbox.run() key = None if len(keys) > 0: key = loc.get_active_text() askbox.destroy() loc.destroy() loc = [False,None,None,None,None] lockeys = {} if key is not None and len(key) > 0: lockeys = backends.getCityList(1) key = lockeys.get(key,'N') lockeys = backends.getCityList() if config['debug'] > 0: print "new key: %s" % key print "%s (%s), %s (%s)" % (lockeys[key][0],key,lockeys[key][2],lockeys[key][1]) loc[1] = key loc[2] = lockeys[key][0] loc[3] = lockeys[key][1] loc[4] = lockeys[key][2] loc[0] = True if config['debug'] > 0: printPretty(loc) return loc
def activateInfoEntry(self,ar,alts, scroll, data, fileid, key, extra = 0, exargs = []): if config['debug'] > 4: printPretty("%s\n%s" % (data,[fileid,key,exargs])) cat = data.get("cat") path = [] # if cat in ['p','l','c']: path = [fileid,"info",key] for i in range(len(exargs)): path.append(exargs[i]) self.connect("focus-out-event", checkForChange,data,path,ar,alts) self.connect("activate", checkForChange,None,data,path,ar,alts) self.connect("focus-in-event",scrollOnTab,scroll)
def storyDefault(target,rd): global config global status s = {} s = myStories(rd) if s == {} or len(s) != 1 or config['defaultstory'] == False: return k = s.keys() printPretty(k) v = k[0] m = "Single-story Realm. Setting stories value to %s. To prevent this, use the story editor to add stories to the realm, or change the setting in the options dialog." % v status.push(0,m) print m target.set_text(v) return
def getInf(data,path,default = ""): """Returns the value of a key path (which must be a list) in the given data, a given default, or an empty string.""" end = len(path) - 1 if not data or end < 0: printPretty("Bad data to getInf: %s %s" % (data, path)) return default i = 0 while i < end: if config['debug'] > 5: printPretty(str(data) + '\n') if data.get(path[i]): if config['debug'] > 4: print "seeking %s in %s" % (path[i],data.keys()) data = data[path[i]] i += 1 else: return default value = default if default in [{},[]]: # expecting dict or list if config['debug'] > 4: print "expecting {}/[]" value = data.get(path[-1],default) else: # expecting string, numeric, etc, that should be part of a [value,bool] pair try: (value,mod) = data.get(path[-1],(default,False)) except ValueError as e: printPretty("getInf: (nonfatal) %s yields %s with error %s" % (path,data.get(path[-1],(default,False)),e),False) return value
def pushLoc(statefile,statename = "",cityfile = "",cityname = "",placefile = "",placename = ""): for f in [statefile,cityfile,placefile]: if f is None: f = "" if config['debug'] > 3: printPretty([statefile,cityfile,placefile]) if len(statefile) > 0: if statefile.find(".xml") > -1: statefile = statefile.split('.')[0] if not placeList.get(statefile): placeList[statefile] = {} if statename is not None and len(statename) > 0: placeList[statefile]['_name'] = statename if len(cityfile) > 0: if cityfile.find(".xml") > -1: cityfile = cityfile.split('.')[0] if not placeList[statefile].get(cityfile): placeList[statefile][cityfile] = {} if cityname is not None and len(cityname) > 0: placeList[statefile][cityfile]['_name'] = cityname if len(placefile) > 0: if placefile.find(".xml") > -1: placefile = placefile.split('.')[0] if len(placename) > 0 and len(placefile) > 0: placeList[statefile][cityfile][placefile] = placename elif len(placefile) > 0: print "Could not place ", printPretty([statefile,cityfile,placefile]) elif len(placefile) > 0: print "Could not place ", printPretty([statefile,cityfile,placefile])
def listThings(pretty): if pretty: printPretty(people) printPretty(places) printPretty(cities) printPretty(states) showConfig() else: print people print places print cities print states print config getPlaceList(pretty) return True
def saveXMLtree(tree,category,fileid): out = "" if config['debug'] > 6: printPretty(etree.tostring(tree),True,True) try: out = etree.tostring(tree,pretty_print=True) except TypeError: # for me, previous line results in "unexpected keyword argument 'pretty_print'" out = xmlout.prettyXML(tree) start = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<?xml-stylesheet type=\"text/xsl\" href=\"" start += os.path.join(config['xslurl'],"%s.xsl" % category) start += "\"?>\n<!DOCTYPE person SYSTEM \"%s%s.dtd\">\n" % (config['dtdurl'],category) finaloutput = start + out if config['debug'] > 0: print finaloutput fn = os.path.join(os.path.abspath(config['realmdir']),fileid + ".xml") try: with codecs.open(fn,'wU','UTF-8') as f: f.write(finaloutput) f.close() except IOError as e: message = "The file %s could not be saved: %s" % (fn,e) common.bsay("?",message) status.push(0,message) return False return True
def showCity(caller, fileid): if cities.get(fileid): printPretty(cities[fileid])
def populateWorld(): """Looks in the realmdir and makes a list of fileids the program can load. Makes worldList a tuple of lists. """ global config global worldList fn = os.path.join(config['realmdir'],"myrealm.cfg") persons = [] places = [] cities = [] states = [] orgs = [] # other data types. (found,fn) = common.findFile(lineno(),fn) if config['uselistfile'] and found: print " Loading worldList from file..." lines = [] try: with codecs.open(fn,'rU','utf-8') as conf: lines = conf.readlines() conf.close() except IOError as e: print " Could not open worldlist file: %s" % e exit(1) for line in lines: try: line = line.strip() if line: values = [x.strip() for x in line.split('=')] if values[0] == "persons": y = values[1] persons.extend(y.split(',')) elif values[0] == "places": y = values[1] places.extend(y.split(',')) elif values[0] == "cities": y = values[1] cities.extend(y.split(',')) elif values[0] == "states": y = values[1] states.extend(y.split(',')) elif values[0] == "orgs": y = values[1] orgs.extend(y.split(',')) elif values[0] == "person": persons.append(values[1]) elif values[0] == "place": places.append(values[1]) elif values[0] == "city": cities.append(values[1]) elif values[0] == "state": states.append(values[1]) elif values[0] == "org": orgs.append(values[1]) else: print "Unknown type %s found" % values[0] except Exception as e: print " There was an error in the configuration file: %s" % e # elif not found: # print " Fatal error. Realm directory %s does not exist! Exiting." % config['realmdir'] # exit(-1) else: print " Generating worldList from directory..." olist = os.listdir(config['realmdir']) nlist = [] ilist = [] for i in range(len(olist)): if re.search(r'.[Xx][Mm][Ll]$',olist[i]): ilist.append(os.path.splitext(olist[i])[0]) nlist.append(olist[i]) for i in range(len(nlist)): fn = os.path.join(config['realmdir'],nlist[i]) line = ""; match = -1; lno = 2 while match == -1 and lno < 6: line = getline(fn,lno) match = line.find("SYSTEM") lno += 1 match2 = line.find(".dtd") if match != -1 and match2 > match: match += 8 # trims 'SYSTEM "' line = line[match:match2] # trims '.dtd">\n' if "person" in line: persons.append(ilist[i]) elif "place" in line: places.append(ilist[i]) elif "city" in line: cities.append(ilist[i]) elif "state" in line: states.append(ilist[i]) elif "org" in line: orgs.append(ilist[i]) else: print "Unknown type %s found" % line if config['debug'] > 2: print "\nPersons: %s\nPlaces: %s\nCities: %s\nStates: %s\nOrgs: %s\n" % (persons,places,cities,states,orgs) worldList['p'] = persons worldList['l'] = places worldList['c'] = cities worldList['s'] = states worldList['o'] = orgs for key in worldList.keys(): if len(worldList[key]): if not len(worldList[key][0]): worldList[key] = [] for s in worldList['s']: pushLoc(s) getStateList(0) getCityList(0) if config['debug'] > 3: printPretty(worldList) printPretty(placeList)
def loadState(fileid): """Given an id (filename) matching an XML file in the appropriate directory, loads the tree from the file and pushes its data into a dictionary. """ dinf = {} root = etree.Element("state") text = None statename = "" statefile = "" # TODO: put this in a global variable, and make a function to populate it from the DTD. tags = ["name","start","scue","end","ecue","aspects","update"] for tag in tags: dinf[tag] = ["",False] dinf['cities'] = {} dinf['m'] = {} dinf['m']['events'] = {} dinf['aspects'] = {} if not idExists(fileid): status.push(0,"new state created... '%s'" % fileid) return dinf statefile = fileid fn = os.path.join(config['realmdir'],"%s.xml" % fileid) status.push(0,"loading state from XML... '%s'" % fn) try: with codecs.open(fn,'rU','utf-8') as f: tree = etree.parse(f) f.close() root = tree.getroot() except IOError as e: print "c: Could not open configuration file: %s" % e ir = 0 for i in range(len(root)): if root[i].tag is not None: if root[i].tag == "city": if len(root[i]) > 0: node = "" node = root[i].find("file") if node.text: node = node.text.strip() node = common.validateFileid(node) dinf['cities'][node] = {} for j in root[i]: if j.tag and j.text and j.tag != "file": dinf['cities'][node][j.tag] = [j.text.strip(),False] if config['debug'] > 3: printPretty(dinf['cities'][node]) else: if config['debug'] > 0: print "Invalid city tag:" for c in root[i]: print c.tag + ': ' + c.text, else: # no relat length if config['debug'] > 0: print "Empty city tag." elif root[i].tag == "events": if len(root[i]) > 0: nodes = root[i] for node in nodes: k = str(len(dinf['m']['events'])) dinf['m']['events'][k] = {} for j in node: if j.tag and j.text: dinf['m']['events'][k][j.tag] = [j.text.strip(),False] else: if config['debug'] > 0: print "Invalid milestone tag:" for c in node: print c.tag + ': ' + c.text, if config['debug'] > 3: printPretty(dinf['m']['events']) else: # no relat length if config['debug'] > 0: print "Empty milestone tag." elif root[i].tag == "aspects": if len(root[i]) > 0: nodes = root[i] for node in nodes: k = str(len(dinf['aspects'])) dinf['aspects'][k] = {} if node.tag and node.text: dinf['aspects'][k] = [node.text.strip(),False] else: if config['debug'] > 0: print "Invalid aspects tag:" print node.tag + ': ' + node.text, else: # no aspects length if config['debug'] > 0: print "Empty aspects tag." elif root[i].text is not None: dinf[root[i].tag] = [root[i].text.strip(), False] if config['debug'] > 2: print str(i) + " ", statename = dinf.get("name","") if len(statename) > 1: pushLoc(statefile,statename) return dinf
def showState(caller,fileid): if states.get(fileid): printPretty(states[fileid])
def saveState(fileid,data): """Given a filename, saves a state's values to an "id" XML file. """ global states info = data.get('info') fn = fileid + ".xml" state = etree.Element("state") # TODO: put this in a global variable, and make a function to populate it from the DTD. tags = ["name","start","scue","end","ecue","vital","polit","culture","history", "geography","econ","demo","events","cities","aspects","update"] for tag in tags: if tag == "cities": nodes = info.get("cities") if nodes is not None: for node in nodes.keys(): if nodes[node].get("name"): connected = etree.Element("city") value = info['cities'][node].get("name") if value is None: value = ['',False] etree.SubElement(connected,"name").text = value[0] value = node if value is None: value = '' etree.SubElement(connected,"file").text = value value = info['cities'][node].get("note") if value is not None and len(value[0]) > 0: etree.SubElement(connected,"note").text = value[0] state.append(connected) else: print "A required tag is missing from city %s." % node else: print "no cities found" elif tag == "events": nodes = info.get("m") nodes = nodes.get("events") if nodes is not None: events = etree.Element("events") for node in nodes.keys(): if nodes[node].get("event"): connected = etree.Element("mstone") value = info['m']['events'][node].get("event") if value is None: value = ['',False] etree.SubElement(connected,"event").text = value[0] value = info['m']['events'][node].get("date") if value is None: value = ['',False] etree.SubElement(connected,"date").text = value[0] events.append(connected) else: print "A required tag is missing from event %s." % node state.append(events) else: print "no events found" # 820 # elif tag == "aspects": nodes = info.get("aspects") if nodes is not None: aspects = etree.Element("aspects") for node in sorted(nodes.keys()): value = nodes[node] if value is None: value = ['',False] etree.SubElement(aspects,"text").text = value[0] state.append( aspects ) else: print "no aspects found" elif tag == "update": etree.SubElement(state,tag).text = common.skrTimeStamp(config['datestyle']) else: value = info.get(tag) if value is None: value = ['',False] etree.SubElement(state,tag).text = value[0] r = saveXMLtree(state,"state",fileid) if r: try: states[fileid]['changed'] = False except KeyError: printPretty(states) return r
def markChanged(self,cat,path,alts,counter): global config if path == str(path): path = [path] # prevents string from being processed as a long list self.modify_base(gtk.STATE_NORMAL,gtk.gdk.color_parse(config['altcolor'])) # change background for edited if self not in alts: alts.append(self) setRuletext(counter,len(alts)) end = len(path) value = ["",False] value[1] = True value[0] = self.get_text() root = None goforit = False if cat == 'p': global people root = people elif cat == 'l': global places root = places elif cat == 'c': global cities root = cities elif cat == 's': global states root = states elif cat == 'o': global orgs root = orgs elif cat == 'i': global items root = items else: print "ERR: Invalid category %s passed to markChanged." % cat if root: if config['debug'] > 6: printPretty(root) goforit = preRead(True,cat,path[:-1],end) if goforit: if end == 3: try: root[path[0]][path[1]][path[2]] = value except KeyError: print changeFail(path[2]) return elif end == 4: try: root[path[0]][path[1]][path[2]][path[3]] = value except KeyError: print changeFail(path[3]) return elif end == 5: try: root[path[0]][path[1]][path[2]][path[3]][path[4]] = value except KeyError: print changeFail(path[4]) return elif end == 6: try: root[path[0]][path[1]][path[2]][path[3]][path[4]][path[5]] = value except KeyError: print changeFail(path[5]) return elif end == 7: try: root[path[0]][path[1]][path[2]][path[3]][path[4]][path[5]][path[6]] = value except KeyError: print changeFail(path[6]) return else: say("Path too long: %s" % path) return root[path[0]]['changed'] = True if config['debug'] > 2: print "Value set: %s" % getInf(root.get(path[0]),path[1:]) else: printPretty("markChanged: Invalid path (%s)" % path) debugPath(root,path) return
def addMilestone(caller,scroll,ar,alts,target,data,fileid,side,key,boxwidth): i = 0 err = False if data: if data.get(side): if data[side].get(key): if not data[side][key].get("events"): data[side][key]["events"] = {} i = str(len(data[side][key]['events'])) data[side][key]['events'][i] = {} data[side][key]['events'][i]['date'] = ["",False] data[side][key]['events'][i]['event'] = ["",False] else: print "Could not find %s in record %s!" % (key,fileid) err = True else: x = "relations" if side == "info": x = "info" if config['debug'] > 0: printPretty("%s %s %s %s %s %s %s" % (caller,target,data,fileid,side,key,boxwidth)) print "Record %s has no %s!" % (fileid,x) err = True else: print "Could not find %s!" % fileid err = True if config['debug'] > 5: print str(target) if not err: rowmile = gtk.HBox() rowmile.show() blank = gtk.Label() blank.show() blank.set_width_chars(12) # blank.set_size_request(int(boxwidth * 0.20),10) rowmile.pack_start(blank,0,0,2) d = gtk.Entry() d.show() d.set_width_chars(12) d.set_text(getInf(data,[side,key,'events',i,'date'])) rowmile.pack_start(d,1,1,2) d.grab_focus() datebut = gtk.Button() datebut.show() image = gtk.Image() image.set_from_file("img/date.png") datebut.set_image(image) datebut.unset_flags(gtk.CAN_FOCUS) datebut.connect("clicked",dateChoose,d,data,[fileid,side,key,'events',i,'date']) rowmile.pack_start(datebut,0,0,2) e = gtk.Entry() e.show() e.set_width_chars(18) e.set_text(getInf(data,[side,key,'events',i,'event'])) if side == "relat": activateRelEntry(d,ar,alts,scroll,data,fileid,key,"date",i) activateRelEntry(e,ar,alts,scroll,data,fileid,key,"event",i) elif side == "info": extraargs = ["events",i,"date"] activateInfoEntry(d,ar,alts,scroll,data,fileid,key,len(extraargs),extraargs) extraargs[2] = "event" activateInfoEntry(e,ar,alts,scroll,data,fileid,key,len(extraargs),extraargs) rowmile.pack_start(e,1,1,2) target.pack_start(rowmile,0,0,1)
def showPerson(caller,fileid): if people.get(fileid): printPretty(people[fileid])
def getPlaceList(pretty): if pretty: printPretty(placeList) else: print placeList return True
def savePerson(fileid,data): """Given a filename, saves a person's values to an "id" XML file. """ global people info = data.get('info') rels = data.get('relat') fn = fileid + ".xml" person = etree.Element("person") # TODO: put this in a global variable, and make a function to populate it from the DTD. tags = ["commonname", "ctitle", "gname", "mname", "fname", "nname", "nameorder", "gender", "bday", "dday", "stories", "mention", "appear1ch", "appear1wr", "conflict", "leadrel", "bodytyp", "age", "skin", "eyes", "hair", "dmarks", "dress", "attposs", "asmell", "personality", "speech", "formocc", "currocc", "strength", "weak", "mole", "hobby", "misc", "ethnic", "origin", "backstory", "residence", "minchar", "talent", "abil", "sgoal", "other", "relat", "aspects", "update"] reltags = ["related", "relation", "file", "rtype", "events", "cat", "realm"] for tag in tags: if tag == "relat": if len(rels): for r in rels: if rels[r].get("cat") is None: rels[r]['cat'] = common.getCat(r) # Try to figure it out if rels[r].get("related") is not None and rels[r].get("relation") is not None and rels[r].get("rtype") is not None and rels[r].get("cat") is not None: connected = etree.Element("relat") for t in reltags: if rels[r].get(t): if t == "events": if len(rels[r]['events']): events = etree.Element("events") elist = rels[r]['events'].keys() chron = sorted(elist, key = lambda x: rels[r]['events'][x].get("date")) for e in chron: mstone = etree.Element("mstone") etree.SubElement(mstone,"date").text = rels[r]['events'][e].get("date",("",False))[0] etree.SubElement(mstone,"event").text = rels[r]['events'][e].get("event",("",False))[0] if rels[r]['events'][e].get("Type"): etree.SubElement(mstone,"type").text = rels[r]['events'][e].get("type")[0] events.append(mstone) connected.append(events) else: value = rels[r].get(t) if value is None: value = ['',False] etree.SubElement(connected,t).text = value[0] elif t == "file": value = [r,False] etree.SubElement(connected,t).text = value[0] person.append(connected) else: print "A required tag is missing from relation %s." % r, printPretty(rels[r]) else: print "no relations found" elif tag == "currocc" or tag == "formocc": if info[tag].get("pos"): occ = etree.Element(tag) value = info[tag].get("pos") if value is None: value = ['',False] etree.SubElement(occ,"pos").text = value[0] if info[tag].get("events"): if len(info[tag]['events']): events = etree.Element("events") elist = info[tag]['events'].keys() chron = sorted(elist, key = lambda x: info[tag]['events'][x].get("date")) for e in chron: mstone = etree.Element("mstone") etree.SubElement(mstone,"date").text = info[tag]['events'][e].get("date",("",False))[0] etree.SubElement(mstone,"event").text = info[tag]['events'][e].get("event",("",False))[0] if info[tag]['events'][e].get("Type"): etree.SubElement(mstone,"type").text = info[tag]['events'][e].get("type")[0] events.append(mstone) occ.append(events) person.append( occ ) # 820 # elif tag == "aspects": nodes = info.get("aspects") if nodes is not None: aspects = etree.Element("aspects") for node in sorted(nodes.keys()): value = nodes[node] if value is None: value = ['',False] etree.SubElement(aspects,"text").text = value[0] person.append( aspects ) else: print "no aspects found" elif tag == "update": etree.SubElement(person,tag).text = common.skrTimeStamp(config['datestyle']) else: value = info.get(tag) if value is None: value = ['',False] etree.SubElement(person,tag).text = value[0] saveXMLtree(person,"person",fileid) people[fileid]['changed'] = False return True
def showPlace(caller,fileid): if places.get(fileid): printPretty(places[fileid])