Merge branches/gramps35 with trunk

svn: r20164
This commit is contained in:
Doug Blank 2012-07-31 20:49:19 +00:00
parent 3158247c90
commit 55685f32b6
31 changed files with 4161 additions and 67974 deletions

View File

@ -17,6 +17,8 @@
<script type="text/javascript" src="/styles/javascript/jquery-ui-1.7.2.custom.min.js"></script>
<script type="text/javascript" src="/styles/jhtmlarea/scripts/jHtmlArea-0.7.0.js"></script>
<link rel="Stylesheet" type="text/css" href="/styles/jhtmlarea/style/jHtmlArea.css" />
<script type="text/javascript" src="/styles/javascript/jquery.flexbox.min.js"></script>
<link type="text/css" rel="stylesheet" href="/styles/css/jquery.flexbox.css" />
{% endblock %}
<style type="text/css">
@ -239,8 +241,7 @@ function optClick(theOption) {
document.location.href=theOption;
}
function setHasData(classname, value)
{
function setHasData(classname, value) {
var elems = document.getElementsByTagName('*'), i;
for (i in elems) {
if((" " + elems[i].className + " ").indexOf(" " + classname + " ") > -1) {
@ -254,6 +255,18 @@ function setHasData(classname, value)
}
}
}
function setReturnValues() {
var elems = document.getElementsByTagName('*'), i;
for (i in elems) {
if ((" " + elems[i].name + " ").indexOf("_return ") > -1) {
var pos = (" " + elems[i].name + " ").indexOf("_return ");
var s = elems[i].name.substring(0, pos - 1);
var v = document.getElementsByName(s)[0];
elems[i].value = v.value;
}
}
}
//-->
</SCRIPT>
@ -273,7 +286,9 @@ function setHasData(classname, value)
-->
</STYLE>
</head>
<body onclick="hideMenus()" onload="if (document.getElementById('get_focus')) {document.getElementById('get_focus').focus();}">
<body onclick="hideMenus()"
onload="if (document.getElementById('get_focus')) {document.getElementById('get_focus').focus();}"
>
<div id="header" style="padding-top: 1em; background-position:0px -32px;">
<h1 id="SiteTitle" style="margin-left: 0em;">{% block heading %}{{sitename}}{% endblock %}</h1>
</div>
@ -348,11 +363,11 @@ function setHasData(classname, value)
</div>
<div class="grampsweb">
{% for message in messages %}
<font color="red">{{message}}</font>
<font color="red">{{message}}</font><br/>
{% endfor %}
{% if message %}
<div id="system_message" class="{{ message_type }}">
<font color="red">{{message}}</font>
<font color="red">{{message}}</font><br/>
</div>
{% endif %}
{% block content %}
@ -363,11 +378,12 @@ function setHasData(classname, value)
<div id="footer">
{% block footer %}
<p id="createdate">
<a href="http://www.gramps-project.org/wiki/index.php?title=Gramps-Connect">Gramps Connect, version {{gramps_version}}</a>.
<a href="http://www.gramps-project.org/wiki/index.php?title=Gramps-Connect">Gramps-Connect, version {{gramps_version}}</a>.
</p>
<p id="copyright">&copy; 2009-2012 <a href="http://www.gramps-project.org/">www.gramps-project.org</a>
</p>
{% endblock %}
</div>
</body>
</html>

View File

@ -17,12 +17,16 @@
{% for source in page.object_list %}
<tr class="{% cycle odd,even %}">
<td>{{ forloop.counter|row_count:page }}</td>
<td><a href="/{{view}}/{{source.handle|escape}}{{args}}" class="browsecell">
<td><a href="/{{view}}/{{source.handle|escape}}{{args}}" class="browsecell"
>
<span class="grampsid">[{{source.gramps_id}}]</span></a>
{% if user.is_authenticated %}
<td><a href="/{{view}}/{{source.handle|escape}}{{args}}" class="browsecell">{{source.title|escape|nbsp}}</a>
<td><a href="/{{view}}/{{source.handle|escape}}{{args}}" class="browsecell">{{source.pubinfo|nbsp}}</a>
<td><a href="/{{view}}/{{source.handle|escape}}{{args}}" class="browsecell">{{source.author|nbsp}}</a>
{% if user.is_authenticated or source.public %}
<td><a href="/{{view}}/{{source.handle|escape}}{{args}}" class="browsecell"
>{{source.title|escape|nbsp}}</a>
<td><a href="/{{view}}/{{source.handle|escape}}{{args}}" class="browsecell"
>{{source.pubinfo|nbsp}}</a>
<td><a href="/{{view}}/{{source.handle|escape}}{{args}}" class="browsecell"
>{{source.author|nbsp}}</a>
{% else %}
<td></td>
<td></td>

View File

@ -26,24 +26,49 @@
<div id="error">{{eventform.errors}}</div>
<hr>
{% endif %}
<form method="post">{% csrf_token %}
<form method="post" onsubmit="setReturnValues()">{% csrf_token %}
<tr>
<td class="ColumnAttribute">{{eventform.event_type.label}}:</td>
<td class="ColumnValue" id="data"> {% render eventform.event_type user action %}</td>
<td class="ColumnAttribute">{{eventform.text.label}}:</td>
<td class="ColumnValue" id="data">{% render eventform.text user action %}</td>
<td></td>
</tr>
<tr>
<td class="ColumnAttribute">Description:</td>
<td class="ColumnValue" id="data" colspan="3">{% render eventform.description user action %}</td>
<td></td>
</tr>
<tr>
<td class="ColumnAttribute">ID:</td>
<td class="ColumnValue" id="data" colspan="3">{% render eventform.gramps_id user action %}</td>
<td></td>
</tr>
<tr>
<td class="ColumnAttribute">Place:</td>
<td class="ColumnValue" id="data" colspan="3">{% render eventform.place user action %}</td>
<td class="ColumnValue" id="data" colspan="3">
{% if action != "view" %}
<script type="text/javascript">
$(function() {
$('#place').flexbox('/json/?field=place', {
watermark: 'Place',
width: 600,
paging: {
pageSize: 10
},
initialValue: '{{event.place.get_selection_string}}',
initialId: '{{event.place.handle}}'
});
});
// </script>
<div id="place"></div>
{% else %}
<a href="/place/?search={{event.place}}">{{event.place}}</a>
{% endif %}
</td>
<td>
<td class="ColumnValue" id="data" colspan="3">{% render eventform.private user action %}
</td>
</tr>
</table>
</div>
@ -82,6 +107,7 @@
{% if user.is_superuser %}
{% if action == "edit" %}
{% make_button "Cancel" "/event/%s" event.handle args %}
<input type="hidden" id="place_return" name="place_return" value=""/>
<input type="hidden" name="action" value="save"/>
<input type="hidden" name="search" value="{{search}}"/>
<input type="hidden" name="page" value="{{page}}"/>
@ -89,6 +115,7 @@
{% else %}
{% ifequal action "add" %}
{% make_button "Cancel" "/event/" args %}
<input type="hidden" id="place_return" name="place_return" value=""/>
<input type="hidden" name="action" value="create"/>
<input type="hidden" name="search" value="{{search}}"/>
<input type="hidden" name="page" value="{{page}}"/>

View File

@ -21,20 +21,17 @@
<td><a href="/{{view}}/{{event.handle|escape}}{{args}}" class="noThumb browsecell">
<span class="grampsid">[{{event.gramps_id}}]</span></a>
{% if user.is_authenticated %}
{% if user.is_authenticated or event.public %}
<td><a href="/{{view}}/{{event.handle|escape}}{{args}}" class="browsecell">{{event.event_type|nbsp}}</a>
<td><a href="/{{view}}/{{event.handle|escape}}{{args}}" class="browsecell">{{event.description|nbsp}}</a>
<td><a href="/{{view}}/{{event.handle|escape}}{{args}}" class="browsecell">{{event|date_as_text:user}}</a>
<td><a href="/{{view}}/{{event.handle|escape}}{{args}}" class="browsecell">{{event.place.title|nbsp}}</a>
{% else %}
<td>[Private]</td>
<td>[Private]</td>
<td>[Private]</td>
<td>[Private]</td>
<td><a href="/{{view}}/{{event.handle|escape}}{{args}}" class="browsecell">[Private]</a>
<td><a href="/{{view}}/{{event.handle|escape}}{{args}}" class="browsecell">[Private]</a>
<td><a href="/{{view}}/{{event.handle|escape}}{{args}}" class="browsecell">[Private]</a>
<td><a href="/{{view}}/{{event.handle|escape}}{{args}}" class="browsecell">[Private]</a>
{% endif %}
</tr>
{% endfor %}
</tbody>

View File

@ -16,14 +16,44 @@
<tbody>
{% for family in page.object_list %}
<tr class="{% cycle odd,even %}">
<td><a href="/{{view}}/{{family.handle|escape}}{{args}}" class="browsecell">{{ forloop.counter|row_count:page }}</a></td>
<td><a href="/{{view}}/{{family.handle|escape}}{{args}}" class="browsecell"><span class="grampsid">[{{family.gramps_id}}]</span></a>
<td><a href="/{{view}}/{{family.handle|escape}}{{args}}" class="browsecell">{{family.father|make_name:user|nbsp}}</a>
<td><a href="/{{view}}/{{family.handle|escape}}{{args}}" class="browsecell">{{family.mother|make_name:user|nbsp}}</a>
{% if user.is_authenticated %}
<td><a href="/{{view}}/{{family.handle|escape}}{{args}}" class="browsecell">{{family.family_rel_type|escape|nbsp}}</a>
<td><a href="/{{view}}/{{family.handle|escape}}{{args}}" class="browsecell"
{% if family.tags.all %}
style="color: {{family.tags.all.0.color|format_color}};"
{% endif %}
>{{ forloop.counter|row_count:page }}</a></td>
<td><a href="/{{view}}/{{family.handle|escape}}{{args}}" class="browsecell"
{% if family.tags.all %}
style="color: {{family.tags.all.0.color|format_color}};"
{% endif %}
><span class="grampsid">[{{family.gramps_id}}]</span></a>
<td><a href="/{{view}}/{{family.handle|escape}}{{args}}" class="browsecell"
{% if family.tags.all %}
style="color: {{family.tags.all.0.color|format_color}};"
{% endif %}
>{{family.father|make_name:user|nbsp}}</a>
<td><a href="/{{view}}/{{family.handle|escape}}{{args}}" class="browsecell"
{% if family.tags.all %}
style="color: {{family.tags.all.0.color|format_color}};"
{% endif %}
>{{family.mother|make_name:user|nbsp}}</a>
{% if user.is_authenticated or family.public %}
<td><a href="/{{view}}/{{family.handle|escape}}{{args}}" class="browsecell"
{% if family.tags.all %}
style="color: {{family.tags.all.0.color|format_color}};"
{% endif %}
>{{family.family_rel_type|escape|nbsp}}</a>
{% else %}
<td><a href="/{{view}}/{{family.handle|escape}}{{args}}" class="browsecell">[Private]</a>
<td><a href="/{{view}}/{{family.handle|escape}}{{args}}" class="browsecell"
{% if family.tags.all %}
style="color: {{family.tags.all.0.color|format_color}};"
{% endif %}
>
{% if not family.public %}
[Private]
{% else %}
{{family.family_rel_type}}
{% endif %}
</a>
{% endif %}
</tr>
{% endfor %}

View File

@ -28,7 +28,7 @@
<div id="error">{{familyform.errors}}</div>
<hr>
{% endif %}
<form method="post">{% csrf_token %}
<form method="post" onsubmit="setReturnValues()">{% csrf_token %}
<tr>
<th colspan="2">Father</th>
<th colspan="2">Mother</th>
@ -36,16 +36,55 @@
<tr>
<td class="ColumnAttribute">Name:</td>
{% if user.is_authenticated or father.probably_alive %}
<td class="ColumnValue" id="data">{% render familyform.father user action %}</td>
<td class="ColumnValue" id="data">
{% if action != "view" %}
<script type="text/javascript">
$(function() {
$('#father').flexbox('/json/?field=father', {
watermark: 'Father',
width: 300,
paging: {
pageSize: 10
},
initialValue: '{{family.father.get_selection_string}}',
initialId: '{{family.father.handle}}'
});
});
// </script>
<div id="father"></div>
{% else %}
<td class="ColumnValue" id="data">{{family.father|render_name:user}}</td>
{{family.father|render_name:user}}
{% endif %}
</td>
{% else %}
{{family.father|render_name:user}}
{% endif %}
</td>
<td class="ColumnAttribute">Name:</td>
{% if user.is_authenticated or family.mother.probably_alive %}
<td class="ColumnValue" id="data">{% render familyform.mother user action %}</td>
<td class="ColumnValue" id="data">
{% if action != "view" %}
<script type="text/javascript">
$(function() {
$('#mother').flexbox('/json/?field=mother', {
watermark: 'Mother',
width: 300,
paging: {
pageSize: 10
},
initialValue: '{{family.mother.get_selection_string}}',
initialId: '{{family.mother.handle}}'
});
});
// </script>
<div id="mother"></div>
{% else %}
<td class="ColumnValue" id="data">{{family.mother|render_name:user}}</td>
{{family.mother|render_name:user}}
{% endif %}
{% else %}
{{family.mother|render_name:user}}
{% endif %}
</td>
</tr>
{% if user.is_authenticated or not familyform.father.probably_alive %}
<tr>
@ -135,6 +174,8 @@
{% if user.is_superuser %}
{% if action == "edit" %}
{% make_button "Cancel" "/family/%s" family.handle args %}
<input type="hidden" id="father_return" name="father_return" value=""/>
<input type="hidden" id="mother_return" name="mother_return" value=""/>
<input type="hidden" name="action" value="save"/>
<input type="hidden" name="search" value="{{search}}"/>
<input type="hidden" name="page" value="{{page}}"/>
@ -142,6 +183,8 @@
{% else %}
{% ifequal action "add" %}
{% make_button "Cancel" "/family/" args %}
<input type="hidden" id="father_return" name="father_return" value=""/>
<input type="hidden" id="mother_return" name="mother_return" value=""/>
<input type="hidden" name="action" value="create"/>
<input type="hidden" name="search" value="{{search}}"/>
<input type="hidden" name="page" value="{{page}}"/>

View File

@ -16,11 +16,23 @@
{% for media in page.object_list %}
<tr class="{% cycle odd,even %}">
<td>{{ forloop.counter|row_count:page }}</td>
<td><a href="/{{view}}/{{media.handle|escape}}{{args}}" class="noThumb browsecell">
<td><a href="/{{view}}/{{media.handle|escape}}{{args}}" class="noThumb browsecell"
{% if media.tags.all %}
style="color: {{media.tags.all.0.color|format_color}};"
{% endif %}
>
<span class="grampsid">[{{media.gramps_id}}]</span></a>
{% if user.is_authenticated %}
<td><a href="/{{view}}/{{media.handle|escape}}{{args}}" class="browsecell">{{media.desc|escape}}</a>
<td><a href="/{{view}}/{{media.handle|escape}}{{args}}" class="browsecell">{{media.path|escape}}</a>
{% if user.is_authenticated or media.public %}
<td><a href="/{{view}}/{{media.handle|escape}}{{args}}" class="browsecell"
{% if media.tags.all %}
style="color: {{media.tags.all.0.color|format_color}};"
{% endif %}
>{{media.desc|escape}}</a>
<td><a href="/{{view}}/{{media.handle|escape}}{{args}}" class="browsecell"
{% if media.tags.all %}
style="color: {{media.tags.all.0.color|format_color}};"
{% endif %}
>{{media.path|escape}}</a>
{% else %}
<td></td>
<td></td>

View File

@ -16,14 +16,26 @@
{% for note in page.object_list %}
<tr class="{% cycle odd,even %}">
<td>{{ forloop.counter|row_count:page }}</td>
<td><a href="/{{view}}/{{note.handle|escape}}{{args}}" class="noThumb browsecell">
<td><a href="/{{view}}/{{note.handle|escape}}{{args}}" class="noThumb browsecell"
{% if note.tags.all %}
style="color: {{note.tags.all.0.color|format_color}};"
{% endif %}
>
<span class="grampsid">[{{note.gramps_id}}]</span></a>
{% if user.is_authenticated %}
<td><a href="/{{view}}/{{note.handle|escape}}{{args}}" class="browsecell">{{note.note_type|escape|nbsp}}</a>
<td><a href="/{{view}}/{{note.handle|escape}}{{args}}" class="browsecell">{{note.text|preview:70|nbsp}}</a>
{% if user.is_authenticated or note.public %}
<td><a href="/{{view}}/{{note.handle|escape}}{{args}}" class="browsecell"
{% if note.tags.all %}
style="color: {{note.tags.all.0.color|format_color}};"
{% endif %}
>{{note.note_type|escape|nbsp}}</a>
<td><a href="/{{view}}/{{note.handle|escape}}{{args}}" class="browsecell"
{% if note.tags.all %}
style="color: {{note.tags.all.0.color|format_color}};"
{% endif %}
>{{note.text|preview:70|nbsp}}</a>
{% else %}
<td></td>
<td></td>
<td>[Private]</td>
<td>[Private]</td>
{% endif %}
</tr>
{% endfor %}

View File

@ -16,16 +16,40 @@
</thead>
<tbody>
{% for name in page.object_list %}
<tr class="{% cycle odd,even %}">
<tr class="{% cycle odd,even %}" style="">
{% if name.person %}
<td><a href="{{name.person.handle}}/{{args}}" class="noThumb browsecell">{{ forloop.counter|row_count:page }}</a>
<td><a href="{{name.person.handle}}/{{args}}" class="noThumb browsecell"
{% if name.person.tags.all %}
style="color: {{name.person.tags.all.0.color|format_color}};"
{% endif %}
>{{ forloop.counter|row_count:page }}</a>
</td>
<td><a href="{{name.person.handle}}/{{args}}" class="noThumb browsecell">{{name|make_name:user}} &nbsp;</a>
<td><a href="{{name.person.handle}}/{{args}}" class="noThumb browsecell"
{% if name.person.tags.all %}
style="color: {{name.person.tags.all.0.color|format_color}};"
{% endif %}
>{{name|make_name:user}} &nbsp;</a>
</td>
<td><a href="{{name.person.handle}}/{{args}}" class="grampsid browsecell">[{{name.person.gramps_id}}]</a></td>
<td><a href="{{name.person.handle}}/{{args}}" class="noThumb browsecell">{{name.person.gender_type}} &nbsp;</a></td>
<td><a href="{{name.person.handle}}/{{args}}" class="noThumb browsecell">{{name.person.birth|date_as_text:user}} &nbsp;</a></td>
<td><a href="{{name.person.handle}}/{{args}}" class="noThumb browsecell">{{name.person.death|date_as_text:user}} &nbsp;</a></td>
<td><a href="{{name.person.handle}}/{{args}}" class="grampsid browsecell"
{% if name.person.tags.all %}
style="color: {{name.person.tags.all.0.color|format_color}};"
{% endif %}
>[{{name.person.gramps_id}}]</a></td>
<td><a href="{{name.person.handle}}/{{args}}" class="noThumb browsecell"
{% if name.person.tags.all %}
style="color: {{name.person.tags.all.0.color|format_color}};"
{% endif %}
>{{name.person.gender_type}} &nbsp;</a></td>
<td><a href="{{name.person.handle}}/{{args}}" class="noThumb browsecell"
{% if name.person.tags.all %}
style="color: {{name.person.tags.all.0.color|format_color}};"
{% endif %}
>{{name.person.birth|date_as_text:user}} &nbsp;</a></td>
<td><a href="{{name.person.handle}}/{{args}}" class="noThumb browsecell"
{% if name.person.tags.all %}
style="color: {{name.person.tags.all.0.color|format_color}};"
{% endif %}
>{{name.person.death|date_as_text:user}} &nbsp;</a></td>
{% endif %}
</tr>
{% endfor %}

View File

@ -60,7 +60,39 @@
<li class="ui-corner-top ui-state-default"><a class="tab-history" href="#tab-history">History</a></li>
</ul>
<div class="ui-tab-panel ui-widget-content ui-corner-bottom" id="tab-locations" style="background-color: #f4f0ec;">
<!-- place.location_set -->
<table class="infolist" style="width:90%;">
<tr>
<td class="ColumnAttribute">Street:</td>
<td class="Columnvalue" id="data" colspan="3"> FIXME </td>
</tr>
<tr>
<td class="ColumnAttribute">Locality:</td>
<td class="Columnvalue" id="data"> FIXME </td>
<td class="ColumnAttribute">Church parish:</td>
<td class="Columnvalue" id="data"> FIXME </td>
</tr>
<tr>
<td class="ColumnAttribute">City:</td>
<td class="Columnvalue" id="data"> FIXME </td>
<td class="ColumnAttribute">State:</td>
<td class="Columnvalue" id="data"> FIXME </td>
</tr>
<tr>
<td class="ColumnAttribute">County:</td>
<td class="Columnvalue" id="data"> FIXME </td>
<td class="ColumnAttribute">ZIP/Postal code:</td>
<td class="Columnvalue" id="data"> FIXME </td>
</tr>
<tr>
<td class="ColumnAttribute">Country:</td>
<td class="Columnvalue" id="data"> FIXME </td>
<td class="ColumnAttribute">Phone:</td>
<td class="Columnvalue" id="data"> FIXME </td>
</tr>
</table>
</div>
<div class="ui-tab-panel ui-widget-content ui-corner-bottom ui-tab-hide" id="tab-alternatelocations" style="background-color: #f4f0ec;">
{% location_table place user action "/location/$act/place/%s" place.handle %}

View File

@ -17,7 +17,7 @@
<td>{{ forloop.counter|row_count:page }}</td>
<td><a href="/{{view}}/{{place.handle|escape}}{{args}}" class="noThumb browsecell">
<span class="grampsid">[{{place.gramps_id}}]</span></a>
{% if user.is_authenticated %}
{% if user.is_authenticated or place.public %}
<td><a href="/{{view}}/{{place.handle|escape}}{{args}}" class="browsecell">{{place.title|escape|nbsp}}</a>
{% else %}
<td></td>

View File

@ -19,7 +19,7 @@
<td>{{ forloop.counter|row_count:page }}</td>
<td><a href="/{{view}}/{{repository.handle|escape}}{{args}}" class="noThumb browsecell">
<span class="grampsid">[{{repository.gramps_id}}]</span></a>
{% if user.is_authenticated %}
{% if user.is_authenticated or repository.public %}
<td><a href="/{{view}}/{{repository.handle|escape}}{{args}}" class="browsecell">{{repository.repository_type|escape|nbsp}}</a>
<td><a href="/{{view}}/{{repository.handle|escape}}{{args}}" class="browsecell">{{repository.name|escape|nbsp}}</a>
{% else %}

View File

@ -54,11 +54,11 @@
<div class="ui-tabs ui-widget ui-widget-content ui-corner-all" id="tabs" style="border: none;">
<ul class="ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all">
<li class="ui-state-default ui-corner-top ui-tabs-selected ui-state-active"><a class="tab-notes" href="#tab-notes">Note</a></li>
<li class="ui-corner-top ui-state-default"><a class="#tab-media" href="#tab-media">Media</a></li>
<li class="ui-corner-top ui-state-default"><a class="#tab-data" href="#tab-data">Data</a></li>
<li class="ui-corner-top ui-state-default"><a class="#tab-repositories" href="#tab-repositories">Repository</a></li>
<li class="ui-corner-top ui-state-default"><a class="#tab-references" href="#tab-references">Reference</a></li>
<li class="ui-corner-top ui-state-default"><a class="#tab-history" href="#tab-history">History</a></li>
<li class="ui-corner-top ui-state-default"><a class="tab-media" href="#tab-media">Media</a></li>
<li class="ui-corner-top ui-state-default"><a class="tab-data" href="#tab-data">Data</a></li>
<li class="ui-corner-top ui-state-default"><a class="tab-repositories" href="#tab-repositories">Repository</a></li>
<li class="ui-corner-top ui-state-default"><a class="tab-references" href="#tab-references">Reference</a></li>
<li class="ui-corner-top ui-state-default"><a class="tab-history" href="#tab-history">History</a></li>
</ul>
<div class="ui-tabs-panel ui-widget-content ui-corner-bottom" id="tab-notes" style="background-color: #f4f0ec;">
{% note_table source user action "/note/$act/source/%s" source.handle %}

View File

@ -19,7 +19,7 @@
<td>{{ forloop.counter|row_count:page }}</td>
<td><a href="/{{view}}/{{source.handle|escape}}{{args}}" class="noThumb browsecell">
<span class="grampsid">[{{source.gramps_id}}]</span></a>
{% if user.is_authenticated %}
{% if user.is_authenticated or source.public %}
<td><a href="/{{view}}/{{source.handle|escape}}{{args}}" class="browsecell">{{source.title|escape|nbsp}}</a>
<td><a href="/{{view}}/{{source.handle|escape}}{{args}}" class="browsecell">{{source.pubinfo|nbsp}}</a>
<td><a href="/{{view}}/{{source.handle|escape}}{{args}}" class="browsecell">{{source.author|nbsp}}</a>

65
src/gen/utils/svn.py Normal file
View File

@ -0,0 +1,65 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2012 Doug Blank <doug.blank@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id: $
"""
Based on the version from Django, a Python ORM.
"""
import re
import os
def get_svn_revision(path=None):
"""
Returns the SVN revision in the form SVN-XXXX,
where XXXX is the revision number.
Returns "" if anything goes wrong, such as an unexpected
format of internal SVN files.
If path is provided, it should be a directory whose SVN info you
want to inspect. If it's not provided, this will use the directory
where this file resides.
"""
rev = None
if path is None:
path = os.path.dirname(__file__)
entries_path = '%s/.svn/entries' % path
try:
entries = open(entries_path, 'r').read()
except IOError:
pass
else:
# Versions >= 7 of the entries file are flat text. The first line is
# the version number. The next set of digits after 'dir' is the revision
if re.match('(\d+)', entries):
rev_match = re.search('\d+\s+dir\s+(\d+)', entries)
if rev_match:
rev = rev_match.groups()[0]
# Older XML versions of the file specify revision as an attribute of
# the first entries node.
else:
from xml.dom import minidom
dom = minidom.parse(entries_path)
rev = dom.getElementsByTagName('entry')[0].getAttribute('revision')
if rev:
return u'SVN-%s' % rev
return u''

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1009 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,859 @@
/*!
* jQuery FlexBox $Version: 0.9.6 $
*
* Copyright (c) 2008-2010 Noah Heldman and Fairway Technologies (http://www.fairwaytech.com/flexbox)
* Licensed under Ms-PL (http://www.codeplex.com/flexbox/license)
*
* $Date: 2010-11-24 01:02:00 PM $
* $Rev: 0.9.6.1 $
*/
(function($) {
$.flexbox = function(div, o) {
// TODO: in straight type-ahead mode (showResults: false), if noMatchingResults, dropdown appears after new match
// TODO: consider having options.mode (select, which replaces html select; combobox; suggest; others?)
// TODO: on resize (at least when wrapping within a table), the arrow is pushed down to the next line
// TODO: check for boundary/value problems (such as minChars of -1) and alert them
// TODO: add options for advanced paging template
// TODO: general cleanup and refactoring, commenting
// TODO: detailed Exception handling, logging
// TODO: FF2, up arrow from bottom has erratic scroll behavior (if multiple flexboxes on page)
// TODO: FF2 (and maybe IE7): if maxVisibleRows == number of returned rows, height is a bit off (maybe set to auto?)
// TODO: escape key only works from input box (this might be okay)
// TODO: make .getJSON parameters (object and callback function) configurable (e.g. when calling yahoo image search)
// TODO: escape key reverts to previous value (FF only?) (is this a good thing?)
// TEST: highlightMatches uses the case of whatever you typed in to replace the match string, which can look funny
// TEST: handle pageDown and pageUp keys when scrolling through results
// TEST: allow client-side paging (return all data initially, set paging:{pageSize:#}, and ensure maxCacheBytes is > 0)
// TEST: accept json object as first parameter to flexbox instead of page source, and have it work like a combobox
// TEST: implement no results template
// TEST: implement noResultsText and class
// TEST: watermark color should be configurable (and so should default input color)
// TEST: exception handling and alerts for common mistakes
// TEST: first example should use defaults ONLY
// TEST: add property initialValue, so you can set it when the flexbox loads
// TEST: handle hidden input value for form submissions
// TEST: how can we allow programmatically setting the field value (and therefore hidden value). add jquery function?
// TEST: use pageSize parameter as threshold to switch from no paging to paging based on results
// TEST: if you type in an input value that matches the html, it might display html code (try typing "class" in the input box)
// TEST: don't require all paging subprops (let default override)
// TEST: when tabbing from one ffb to another, the previous ffb results flash...
// TEST: IE7: when two non-paging ffbs right after each other, with only a clear-both div between them, the bottom ffb jumps down when selecting a value, then jumps back up on mouseover
// TEST: FF2, make sure we scroll to top before showing results (maxVisibleRows only)
// TEST: if maxVisibleRows is hiding the value the user types in to the input, scroll to that value (is this even possible?)
// TEST: make sure caching supports multiple ffbs uniquely
// TEST: when entering a number in the paging input box, the results are displayed twice
var timeout = false, // hold timeout ID for suggestion results to appear
cache = [], // simple array with cacheData key values, MRU is the first element
cacheData = [], // associative array holding actual cached data
cacheSize = 0, // size of cache in bytes (cache up to o.maxCacheBytes bytes)
delim = '\u25CA', // use an obscure unicode character (lozenge) as the cache key delimiter
scrolling = false,
pageSize = o.paging && o.paging.pageSize ? o.paging.pageSize : 0,
retrievingRemoteData = false,
$div = $(div).css('position', 'relative').css('z-index', 0);
// The hiddenField MUST be appended to the div before the input, or IE7 does not shift the dropdown below the input field (it overlaps)
var $hdn = $('<input type="hidden"/>')
.attr('id', $div.attr('id') + '_hidden')
.attr('name', $div.attr('id'))
.val(o.initialId)
.appendTo($div);
var $input = $('<input/>')
.attr('id', $div.attr('id') + '_input')
.attr('autocomplete', 'off')
.addClass(o.inputClass)
.css('width', o.width + 'px')
.appendTo($div)
.click(function(e) {
if (o.watermark !== '' && this.value === o.watermark)
this.value = '';
else
this.select();
})
.focus(function(e) {
$(this).removeClass('watermark');
})
.blur(function(e) {
if (this.value === '') $hdn.val('');
setTimeout(function() { if (!$input.data('active')) hideResults(); }, 200);
})
.keydown(processKeyDown);
if (o.initialValue !== '')
$input.val(o.initialValue).removeClass('watermark');
else
$input.val(o.watermark).addClass('watermark');
var arrowWidth = 0;
if (o.showArrow && o.showResults) {
var arrowClick = function() {
if ($ctr.is(':visible')) {
hideResults();
}
else {
$input.focus();
if (o.watermark !== '' && $input.val() === o.watermark)
$input.val('');
else
$input.select();
if (timeout)
clearTimeout(timeout);
timeout = setTimeout(function() { flexbox(1, true, o.arrowQuery); }, o.queryDelay);
}
};
var $arrow = $('<span></span>')
.attr('id', $div.attr('id') + '_arrow')
.addClass(o.arrowClass)
.addClass('out')
.hover(function() {
$(this).removeClass('out').addClass('over');
}, function() {
$(this).removeClass('over').addClass('out');
})
.mousedown(function() {
$(this).removeClass('over').addClass('active');
})
.mouseup(function() {
$(this).removeClass('active').addClass('over');
})
.click(arrowClick)
.appendTo($div);
arrowWidth = $arrow.width();
$input.css('width', (o.width - arrowWidth) + 'px');
}
if (!o.allowInput) { o.selectFirstMatch = false; $input.click(arrowClick); } // simulate <select> behavior
// Handle presence of CSS Universal Selector (*) that defines padding by verifying what the browser thinks the outerHeight is.
// In FF, the outerHeight() will not pick up the correct input field padding
var inputPad = $input.outerHeight() - $input.height() - 2;
var inputWidth = $input.outerWidth() - 2;
var top = $input.outerHeight();
if (inputPad === 0) {
inputWidth += 4;
top += 4;
}
else if (inputPad !== 4) {
inputWidth += inputPad;
top += inputPad;
}
var $ctr = $('<div></div>')
.attr('id', $div.attr('id') + '_ctr')
.css('width', inputWidth + arrowWidth)
.css('top', top)
.css('left', 0)
.addClass(o.containerClass)
.appendTo($div)
.mousedown(function(e) {
$input.data('active', true);
})
.hide();
var $content = $('<div></div>')
.addClass(o.contentClass)
.appendTo($ctr)
.scroll(function() {
scrolling = true;
});
var $paging = $('<div></div>').appendTo($ctr);
$div.css('height', $input.outerHeight());
function processKeyDown(e) {
// handle modifiers
var mod = 0;
if (typeof (e.ctrlKey) !== 'undefined') {
if (e.ctrlKey) mod |= 1;
if (e.shiftKey) mod |= 2;
} else {
if (e.modifiers & Event.CONTROL_MASK) mod |= 1;
if (e.modifiers & Event.SHIFT_MASK) mod |= 2;
}
// if the keyCode is one of the modifiers, bail out (we'll catch it on the next keypress)
if (/16$|17$/.test(e.keyCode)) return; // 16 = Shift, 17 = Ctrl
var tab = e.keyCode === 9, esc = e.keyCode === 27;
var tabWithModifiers = e.keyCode === 9 && mod > 0;
var backspace = e.keyCode === 8; // we will end up extending the delay time for backspaces...
// tab is a special case, since we want to bubble events...
if (tab) if (getCurr()) selectCurr();
// handling up/down/escape/right arrow/left arrow requires results to be visible
// handling enter requires that AND a result to be selected
if ((/27$|38$|33$|34$/.test(e.keyCode) && $ctr.is(':visible')) ||
(/13$|40$/.test(e.keyCode)) || !o.allowInput) {
if (e.preventDefault) e.preventDefault();
if (e.stopPropagation) e.stopPropagation();
e.cancelBubble = true;
e.returnValue = false;
switch (e.keyCode) {
case 38: // up arrow
prevResult();
break;
case 40: // down arrow
if ($ctr.is(':visible')) nextResult();
else flexboxDelay(true);
break;
case 13: // enter
if (getCurr()) selectCurr();
else flexboxDelay(true);
break;
case 27: // escape
hideResults();
break;
case 34: // page down
if (!retrievingRemoteData) {
if (o.paging) $('#' + $div.attr('id') + 'n').click();
else nextPage();
}
break;
case 33: // page up
if (!retrievingRemoteData) {
if (o.paging) $('#' + $div.attr('id') + 'p').click();
else prevPage();
}
break;
default:
if (!o.allowInput) { return; }
}
} else if (!esc && !tab && !tabWithModifiers) { // skip esc and tab key and any modifiers
flexboxDelay(false, backspace);
}
}
function flexboxDelay(simulateArrowClick, increaseDelay) {
if (timeout) clearTimeout(timeout);
var delay = increaseDelay ? o.queryDelay * 5 : o.queryDelay;
timeout = setTimeout(function() { flexbox(1, simulateArrowClick, ''); }, delay);
}
function flexbox(p, arrowOrPagingClicked, prevQuery) {
if (arrowOrPagingClicked) prevQuery = '';
var q = prevQuery && prevQuery.length > 0 ? prevQuery : $.trim($input.val());
if (q.length >= o.minChars || arrowOrPagingClicked) {
// If we are getting data from the server, set the height of the content box so it doesn't shrink when navigating between pages, due to the $content.html('') below...
if ($content.outerHeight() > 0)
$content.css('height', $content.outerHeight());
$content.html('').attr('scrollTop', 0);
var cached = checkCache(q, p);
if (cached) {
$content.css('height', 'auto');
displayItems(cached.data, q);
showPaging(p, cached.t);
}
else {
var params = { q: q, p: p, s: pageSize, contentType: 'application/json; charset=utf-8' };
var callback = function(data, overrideQuery) {
if (overrideQuery === true) q = overrideQuery; // must compare to boolean because by default, the string value "success" is passed when the jQuery $.getJSON method's callback is called
var totalResults = parseInt(data[o.totalProperty]);
// Handle client-side paging, if any paging configuration options were specified
if (isNaN(totalResults) && o.paging) {
if (o.maxCacheBytes <= 0) alert('The "maxCacheBytes" configuration option must be greater\nthan zero when implementing client-side paging.');
totalResults = data[o.resultsProperty].length;
var pages = totalResults / pageSize;
if (totalResults % pageSize > 0) pages = parseInt(++pages);
for (var i = 1; i <= pages; i++) {
var pageData = {};
pageData[o.totalProperty] = totalResults;
pageData[o.resultsProperty] = data[o.resultsProperty].splice(0, pageSize);
if (i === 1) totalSize = displayItems(pageData, q);
updateCache(q, i, pageSize, totalResults, pageData, totalSize);
}
}
else {
var totalSize = displayItems(data, q);
updateCache(q, p, pageSize, totalResults, data, totalSize);
}
showPaging(p, totalResults);
$content.css('height', 'auto');
retrievingRemoteData = false;
};
if (typeof (o.source) === 'object') {
if (o.allowInput) callback(filter(o.source, params));
else callback(o.source);
}
else {
retrievingRemoteData = true;
if (o.method.toUpperCase() == 'POST') $.post(o.source, params, callback, 'json');
else $.getJSON(o.source, params, callback);
}
}
} else
hideResults();
}
function filter(data, params) {
var filtered = {};
filtered[o.resultsProperty] = [];
filtered[o.totalProperty] = 0;
var index = 0;
for (var i=0; i < data[o.resultsProperty].length; i++) {
var indexOfMatch = data[o.resultsProperty][i][o.displayValue].toLowerCase().indexOf(params.q.toLowerCase());
if ((o.matchAny && indexOfMatch !== -1) || (!o.matchAny && indexOfMatch === 0)) {
filtered[o.resultsProperty][index++] = data[o.resultsProperty][i];
filtered[o.totalProperty] += 1;
}
}
if (o.paging) {
var start = (params.p - 1) * params.s;
var howMany = (start + params.s) > filtered[o.totalProperty] ? filtered[o.totalProperty] - start : params.s;
filtered[o.resultsProperty] = filtered[o.resultsProperty].splice(start, howMany);
}
return filtered;
}
function showPaging(p, totalResults) {
$paging.html('').removeClass(o.paging.cssClass); // clear out for threshold scenarios
if (o.showResults && o.paging && totalResults > pageSize) {
var pages = totalResults / pageSize;
if (totalResults % pageSize > 0) pages = parseInt(++pages);
outputPagingLinks(pages, p, totalResults);
}
}
function handleKeyPress(e, page, totalPages) {
if (/^13$|^39$|^37$/.test(e.keyCode)) {
if (e.preventDefault)
e.preventDefault();
if (e.stopPropagation)
e.stopPropagation();
e.cancelBubble = true;
e.returnValue = false;
switch (e.keyCode) {
case 13: // Enter
if (/^\d+$/.test(page) && page > 0 && page <= totalPages)
flexbox(page, true);
else
alert('Please enter a page number between 1 and ' + totalPages);
// TODO: make this alert a function call, and a customizable parameter
break;
case 39: // right arrow
$('#' + $div.attr('id') + 'n').click();
break;
case 37: // left arrow
$('#' + $div.attr('id') + 'p').click();
break;
}
}
}
function handlePagingClick(e) {
flexbox(parseInt($(this).attr('page')), true, $input.attr('pq')); // pq == previous query
return false;
}
function outputPagingLinks(totalPages, currentPage, totalResults) {
// TODO: make these configurable images
var first = '&lt;&lt;',
prev = '&lt;',
next = '&gt;',
last = '&gt;&gt;',
more = '...';
$paging.addClass(o.paging.cssClass);
// set up our base page link element
var $link = $('<a/>')
.attr('href', '#')
.addClass('page')
.click(handlePagingClick),
$span = $('<span></span>').addClass('page'),
divId = $div.attr('id');
// show first page
if (currentPage > 1) {
$link.clone(true).attr('id', divId + 'f').attr('page', 1).html(first).appendTo($paging);
$link.clone(true).attr('id', divId + 'p').attr('page', currentPage - 1).html(prev).appendTo($paging);
}
else {
$span.clone(true).html(first).appendTo($paging);
$span.clone(true).html(prev).appendTo($paging);
}
if (o.paging.style === 'links') {
var maxPageLinks = o.paging.maxPageLinks;
// show page numbers
if (totalPages <= maxPageLinks) {
for (var i = 1; i <= totalPages; i++) {
if (i === currentPage) {
$span.clone(true).html(currentPage).appendTo($paging);
}
else {
$link.clone(true).attr('page', i).html(i).appendTo($paging);
}
}
}
else {
if ((currentPage + parseInt(maxPageLinks / 2)) > totalPages) {
startPage = totalPages - maxPageLinks + 1;
}
else {
startPage = currentPage - parseInt(maxPageLinks / 2);
}
if (startPage > 1) {
$link.clone(true).attr('page', startPage - 1).html(more).appendTo($paging);
}
else {
startPage = 1;
}
for (var i = startPage; i < startPage + maxPageLinks; i++) {
if (i === currentPage) {
$span.clone(true).html(i).appendTo($paging);
}
else {
$link.clone(true).attr('page', i).html(i).appendTo($paging);
}
}
if (totalPages > (startPage + maxPageLinks)) {
$link.clone(true).attr('page', i).html(more).appendTo($paging);
}
}
}
else if (o.paging.style === 'input') {
var $pagingBox = $('<input/>')
.addClass('box')
.click(function(e) {
this.select();
})
.keypress(function(e) {
return handleKeyPress(e, this.value, totalPages);
})
.val(currentPage)
.appendTo($paging);
}
if (currentPage < totalPages) {
$link.clone(true).attr('id', divId + 'n').attr('page', +currentPage + 1).html(next).appendTo($paging);
$link.clone(true).attr('id', divId + 'l').attr('page', totalPages).html(last).appendTo($paging);
}
else {
$span.clone(true).html(next).appendTo($paging);
$span.clone(true).html(last).appendTo($paging);
}
var startingResult = (currentPage - 1) * pageSize + 1;
var endingResult = (startingResult > (totalResults - pageSize)) ? totalResults : startingResult + pageSize - 1;
if (o.paging.showSummary) {
var summaryData = {
"start": startingResult,
"end": endingResult,
"total": totalResults,
"page": currentPage,
"pages": totalPages
};
var html = o.paging.summaryTemplate.applyTemplate(summaryData);
$('<br/>').appendTo($paging);
$('<span></span>')
.addClass(o.paging.summaryClass)
.html(html)
.appendTo($paging);
}
}
function checkCache(q, p) {
var key = q + delim + p; // use null character as delimiter
if (cacheData[key]) {
for (var i = 0; i < cache.length; i++) { // TODO: is it possible to not loop here?
if (cache[i] === key) {
// pull out the matching element (splice), and add it to the beginning of the array (unshift)
cache.unshift(cache.splice(i, 1)[0]);
return cacheData[key];
}
}
}
return false;
}
function updateCache(q, p, s, t, data, size) {
if (o.maxCacheBytes > 0) {
while (cache.length && (cacheSize + size > o.maxCacheBytes)) {
var cached = cache.pop();
cacheSize -= cached.size;
}
var key = q + delim + p; // use null character as delimiter
cacheData[key] = {
q: q,
p: p,
s: s,
t: t,
size: size,
data: data
}; // add the data to the cache at the hash key location
cache.push(key); // add the key to the MRU list
cacheSize += size;
}
}
function displayItems(d, q) {
var totalSize = 0, itemCount = 0;
if (!d)
return;
$hdn.val($input.val());
if (parseInt(d[o.totalProperty]) === 0 && o.noResultsText && o.noResultsText.length > 0) {
$content.addClass(o.noResultsClass).html(o.noResultsText);
$ctr.show();
return;
} else $content.removeClass(o.noResultsClass);
for (var i = 0; i < d[o.resultsProperty].length; i++) {
var data = d[o.resultsProperty][i],
result = o.resultTemplate.applyTemplate(data),
exactMatch = q === result,
selectedMatch = false,
hasHtmlTags = false,
match = data[o.displayValue];
if (!exactMatch && o.highlightMatches && q !== '') {
var pattern = q,
highlightStart = match.toLowerCase().indexOf(q.toLowerCase()),
replaceString = '<span class="' + o.matchClass + '">' + match.substr(highlightStart,q.length) + '</span>';
if (result.match('<(.|\n)*?>')) { // see if the content contains html tags
hasHtmlTags = true;
pattern = '(>)([^<]*?)(' + q + ')((.|\n)*?)(<)'; // TODO: look for a better way
replaceString = '$1$2<span class="' + o.matchClass + '">$3</span>$4$6';
}
result = result.replace(new RegExp(pattern.replace("[", "\\["), o.highlightMatchesRegExModifier), replaceString);
}
// write the value of the first match to the input box, and select the remainder,
// but only if autoCompleteFirstMatch is set, and there are no html tags in the response
if (o.autoCompleteFirstMatch && !hasHtmlTags && i === 0) {
if (q.length > 0 && match.toLowerCase().indexOf(q.toLowerCase()) === 0) {
$input.attr('pq', q); // pq == previous query
$hdn.val(data[o.hiddenValue]);
$input.val(data[o.displayValue]);
selectedMatch = selectRange(q.length, $input.val().length);
}
}
if (!o.showResults) return;
$row = $('<div></div>')
.attr('id', data[o.hiddenValue])
.attr('val', data[o.displayValue])
.addClass('row')
.html(result)
.appendTo($content);
if (exactMatch || (++itemCount == 1 && o.selectFirstMatch) || selectedMatch) {
$row.addClass(o.selectClass);
}
totalSize += result.length;
}
if (totalSize === 0) {
hideResults();
return;
}
$ctr.parent().css('z-index', 11000);
$ctr.show();
$content
.children('div')
.mouseover(function() {
$content.children('div').removeClass(o.selectClass);
$(this).addClass(o.selectClass);
})
.mouseup(function(e) {
e.preventDefault();
e.stopPropagation();
selectCurr();
});
if (o.maxVisibleRows > 0) {
var maxHeight = $row.outerHeight() * o.maxVisibleRows;
$content.css('max-height', maxHeight);
}
return totalSize;
}
function selectRange(s, l) {
var tb = $input[0];
if (tb.createTextRange) {
var r = tb.createTextRange();
r.moveStart('character', s);
r.moveEnd('character', l - tb.value.length);
r.select();
} else if (tb.setSelectionRange) {
tb.setSelectionRange(s, l);
}
tb.focus();
return true;
}
String.prototype.applyTemplate = function(d) {
try {
if (d === '') return this;
return this.replace(/{([^{}]*)}/g,
function(a, b) {
var r;
if (b.indexOf('.') !== -1) { // handle dot notation in {}, such as {Thumbnail.Url}
var ary = b.split('.');
var obj = d;
for (var i = 0; i < ary.length; i++)
obj = obj[ary[i]];
r = obj;
}
else
r = d[b];
if (typeof r === 'string' || typeof r === 'number') return r; else throw (a);
}
);
} catch (ex) {
alert('Invalid JSON property ' + ex + ' found when trying to apply resultTemplate or paging.summaryTemplate.\nPlease check your spelling and try again.');
}
};
function hideResults() {
$input.data('active', false); // for input blur
$div.css('z-index', 0);
$ctr.hide();
}
function getCurr() {
if (!$ctr.is(':visible'))
return false;
var $curr = $content.children('div.' + o.selectClass);
if (!$curr.length)
$curr = false;
return $curr;
}
function selectCurr() {
$curr = getCurr();
if ($curr) {
$hdn.val($curr.attr('id'));
$input.val($curr.attr('val')).focus();
hideResults();
if (o.onSelect) {
o.onSelect.apply($input[0]);
}
}
}
function supportsGetBoxObjectFor() {
try {
document.getBoxObjectFor(document.body);
return true;
}
catch (e) {
return false;
}
}
function supportsGetBoundingClientRect() {
try {
document.body.getBoundingClientRect();
return true;
}
catch (e) {
return false;
}
}
function nextPage() {
$curr = getCurr();
if ($curr && $curr.next().length > 0) {
$curr.removeClass(o.selectClass);
for (var i = 0; i < o.maxVisibleRows; i++) {
if ($curr.next().length > 0) {
$curr = $curr.next();
}
}
$curr.addClass(o.selectClass);
var scrollPos = $content.attr('scrollTop');
$content.attr('scrollTop', scrollPos + $content.height());
}
else if (!$curr)
$content.children('div:first-child').addClass(o.selectClass);
}
function prevPage() {
$curr = getCurr();
if ($curr && $curr.prev().length > 0) {
$curr.removeClass(o.selectClass);
for (var i = 0; i < o.maxVisibleRows; i++) {
if ($curr.prev().length > 0) {
$curr = $curr.prev();
}
}
$curr.addClass(o.selectClass);
var scrollPos = $content.attr('scrollTop');
$content.attr('scrollTop', scrollPos - $content.height());
}
else if (!$curr)
$content.children('div:last-child').addClass(o.selectClass);
}
function nextResult() {
$curr = getCurr();
if ($curr && $curr.next().length > 0) {
$curr.removeClass(o.selectClass).next().addClass(o.selectClass);
var scrollPos = $content.attr('scrollTop'),
curr = $curr[0], parentBottom, bottom, height;
if (supportsGetBoxObjectFor()) {
parentBottom = document.getBoxObjectFor($content[0]).y + $content.attr('offsetHeight');
bottom = document.getBoxObjectFor(curr).y + $curr.attr('offsetHeight');
height = document.getBoxObjectFor(curr).height;
}
else if (supportsGetBoundingClientRect()) {
parentBottom = $content[0].getBoundingClientRect().bottom;
var rect = curr.getBoundingClientRect();
bottom = rect.bottom;
height = bottom - rect.top;
}
if (bottom >= parentBottom)
$content.attr('scrollTop', scrollPos + height);
}
else if (!$curr)
$content.children('div:first-child').addClass(o.selectClass);
}
function prevResult() {
$curr = getCurr();
if ($curr && $curr.prev().length > 0) {
$curr.removeClass(o.selectClass).prev().addClass(o.selectClass);
var scrollPos = $content.attr('scrollTop'),
curr = $curr[0],
parent = $curr.parent()[0],
parentTop, top, height;
if (supportsGetBoxObjectFor()) {
height = document.getBoxObjectFor(curr).height;
parentTop = document.getBoxObjectFor($content[0]).y - (height * 2); // TODO: this is not working when i add another control...
top = document.getBoxObjectFor(curr).y - document.getBoxObjectFor($content[0]).y;
}
else if (supportsGetBoundingClientRect()) {
parentTop = parent.getBoundingClientRect().top;
var rect = curr.getBoundingClientRect();
top = rect.top;
height = rect.bottom - top;
}
if (top <= parentTop)
$content.attr('scrollTop', scrollPos - height);
}
else if (!$curr)
$content.children('div:last-child').addClass(o.selectClass);
}
};
$.fn.flexbox = function(source, options) {
if (!source)
return;
try {
var defaults = $.fn.flexbox.defaults;
var o = $.extend({}, defaults, options);
for (var prop in o) {
if (defaults[prop] === undefined) throw ('Invalid option specified: ' + prop + '\nPlease check your spelling and try again.');
}
o.source = source;
if (options) {
o.paging = (options.paging || options.paging == null) ? $.extend({}, defaults.paging, options.paging) : false;
for (var prop in o.paging) {
if (defaults.paging[prop] === undefined) throw ('Invalid option specified: ' + prop + '\nPlease check your spelling and try again.');
}
if (options.displayValue && !options.hiddenValue) {
o.hiddenValue = options.displayValue;
}
}
this.each(function() {
new $.flexbox(this, o);
});
return this;
} catch (ex) {
if (typeof ex === 'object') alert(ex.message); else alert(ex);
}
};
// plugin defaults - added as a property on our plugin function so they can be set independently
$.fn.flexbox.defaults = {
method: 'GET', // One of 'GET' or 'POST'
queryDelay: 100, // num of milliseconds before query is run.
allowInput: true, // set to false to disallow the user from typing in queries
containerClass: 'ffb',
contentClass: 'content',
selectClass: 'ffb-sel',
inputClass: 'ffb-input',
arrowClass: 'ffb-arrow',
matchClass: 'ffb-match',
noResultsText: 'No matching results', // text to show when no results match the query
noResultsClass: 'ffb-no-results', // class to apply to noResultsText
showResults: true, // whether to show results at all, or just typeahead
selectFirstMatch: true, // whether to highlight the first matching value
autoCompleteFirstMatch: false, // whether to complete the first matching value in the input box
highlightMatches: true, // whether all matches within the string should be highlighted with matchClass
highlightMatchesRegExModifier: 'i', // 'i' for case-insensitive, 'g' for global (all occurrences), or combine
matchAny: true, // for client-side filtering ONLY, match any occurrence of the search term in the result (e.g. "ar" would find "area" and "cart")
minChars: 1, // the minimum number of characters the user must enter before a search is executed
showArrow: true, // set to false to simulate google suggest
arrowQuery: '', // the query to run when the arrow is clicked
onSelect: false, // function to run when a result is selected
maxCacheBytes: 32768, // in bytes, 0 means caching is disabled
resultTemplate: '{name}', // html template for each row (put json properties in curly braces)
displayValue: 'name', // json element whose value is displayed on select
hiddenValue: 'id', // json element whose value is submitted when form is submitted
initialValue: '', // what should the value of the input field be when the form is loaded?
initialId: '', // what should the value of the hidden field be when the form is loaded?
watermark: '', // text that appears when flexbox is loaded, if no initialValue is specified. style with css class '.ffb-input.watermark'
width: 200, // total width of flexbox. auto-adjusts based on showArrow value
resultsProperty: 'results', // json property in response that references array of results
totalProperty: 'total', // json property in response that references the total results (for paging)
maxVisibleRows: 0, // default is 0, which means it is ignored. use either this, or paging.pageSize
paging: {
style: 'input', // or 'links'
cssClass: 'paging', // prefix with containerClass (e.g. .ffb .paging)
pageSize: 10, // acts as a threshold. if <= pageSize results, paging doesn't appear
maxPageLinks: 5, // used only if style is 'links'
showSummary: true, // whether to show 'displaying 1-10 of 200 results' text
summaryClass: 'summary', // class for 'displaying 1-10 of 200 results', prefix with containerClass
summaryTemplate: 'Displaying {start}-{end} of {total} results' // can use {page} and {pages} as well
}
};
$.fn.setValue = function(val) {
var id = '#' + this.attr('id');
$(id + '_hidden,' + id + '_input').val(val).removeClass('watermark');
};
})(jQuery);

File diff suppressed because one or more lines are too long

View File

@ -228,6 +228,7 @@ class DbDjango(DbWriteBase, DbReadBase):
self.dji.add_tag_detail(obj.serialize())
self.use_import_cache = False
self.import_cache = {}
self.dji.update_publics()
def transaction_commit(self, txn):
pass
@ -236,8 +237,8 @@ class DbDjango(DbWriteBase, DbReadBase):
pass
def request_rebuild(self):
#self.dji.rebuild_caches()
pass
# caches are ok, but let's compute public's
self.dji.update_publics()
def get_undodb(self):
return None

View File

@ -228,8 +228,8 @@ CREATE TABLE "auth_user" (
"last_login" datetime NOT NULL,
"date_joined" datetime NOT NULL
);
INSERT INTO "auth_user" VALUES(1,'admin','','','bugs@gramps-project.org','sha1$0aac2$c94ddc40e2dfd41bd5453230a3e53a6a925572b2',1,1,1,'2012-07-28 09:32:02.407417','2012-07-28 09:32:02.407417');
INSERT INTO "auth_user" VALUES(2,'admin1','','','bugs@gramps-project.org','sha1$887ff$3829f603618766d49287f3b98b036d6b06c3f440',1,1,1,'2012-07-28 09:32:07.068033','2012-07-28 09:32:07.068033');
INSERT INTO "auth_user" VALUES(1,'admin','','','bugs@gramps-project.org','sha1$248cf$71082f5ec314e2706d1cc9e44a0d63b953ba1d08',1,1,1,'2012-07-31 07:58:28.096063','2012-07-31 07:58:28.096063');
INSERT INTO "auth_user" VALUES(2,'admin1','','','bugs@gramps-project.org','sha1$bd368$2e83f9d34578f66402e62b698950adae05f4d6bf',1,1,1,'2012-07-31 07:58:37.492571','2012-07-31 07:58:37.492571');
CREATE TABLE "auth_message" (
"id" integer NOT NULL PRIMARY KEY,
"user_id" integer NOT NULL REFERENCES "auth_user" ("id"),
@ -648,7 +648,7 @@ CREATE TABLE "grampsdb_config" (
);
INSERT INTO "grampsdb_config" VALUES(1,'sitename','site name of family tree','str','Gramps-Connect');
INSERT INTO "grampsdb_config" VALUES(2,'db_version','database scheme version','str','0.6.1');
INSERT INTO "grampsdb_config" VALUES(3,'db_created','database creation date/time','str','2012-07-28 09:30');
INSERT INTO "grampsdb_config" VALUES(3,'db_created','database creation date/time','str','2012-07-31 07:56');
INSERT INTO "grampsdb_config" VALUES(4,'htmlview.url-handler',NULL,'bool','False');
INSERT INTO "grampsdb_config" VALUES(5,'htmlview.start-url',NULL,'str','http://gramps-project.org');
INSERT INTO "grampsdb_config" VALUES(6,'paths.recent-export-dir',NULL,'str','');
@ -863,6 +863,7 @@ CREATE TABLE "grampsdb_person" (
"last_changed" datetime,
"last_changed_by" text,
"private" bool NOT NULL,
"public" bool NOT NULL,
"cache" text,
"gender_type_id" integer NOT NULL REFERENCES "grampsdb_gendertype" ("id"),
"probably_alive" bool NOT NULL,
@ -885,6 +886,7 @@ CREATE TABLE "grampsdb_family" (
"last_changed" datetime,
"last_changed_by" text,
"private" bool NOT NULL,
"public" bool NOT NULL,
"cache" text,
"father_id" integer REFERENCES "grampsdb_person" ("id"),
"mother_id" integer REFERENCES "grampsdb_person" ("id"),
@ -912,6 +914,7 @@ CREATE TABLE "grampsdb_citation" (
"last_changed" datetime,
"last_changed_by" text,
"private" bool NOT NULL,
"public" bool NOT NULL,
"cache" text,
"confidence" integer,
"page" varchar(50),
@ -925,6 +928,7 @@ CREATE TABLE "grampsdb_source" (
"last_changed" datetime,
"last_changed_by" text,
"private" bool NOT NULL,
"public" bool NOT NULL,
"cache" text,
"title" varchar(50),
"author" varchar(50),
@ -953,6 +957,7 @@ CREATE TABLE "grampsdb_event" (
"last_changed" datetime,
"last_changed_by" text,
"private" bool NOT NULL,
"public" bool NOT NULL,
"cache" text,
"event_type_id" integer NOT NULL REFERENCES "grampsdb_eventtype" ("id"),
"description" varchar(50) NOT NULL,
@ -966,6 +971,7 @@ CREATE TABLE "grampsdb_repository" (
"last_changed" datetime,
"last_changed_by" text,
"private" bool NOT NULL,
"public" bool NOT NULL,
"cache" text,
"repository_type_id" integer NOT NULL REFERENCES "grampsdb_repositorytype" ("id"),
"name" text NOT NULL
@ -978,6 +984,7 @@ CREATE TABLE "grampsdb_place" (
"last_changed" datetime,
"last_changed_by" text,
"private" bool NOT NULL,
"public" bool NOT NULL,
"cache" text,
"title" text NOT NULL,
"long" text NOT NULL,
@ -1011,6 +1018,7 @@ CREATE TABLE "grampsdb_media" (
"last_changed" datetime,
"last_changed_by" text,
"private" bool NOT NULL,
"public" bool NOT NULL,
"cache" text,
"path" text NOT NULL,
"mime" text,
@ -1030,6 +1038,7 @@ CREATE TABLE "grampsdb_note" (
"last_changed" datetime,
"last_changed_by" text,
"private" bool NOT NULL,
"public" bool NOT NULL,
"cache" text,
"note_type_id" integer NOT NULL REFERENCES "grampsdb_notetype" ("id"),
"text" text NOT NULL,
@ -1120,13 +1129,15 @@ CREATE TABLE "grampsdb_sourcedatamap" (
"id" integer NOT NULL PRIMARY KEY,
"key" varchar(80) NOT NULL,
"value" varchar(80) NOT NULL,
"source_id" integer NOT NULL REFERENCES "grampsdb_source" ("id")
"source_id" integer NOT NULL REFERENCES "grampsdb_source" ("id"),
"order" integer unsigned NOT NULL
);
CREATE TABLE "grampsdb_citationdatamap" (
"id" integer NOT NULL PRIMARY KEY,
"key" varchar(80) NOT NULL,
"value" varchar(80) NOT NULL,
"citation_id" integer NOT NULL REFERENCES "grampsdb_citation" ("id")
"citation_id" integer NOT NULL REFERENCES "grampsdb_citation" ("id"),
"order" integer unsigned NOT NULL
);
CREATE TABLE "grampsdb_address" (
"id" integer NOT NULL PRIMARY KEY,

File diff suppressed because it is too large Load Diff

View File

@ -27,7 +27,7 @@
from django import forms
from django.forms.models import inlineformset_factory
from django.forms.models import BaseModelFormSet
from django.forms.widgets import TextInput
from django.forms.widgets import TextInput, HiddenInput
# Gramps Modules:
from webapp.grampsdb.models import *
@ -132,22 +132,14 @@ class SurnameForm(forms.ModelForm):
class FamilyForm(forms.ModelForm):
class Meta:
model = Family
exclude = ["handle", "cache"]
def __init__(self, *args, **kwargs):
super(FamilyForm, self).__init__(*args, **kwargs)
self.fields['father'].queryset = Person.objects.filter(
gender_type=get_type_from_name(GenderType, "Male")) \
.order_by("name__surname__surname", "name__first_name")
self.fields['mother'].queryset = Person.objects.filter(
gender_type=get_type_from_name(GenderType, "Female")) \
.order_by("name__surname__surname", "name__first_name")
exclude = ["handle", "cache", "mother", "father"]
class EventForm(forms.ModelForm):
class Meta:
model = Event
exclude = ["handle", "sortval", "month1", "year1", "day1",
"newyear", "calendar", "modifier", "quality", "cache"]
"newyear", "calendar", "modifier", "quality", "cache",
"place"]
def clean(self):
from webapp.utils import dp

View File

@ -448,6 +448,7 @@ class PrimaryObject(models.Model):
last_changed_by = models.TextField(blank=True, null=True)
private = models.BooleanField('private')
public = models.BooleanField('public', default=True)
#attributes = models.ManyToManyField("Attribute", blank=True, null=True)
cache = models.TextField(blank=True, null=True)
@ -513,6 +514,9 @@ class Person(PrimaryObject):
def make_tag_list(self):
return tuple()
def get_selection_string(self):
return self.name_set.get(preferred=True).get_selection_string()
class Family(PrimaryObject):
father = models.ForeignKey('Person', related_name="father_ref",
null=True, blank=True)
@ -609,6 +613,9 @@ class Place(PrimaryObject):
lat = models.TextField(blank=True)
#url_list = models.ManyToManyField('Url', null=True, blank=True)
def get_selection_string(self):
return "%s [%s]" % (self.title, self.gramps_id)
def __unicode__(self):
return str(self.title)
@ -719,6 +726,14 @@ class Name(DateObject, SecondaryObject):
surname = "[No primary surname]"
return "%s, %s" % (surname,
self.first_name)
def get_selection_string(self):
try:
surname = self.surname_set.get(primary=True)
except:
surname = "[No primary surname]"
return "%s, %s [%s]" % (surname, self.first_name, self.person.gramps_id)
@staticmethod
def get_dummy():
name = Name()
@ -791,11 +806,13 @@ class SourceDatamap(models.Model):
key = models.CharField(max_length=80, blank=True)
value = models.CharField(max_length=80, blank=True)
source = models.ForeignKey("Source")
order = models.PositiveIntegerField()
class CitationDatamap(models.Model):
key = models.CharField(max_length=80, blank=True)
value = models.CharField(max_length=80, blank=True)
citation = models.ForeignKey("Citation")
order = models.PositiveIntegerField()
class Address(DateObject, SecondaryObject):
#locations = models.ManyToManyField('Location', null=True)

View File

@ -186,6 +186,11 @@ def make_args(search, page):
make_args.is_safe = True
register.simple_tag(make_args)
def format_color(color):
return color[0:3] + color[5:7] + color[9:11]
format_color.is_safe = True
register.filter("format_color", format_color)
def currentSection(view1, view2): # tview, menu
if view1.strip().lower() in [view[1] for view in VIEWS] and view2 == "browse":
return "class=CurrentSection"

View File

@ -47,6 +47,7 @@ from django.shortcuts import get_object_or_404, render_to_response, redirect
from django.template import Context, RequestContext
from django.db.models import Q
from django.forms.models import modelformset_factory
from django.utils import simplejson
#------------------------------------------------------------------------
#
@ -60,7 +61,8 @@ from webapp.grampsdb.view import *
from webapp.dbdjango import DbDjango
import cli.user
import gen.proxy
from gen.const import VERSION
from gen.const import VERSION_TUPLE
from gen.utils.svn import get_svn_revision
# Menu: (<Nice name>, /<path>/, <Model> | None, Need authentication )
MENU = [
@ -95,7 +97,7 @@ def context_processor(request):
else:
context["css_theme"] = "Web_Mainz.css"
# Other things for all environments:
context["gramps_version"] = VERSION
context["gramps_version"] = ".".join([str(v) for v in VERSION_TUPLE]) + " " + get_svn_revision()
context["views"] = VIEWS
context["menu"] = MENU
context["None"] = None
@ -582,7 +584,6 @@ def process_report(request, context, handle, act):
context["tviews"] = _("Reports")
def build_string_query(field, value, exact=False, startswith=False, endswith=False):
print field, value
retval = None
if exact:
retval = Q(**{"%s" % field: value})
@ -601,9 +602,10 @@ def build_person_query(request, search):
"""
protect = not request.user.is_authenticated()
### Build the order:
terms = ["surname", "given", "tag"]
terms = ["surname", "given", "id", "tag", "public", "private"]
if protect:
# Do this to get the names sorted by private/alive
# NOTE: names can be private
query = Q(private=False) & Q(person__private=False)
order = ["surname__surname", "private", "person__probably_alive",
"first_name"]
@ -612,6 +614,9 @@ def build_person_query(request, search):
order = ["surname__surname", "first_name"]
### Build the query:
if search:
if "[" in search: # "Surname, Given [I0002]" to match Flexbox and obj.get_select_string()
search = search.replace("[", ", id=^")
search = search.replace("]", "$")
if "," in search or "=" in search:
for term in [term.strip() for term in search.split(",")]:
startswith = False
@ -645,6 +650,9 @@ def build_person_query(request, search):
elif field == "private":
if not protect:
query &= Q(person__private=boolean(value))
elif field == "public":
if not protect:
query &= Q(person__public=boolean(value))
elif field == "birth":
if protect:
query &= Q(person__birth__year1=safe_int(value)) & Q(person__probably_alive=False)
@ -685,7 +693,8 @@ def build_family_query(request, search):
Build and return a Django QuerySet and sort order for the Family
table.
"""
terms = ["father", "mother", "id", "type", "surnames", "father.name.first_name", "mother.name.first_name", "tag"]
terms = ["father", "mother", "id", "type", "surnames", "father.name.first_name",
"mother.name.first_name", "tag", "public", "private"]
protect = not request.user.is_authenticated()
if protect:
query = (Q(private=False) & Q(father__private=False) &
@ -740,6 +749,10 @@ def build_family_query(request, search):
query &= build_string_query("gramps_id", value, exact, startswith, endswith)
elif field == "tag":
query &= build_string_query("tags__name", value, exact, startswith, endswith)
elif field == "private":
query &= Q(private=boolean(value))
elif field == "public":
query &= Q(public=boolean(value))
else:
make_message(request, message="Invalid query field '%s'" % field)
else: # no search fields, just raw search
@ -759,7 +772,7 @@ def build_family_query(request, search):
return query, order, terms
def build_media_query(request, search):
terms = ["id", "path", "description", "mime", "tag"]
terms = ["id", "path", "description", "mime", "tag", "public", "private"]
protect = not request.user.is_authenticated()
if protect:
query = Q(private=False) # general privacy
@ -801,6 +814,10 @@ def build_media_query(request, search):
query &= build_string_query("mime", value, exact, startswith, endswith)
elif field == "tag":
query &= build_string_query("tags__name", value, exact, startswith, endswith)
elif field == "private":
query &= Q(private=boolean(value))
elif field == "public":
query &= Q(public=boolean(value))
else:
request.user.message_set.create(message="Invalid query field '%s'" % field)
else: # no search fields, just raw search
@ -819,7 +836,7 @@ def build_media_query(request, search):
return query, order, terms
def build_note_query(request, search):
terms = ["id", "type", "text", "tag"]
terms = ["id", "type", "text", "tag", "public", "private"]
protect = not request.user.is_authenticated()
if protect:
query = Q(private=False) # general privacy
@ -859,6 +876,10 @@ def build_note_query(request, search):
query &= build_string_query("text", value, exact, startswith, endswith)
elif field == "tag":
query &= build_string_query("tags__name", value, exact, startswith, endswith)
elif field == "private":
query &= Q(private=boolean(value))
elif field == "public":
query &= Q(public=boolean(value))
else:
request.user.message_set.create(message="Invalid query field '%s'" % field)
else: # no search fields, just raw search
@ -875,7 +896,7 @@ def build_note_query(request, search):
return query, order, terms
def build_place_query(request, search):
terms = ["id", "title"]
terms = ["title", "id", "public", "private"]
protect = not request.user.is_authenticated()
if protect:
query = Q(private=False) # general privacy
@ -884,8 +905,11 @@ def build_place_query(request, search):
query = Q()
order = ["gramps_id"]
if search:
if "," in search or "=" in search:
for term in [term.strip() for term in search.split(",")]:
if "[" in search: # "Place [I0002]" to match Flexbox and obj.get_select_string()
search = search.replace("[", "; id=^")
search = search.replace("]", "$")
if ";" in search or "=" in search:
for term in [term.strip() for term in search.split(";")]:
startswith = False
endswith = False
exact = False
@ -911,6 +935,10 @@ def build_place_query(request, search):
query &= build_string_query("gramps_id", value, exact, startswith, endswith)
elif field == "title":
query &= build_string_query("title", value, exact, startswith, endswith)
elif field == "private":
query &= Q(private=boolean(value))
elif field == "public":
query &= Q(public=boolean(value))
else:
request.user.message_set.create(message="Invalid query field '%s'" % field)
else: # no search fields, just raw search
@ -925,7 +953,7 @@ def build_place_query(request, search):
return query, order, terms
def build_repository_query(request, search):
terms = ["id", "name", "type"]
terms = ["id", "name", "type", "public", "private"]
protect = not request.user.is_authenticated()
if protect:
query = Q(private=False) # general privacy
@ -963,6 +991,10 @@ def build_repository_query(request, search):
query &= build_string_query("name", value, exact, startswith, endswith)
elif field == "type":
query &= build_string_query("repository_type__name", value, exact, startswith, endswith)
elif field == "private":
query &= Q(private=boolean(value))
elif field == "public":
query &= Q(public=boolean(value))
else:
request.user.message_set.create(message="Invalid query field '%s'" % field)
else: # no search fields, just raw search
@ -981,7 +1013,7 @@ def build_repository_query(request, search):
return query, order, terms
def build_citation_query(request, search):
terms = ["id"]
terms = ["id", "private", "public"]
protect = not request.user.is_authenticated()
if protect:
query = Q(private=False) # general privacy
@ -1015,6 +1047,10 @@ def build_citation_query(request, search):
query &= build_string_query(field.replace(".", "__"), value, exact, startswith, endswith)
elif field == "id":
query &= build_string_query("gramps_id", value, exact, startswith, endswith)
elif field == "private":
query &= Q(private=boolean(value))
elif field == "public":
query &= Q(public=boolean(value))
else:
request.user.message_set.create(message="Invalid query field '%s'" % field)
else: # no search fields, just raw search
@ -1027,7 +1063,7 @@ def build_citation_query(request, search):
return query, order, terms
def build_source_query(request, search):
terms = ["id"]
terms = ["id", "private", "public"]
protect = not request.user.is_authenticated()
if protect:
query = Q(private=False) # general privacy
@ -1061,6 +1097,10 @@ def build_source_query(request, search):
query &= build_string_query(field.replace(".", "__"), value, exact, startswith, endswith)
elif field == "id":
query &= build_string_query("gramps_id", value, exact, startswith, endswith)
elif field == "private":
query &= Q(private=boolean(value))
elif field == "public":
query &= Q(public=boolean(value))
else:
request.user.message_set.create(message="Invalid query field '%s'" % field)
else: # no search fields, just raw search
@ -1166,7 +1206,7 @@ def build_report_query(request, search):
return query, order, terms
def build_event_query(request, search):
terms = ["id", "type", "place", "description"]
terms = ["id", "type", "place", "description", "private", "public"]
protect = not request.user.is_authenticated()
if protect:
query = Q(private=False) # general privacy
@ -1201,22 +1241,26 @@ def build_event_query(request, search):
elif field == "id":
query &= build_string_query("gramps_id", value, exact, startswith, endswith)
elif field == "description":
query &= build_string_query("desc", value, exact, startswith, endswith)
query &= build_string_query("description", value, exact, startswith, endswith)
elif field == "type":
query &= build_string_query("event_type__name", value, exact, startswith, endswith)
elif field == "place":
query &= build_string_query("place__title", value, exact, startswith, endswith)
elif field == "private":
query &= Q(private=boolean(value))
elif field == "public":
query &= Q(public=boolean(value))
else:
request.user.message_set.create(message="Invalid query field '%s'" % field)
else: # no search fields, just raw search
if protect:
query &= (Q(gramps_id__icontains=search) |
Q(desc__icontains=search) |
Q(description__icontains=search) |
Q(event_type__name__icontains=search) |
Q(place__title__icontains=search))
else:
query &= (Q(gramps_id__icontains=search) |
Q(desc__icontains=search) |
Q(description__icontains=search) |
Q(event_type__name__icontains=search) |
Q(place__title__icontains=search))
else: # no search
@ -1314,13 +1358,14 @@ def process_list_item(request, view, handle, act, item, index):
# /citation/872323636232635/down/attribute/2
index = int(index)
tab = {
"eventref": "#tab-events",
"citationref": "#tab-citations",
"attribute": "#tab-attributes",
"media": "#tab-media",
"lds": "#tab-lds",
"parentfamily": "#tab-references",
"family": "#tab-references",
"eventref": "#tab-events",
"citationref": "#tab-citations",
"repositoryref": "#tab-repositories",
"attribute": "#tab-attributes",
"media": "#tab-media",
"lds": "#tab-lds",
"parentfamily": "#tab-references",
"family": "#tab-references",
}
if view == "person":
obj = dji.Person.get(handle=handle)
@ -1330,6 +1375,10 @@ def process_list_item(request, view, handle, act, item, index):
obj = dji.Family.get(handle=handle)
elif view == "citation":
obj = dji.Citation.get(handle=handle)
elif view == "source":
obj = dji.Source.get(handle=handle)
else:
raise Exception("add '%s' to list" % view)
obj_type = ContentType.objects.get_for_model(obj)
# Next, get reference
if item == "eventref":
@ -1338,10 +1387,15 @@ def process_list_item(request, view, handle, act, item, index):
elif item == "citationref":
refs = dji.CitationRef.filter(object_id=obj.id,
object_type=obj_type).order_by("order")
elif item == "repositoryref":
refs = dji.RepositoryRef.filter(object_id=obj.id,
object_type=obj_type).order_by("order")
elif item == "parentfamily":
refs = dji.PersonParentFamilyOrder.filter(person=obj).order_by("order")
refs = dji.MyParentFamilies.filter(person=obj).order_by("order")
elif item == "family":
refs = dji.PersonFamilyOrder.filter(person=obj).order_by("order")
refs = dji.MyFamilies.filter(person=obj).order_by("order")
else:
raise Exception("add '%s' to reference list" % item)
# Next, perform action:
if act == "remove":
count = 1
@ -1376,3 +1430,56 @@ def process_list_item(request, view, handle, act, item, index):
count += 1
dji.rebuild_cache(obj)
return redirect("/%s/%s/%s" % (view, handle, tab[item]))
def process_json_request(request):
"""
Process an Ajax/Json query request.
"""
if not request.user.is_authenticated():
response_data = {"results": [], "total": 0}
return HttpResponse(simplejson.dumps(response_data), mimetype="application/json")
field = request.GET.get("field", None)
query = request.GET.get("q", "")
page = int(request.GET.get("p", "1"))
size = int(request.GET.get("s", "10"))
if field == "mother":
q, order, terms = build_person_query(request, query)
q &= Q(person__gender_type__name="Female")
matches = Name.objects.filter(q).order_by(*order)
response_data = {"results": [], "total": len(matches)}
for match in matches[(page - 1) * size:page * size]:
response_data["results"].append(
{"id": match.person.handle,
"name": match.get_selection_string(),
})
elif field == "father":
q, order, terms = build_person_query(request, query)
q &= Q(person__gender_type__name="Male")
matches = Name.objects.filter(q).order_by(*order)
response_data = {"results": [], "total": len(matches)}
for match in matches[(page - 1) * size:page * size]:
response_data["results"].append(
{"id": match.person.handle,
"name": match.get_selection_string(),
})
elif field == "person":
q, order, terms = build_person_query(request, query)
matches = Name.objects.filter(q).order_by(*order)
response_data = {"results": [], "total": len(matches)}
for match in matches[(page - 1) * size:page * size]:
response_data["results"].append(
{"id": match.person.handle,
"name": match.get_selection_string(),
})
elif field == "place":
q, order, terms = build_place_query(request, query)
matches = Place.objects.filter(q).order_by(*order)
response_data = {"results": [], "total": len(matches)}
for match in matches[(page - 1) * size:page * size]:
response_data["results"].append(
{"id": match.handle,
"name": match.get_selection_string(),
})
else:
raise Exception("""Invalid field: '%s'; Example: /json/?field=mother&q=Smith&p=1&size=10""" % field)
return HttpResponse(simplejson.dumps(response_data), mimetype="application/json")

View File

@ -211,10 +211,10 @@ class DjangoInterface(object):
return map(self.pack_name, names)
def get_source_datamap(self, source):
return dict([map.key, map.value] for map in source.sourcedatamap_set.all())
return dict([map.key, map.value] for map in source.sourcedatamap_set.all().order_by("order"))
def get_citation_datamap(self, citation):
return dict([map.key, map.value] for map in citation.citationdatamap_set.all())
return dict([map.key, map.value] for map in citation.citationdatamap_set.all().order_by("order"))
def get_media_list(self, obj):
obj_type = ContentType.objects.get_for_model(obj)
@ -1021,18 +1021,22 @@ class DjangoInterface(object):
## Export individual objects:
def add_source_datamap_dict(self, source, datamap_dict):
count = 1
for key in datamap_dict:
value = datamap_dict[key]
datamap = models.SourceDatamap(key=key, value=value)
datamap = models.SourceDatamap(key=key, value=value, order=count)
datamap.source = source
datamap.save()
count += 1
def add_citation_datamap_dict(self, citation, datamap_dict):
count = 1
for key in datamap_dict:
value = datamap_dict[key]
datamap = models.CitationDatamap(key=key, value=value)
datamap = models.CitationDatamap(key=key, value=value, order=count)
datamap.citation = citation
datamap.save()
count += 1
def add_lds(self, field, obj, data, order):
(lcitation_list, lnote_list, date, type, place_handle,
@ -1697,6 +1701,7 @@ class DjangoInterface(object):
"""
Resets the cache version of an object, and saves it to the database.
"""
self.update_public(item, save=False)
self.reset_cache(item)
item.save()
@ -1721,66 +1726,53 @@ class DjangoInterface(object):
self.Citation.all().count() +
self.Tag.all().count())
for item in self.Note.all():
self.rebuild_cache(item)
count += 1
callback(100 * (count/total if total else 0))
for item in self.Person.all():
raw = self.get_person(item)
item.cache = base64.encodestring(cPickle.dumps(raw))
item.save()
self.rebuild_cache(item)
count += 1
callback(100 * (count/total if total else 0))
for item in self.Family.all():
raw = self.get_family(item)
item.cache = base64.encodestring(cPickle.dumps(raw))
item.save()
self.rebuild_cache(item)
count += 1
callback(100 * (count/total if total else 0))
for item in self.Source.all():
raw = self.get_source(item)
item.cache = base64.encodestring(cPickle.dumps(raw))
item.save()
self.rebuild_cache(item)
count += 1
callback(100 * (count/total if total else 0))
for item in self.Event.all():
raw = self.get_event(item)
item.cache = base64.encodestring(cPickle.dumps(raw))
item.save()
self.rebuild_cache(item)
count += 1
callback(100 * (count/total if total else 0))
for item in self.Repository.all():
raw = self.get_repository(item)
item.cache = base64.encodestring(cPickle.dumps(raw))
item.save()
self.rebuild_cache(item)
count += 1
callback(100 * (count/total if total else 0))
for item in self.Place.all():
raw = self.get_place(item)
item.cache = base64.encodestring(cPickle.dumps(raw))
item.save()
self.rebuild_cache(item)
count += 1
callback(100 * (count/total if total else 0))
for item in self.Media.all():
raw = self.get_media(item)
item.cache = base64.encodestring(cPickle.dumps(raw))
item.save()
self.rebuild_cache(item)
count += 1
callback(100 * (count/total if total else 0))
for item in self.Citation.all():
raw = self.get_citation(item)
item.cache = base64.encodestring(cPickle.dumps(raw))
item.save()
self.rebuild_cache(item)
count += 1
callback(100 * (count/total if total else 0))
for item in self.Tag.all():
raw = self.get_tag(item)
item.cache = base64.encodestring(cPickle.dumps(raw))
item.save()
self.rebuild_cache(item)
count += 1
callback(100)
@ -1804,6 +1796,13 @@ class DjangoInterface(object):
self.Citation.all().count() +
self.Tag.all().count())
for item in self.Note.all():
raw = self.get_note(item)
if item.cache == base64.encodestring(cPickle.dumps(raw)):
print "Different!", item
count += 1
callback(100 * (count/total if total else 0))
for item in self.Person.all():
raw = self.get_person(item)
if item.cache == base64.encodestring(cPickle.dumps(raw)):
@ -1868,6 +1867,9 @@ class DjangoInterface(object):
callback(100)
def check_families(self):
"""
Check family structures.
"""
for family in self.Family.all():
if family.mother:
if not family in family.mother.families.all():
@ -1885,3 +1887,152 @@ class DjangoInterface(object):
for family in person.parent_families.all():
if person not in family.get_children():
print "Child not in family", person, family
def is_public(self, obj, objref):
"""
Returns whether or not an item is "public", and the reason
why/why not.
@param obj - an instance of any Primary object
@param objref - one of the PrimaryRef.objects
@return - a tuple containing a boolean (public?) and reason.
There are three reasons why an item might not be public:
1) The item itself is private.
2) The item is referenced by a living Person.
3) The item is referenced by some other private item.
"""
# If it is private, then no:
if obj.private:
return (False, "It is marked private.")
elif hasattr(obj, "probably_alive") and obj.probably_alive:
return (False, "It is marked probaby alive.")
elif hasattr(obj, "mother") and obj.mother:
public, reason = self.is_public(obj.mother, self.PersonRef)
if not public:
return public, reason
elif hasattr(obj, "father") and obj.father:
public, reason = self.is_public(obj.father, self.PersonRef)
if not public:
return public, reason
# FIXME: what about Associations... anything else? Check PrivateProxy
if objref:
obj_ref_list = objref.filter(ref_object=obj)
for reference in obj_ref_list:
ref_from_class = reference.object_type.model_class()
item = None
try:
item = ref_from_class.objects.get(id=reference.object_id)
except:
print "Warning: Corrupt reference: %s" % reference
continue
# If it is linked to by someone alive? public = False
if hasattr(item, "probably_alive") and item.probably_alive:
return (False, "It is referenced by someone who is probaby alive.")
# If it is linked to by something private? public = False
elif item.private:
return (False, "It is referenced by an item which is marked private.")
return (True, "It is visible to the public.")
def update_public(self, obj, save=True):
"""
>>> dji.update_public(event)
Given an Event or other instance, update the event's public
status, or any event referenced to by the instance.
For example, if a person is found to be alive, then the
referenced events should be marked not public (public = False).
"""
if obj.__class__.__name__ == "Event":
objref = self.EventRef
elif obj.__class__.__name__ == "Person":
objref = self.PersonRef
elif obj.__class__.__name__ == "Note":
objref = self.NoteRef
elif obj.__class__.__name__ == "Repository":
objref = self.RepositoryRef
elif obj.__class__.__name__ == "Citation":
objref = self.CitationRef
elif obj.__class__.__name__ == "Media":
objref = self.MediaRef
elif obj.__class__.__name__ == "Place": # no need for dependency
objref = None
elif obj.__class__.__name__ == "Source": # no need for dependency
objref = None
elif obj.__class__.__name__ == "Family":
objref = self.ChildRef # correct?
else:
raise Exception("Can't compute public of type '%s'" % obj)
public, reason = self.is_public(obj, objref) # correct?
# Ok, update, if needed:
if obj.public != public:
obj.public = public
if save:
obj.save()
def update_publics(self, callback=None):
"""
Call this to check the caches for all primary models.
"""
if not callable(callback):
callback = lambda (percent): None # dummy
callback(0)
count = 0.0
total = (self.Note.all().count() +
self.Person.all().count() +
self.Event.all().count() +
self.Family.all().count() +
self.Repository.all().count() +
self.Place.all().count() +
self.Media.all().count() +
self.Source.all().count() +
self.Citation.all().count())
for item in self.Note.all():
self.update_public(item)
count += 1
callback(100 * (count/total if total else 0))
for item in self.Person.all():
self.update_public(item)
count += 1
callback(100 * (count/total if total else 0))
for item in self.Family.all():
self.update_public(item)
count += 1
callback(100 * (count/total if total else 0))
for item in self.Source.all():
self.update_public(item)
count += 1
callback(100 * (count/total if total else 0))
for item in self.Event.all():
self.update_public(item)
count += 1
callback(100 * (count/total if total else 0))
for item in self.Repository.all():
self.update_public(item)
count += 1
callback(100 * (count/total if total else 0))
for item in self.Place.all():
self.update_public(item)
count += 1
callback(100 * (count/total if total else 0))
for item in self.Media.all():
self.update_public(item)
count += 1
callback(100 * (count/total if total else 0))
for item in self.Citation.all():
self.update_public(item)
count += 1
callback(100 * (count/total if total else 0))

View File

@ -64,6 +64,7 @@ urlpatterns += patterns('',
(r'^favicon\.ico$', 'django.views.generic.simple.redirect_to',
{'url': '/styles/images/favicon.ico'}),
(r'^user/$', user_page),
(r'^json/$', process_json_request),
(r'^user/(\w+)/$', user_page),
(r'^browse/$', browse_page),
(r'^login/$', 'django.contrib.auth.views.login'),

View File

@ -90,12 +90,11 @@ util_tags = [
"attribute_table",
"data_table",
"address_table",
"location_table",
"media_table",
"internet_table",
"association_table",
"location_table",
"lds_table",
"reference_table",
"repository_table",
"person_reference_table",
"note_reference_table",
@ -311,7 +310,7 @@ def event_table(obj, user, act, url, args):
_("Place"),
_("Role"))
table.column_widths = [10, 20, 10, 7, 20, 23, 10]
if user.is_authenticated():
if user.is_authenticated() or obj.public:
obj_type = ContentType.objects.get_for_model(obj)
event_ref_list = models.EventRef.objects.filter(
object_id=obj.id,
@ -357,7 +356,7 @@ def history_table(obj, user, act):
_("Action"),
_("Comment"),
)
if user.is_authenticated():
if user.is_authenticated() or obj.public:
obj_type = ContentType.objects.get_for_model(obj)
for entry in models.Log.objects.filter(
object_id=obj.id,
@ -388,7 +387,7 @@ def name_table(obj, user, act, url=None, *args):
_("Group As"),
_("Source"),
_("Note Preview"))
if user.is_authenticated():
if user.is_authenticated() or obj.public:
links = []
for name in obj.name_set.all().order_by("order"):
obj_type = ContentType.objects.get_for_model(name)
@ -429,7 +428,7 @@ def surname_table(obj, user, act, url=None, *args):
cssid = "tab-surnames"
table = Table("surname_table")
table.columns(_("Order"), _("Surname"),)
if user.is_authenticated():
if user.is_authenticated() or obj.public:
try:
name = obj.name_set.filter(order=order)[0]
except:
@ -450,16 +449,18 @@ def surname_table(obj, user, act, url=None, *args):
return retval
def citation_table(obj, user, act, url=None, *args):
# FIXME: how can citation_table and source_table both be on same
# page? This causes problems with form names, tab names, etc.
retval = ""
has_data = False
cssid = "tab-citations"
cssid = "tab-sources"
table = Table("citation_table")
table.columns("",
_("ID"),
_("Confidence"),
_("Page"))
table.column_widths = [10, 10, 50, 30]
if user.is_authenticated():
if user.is_authenticated() or obj.public:
obj_type = ContentType.objects.get_for_model(obj)
citation_refs = dji.CitationRef.filter(object_type=obj_type,
object_id=obj.id).order_by("order")
@ -501,14 +502,37 @@ def repository_table(obj, user, act, url=None, *args):
cssid = "tab-repositories"
table = Table("repository_table")
table.columns(
"",
_("ID"),
_("Title"),
_("Call number"),
_("Type"),
_("Note"))
if user.is_authenticated():
pass
retval += table.get_html()
## FIXME: missing table
## has_data = True
)
if user.is_authenticated() or obj.public:
obj_type = ContentType.objects.get_for_model(obj)
refs = dji.RepositoryRef.filter(object_type=obj_type,
object_id=obj.id)
count = 1
for repo_ref in refs:
repository = repo_ref.ref_object
table.row(
Link("[[x%d]][[^%d]][[v%d]]" % (count, count, count)) if user.is_superuser else "",
repository.gramps_id,
repository.name,
repo_ref.call_number,
str(repository.repository_type),
)
has_data = True
count += 1
text = table.get_html()
count = 1
for repo_ref in refs:
item = obj.__class__.__name__.lower()
text = text.replace("[[x%d]]" % count, make_button("x", "/%s/%s/remove/repositoryref/%d" % (item, obj.handle, count)))
text = text.replace("[[^%d]]" % count, make_button("^", "/%s/%s/up/repositoryref/%d" % (item, obj.handle, count)))
text = text.replace("[[v%d]]" % count, make_button("v", "/%s/%s/down/repositoryref/%d" % (item, obj.handle, count)))
count += 1
retval += text
if user.is_superuser and url and act == "view":
retval += make_button(_("Add New Repository"), (url % args).replace("$act", "add"))
retval += make_button(_("Add Existing Repository"), (url % args).replace("$act", "share"))
@ -527,16 +551,15 @@ def note_table(obj, user, act, url=None, *args):
_("ID"),
_("Type"),
_("Note"))
if user.is_authenticated():
if user.is_authenticated() or obj.public:
obj_type = ContentType.objects.get_for_model(obj)
note_refs = dji.NoteRef.filter(object_type=obj_type,
object_id=obj.id)
for note_ref in note_refs:
note = table.db.get_note_from_handle(
note_ref.ref_object.handle)
table.row(table.db.get_note_from_handle(note.handle),
str(note_ref.ref_object.note_type),
note_ref.ref_object.text[:50])
note = note_ref.ref_object
table.row(note,
str(note.note_type),
note.text[:50])
has_data = True
retval += table.get_html()
if user.is_superuser and url and act == "view":
@ -551,18 +574,43 @@ def note_table(obj, user, act, url=None, *args):
def data_table(obj, user, act, url=None, *args):
retval = ""
has_data = False
cssid = "has_data"
cssid = "tab-data"
table = Table("data_table")
table.columns(_("Type"),
_("Value"),
)
if user.is_authenticated():
pass
## FIXME: missing table
## has_data = True
retval += table.get_html()
table.columns(
"",
_("Type"),
_("Value"),
)
if user.is_authenticated() or obj.public:
item_class = obj.__class__.__name__.lower()
if item_class == "citation":
refs = models.CitationDatamap.objects.filter(citation=obj).order_by("order")
elif item_class == "source":
refs = models.SourceDatamap.objects.filter(source=obj).order_by("order")
count = 1
for ref in refs:
if item_class == "citation":
ref_obj = ref.citation
elif item_class == "source":
ref_obj = ref.source
table.row(
Link("[[x%d]][[^%d]][[v%d]]" % (count, count, count)) if user.is_superuser else "",
ref_obj.key,
ref_obj.value,
)
has_data = True
count += 1
text = table.get_html()
count = 1
for repo_ref in refs:
text = text.replace("[[x%d]]" % count, make_button("x", "/%s/%s/remove/datamap/%d" % (item_class, obj.handle, count)))
text = text.replace("[[^%d]]" % count, make_button("^", "/%s/%s/up/datamap/%d" % (item_class, obj.handle, count)))
text = text.replace("[[v%d]]" % count, make_button("v", "/%s/%s/down/datamap/%d" % (item_class, obj.handle, count)))
count += 1
retval += text
if user.is_superuser and url and act == "view":
retval += make_button(_("Add Data"), (url % args))
# /data/$act/citation/%s
retval += make_button(_("Add Data"), (url.replace("$act", "add") % args))
else:
retval += nbsp("") # to keep tabs same height
if has_data:
@ -577,7 +625,7 @@ def attribute_table(obj, user, act, url=None, *args):
table.columns(_("Type"),
_("Value"),
)
if user.is_authenticated():
if user.is_authenticated() or obj.public:
obj_type = ContentType.objects.get_for_model(obj)
attributes = dji.Attribute.filter(object_type=obj_type,
object_id=obj.id)
@ -604,7 +652,7 @@ def address_table(obj, user, act, url=None, *args):
_("City"),
_("State"),
_("Country"))
if user.is_authenticated():
if user.is_authenticated() or obj.public:
for address in obj.address_set.all().order_by("order"):
locations = address.location_set.all().order_by("order")
for location in locations:
@ -623,29 +671,6 @@ def address_table(obj, user, act, url=None, *args):
retval += """ <SCRIPT LANGUAGE="JavaScript">setHasData("%s", 1)</SCRIPT>\n""" % cssid
return retval
def location_table(obj, user, act, url=None, *args):
retval = ""
has_data = False
cssid = "tab-locations"
table = Table("location_table")
table.columns(_("Date"),
_("Address"),
_("City"),
_("State"),
_("Country"))
if user.is_authenticated():
pass # FIXME
## FIXME: missing table
## has_data = True
retval += table.get_html()
if user.is_superuser and url and act == "view":
retval += make_button(_("Add Address"), (url % args))
else:
retval += nbsp("") # to keep tabs same height
if has_data:
retval += """ <SCRIPT LANGUAGE="JavaScript">setHasData("%s", 1)</SCRIPT>\n""" % cssid
return retval
def media_table(obj, user, act, url=None, *args):
retval = ""
has_data = False
@ -655,7 +680,7 @@ def media_table(obj, user, act, url=None, *args):
_("Type"),
_("Path/Filename"),
)
if user.is_authenticated():
if user.is_authenticated() or obj.public:
obj_type = ContentType.objects.get_for_model(obj)
media_refs = dji.MediaRef.filter(object_type=obj_type,
object_id=obj.id)
@ -684,7 +709,7 @@ def internet_table(obj, user, act, url=None, *args):
table.columns(_("Type"),
_("Path"),
_("Description"))
if user.is_authenticated():
if user.is_authenticated() or obj.public:
urls = dji.Url.filter(person=obj)
for url_obj in urls:
table.row(str(url_obj.url_type),
@ -708,14 +733,29 @@ def association_table(obj, user, act, url=None, *args):
table.columns(_("Name"),
_("ID"),
_("Association"))
if user.is_authenticated():
gperson = table.db.get_person_from_handle(obj.handle)
if gperson:
associations = gperson.get_person_ref_list()
for association in associations:
table.row() # FIXME: missing table
if user.is_authenticated() or obj.public:
person = table.db.get_person_from_handle(obj.handle)
if person:
links = []
count = 1
associations = person.get_person_ref_list()
for association in associations: # PersonRef
table.row(Link("[[x%d]][[^%d]][[v%d]]" % (count, count, count)) if user.is_superuser and url and act == "view" else "",
association.ref_object.get_primary_name(),
association.ref_object.gramps_id,
association.description,
)
links.append(('URL', "/person/%s/association/%d" % (obj.handle, count)))
has_data = True
retval += table.get_html()
count += 1
table.links(links)
text = table.get_html()
count = 1
for association in associations: # PersonRef
text = text.replace("[[x%d]]" % count, make_button("x", "/person/%s/remove/association/%d" % (obj.handle, count)))
text = text.replace("[[^%d]]" % count, make_button("^", "/person/%s/up/association/%d" % (obj.handle, count)))
text = text.replace("[[v%d]]" % count, make_button("v", "/person/%s/down/association/%d" % (obj.handle, count)))
retval += text
if user.is_superuser and url and act == "view":
retval += make_button(_("Add Association"), (url % args))
else:
@ -724,6 +764,39 @@ def association_table(obj, user, act, url=None, *args):
retval += """ <SCRIPT LANGUAGE="JavaScript">setHasData("%s", 1)</SCRIPT>\n""" % cssid
return retval
def location_table(obj, user, act, url=None, *args):
# obj is Place or Address
retval = ""
has_data = False
cssid = "tab-alternatelocations"
table = Table("location_table")
table.columns(_("Street"),
_("Locality"),
_("City"),
_("State"),
_("Country"))
if user.is_authenticated() or obj.public:
# FIXME: location confusion!
# The single Location on the Location Tab is here too?
# I think if Parish is None, then these are single Locations;
# else they are in the table of alternate locations
for location in obj.location_set.all().order_by("order"):
table.row(
location.street,
location.locality,
location.city,
location.state,
location.country)
has_data = True
retval += table.get_html()
if user.is_superuser and url and act == "view":
retval += make_button(_("Add Address"), (url % args))
else:
retval += nbsp("") # to keep tabs same height
if has_data:
retval += """ <SCRIPT LANGUAGE="JavaScript">setHasData("%s", 1)</SCRIPT>\n""" % cssid
return retval
def lds_table(obj, user, act, url=None, *args):
retval = ""
has_data = False
@ -734,7 +807,7 @@ def lds_table(obj, user, act, url=None, *args):
_("Status"),
_("Temple"),
_("Place"))
if user.is_authenticated():
if user.is_authenticated() or obj.public:
obj_type = ContentType.objects.get_for_model(obj)
ldss = obj.lds_set.all().order_by("order")
for lds in ldss:
@ -753,24 +826,6 @@ def lds_table(obj, user, act, url=None, *args):
retval += """ <SCRIPT LANGUAGE="JavaScript">setHasData("%s", 1)</SCRIPT>\n""" % cssid
return retval
def reference_table(obj, user, act, url=None, *args):
retval = ""
has_data = False
cssid = "tab-references"
table = Table("reference_table")
table.columns(
_("Type"),
_("Reference"),
_("ID"))
if user.is_authenticated():
pass
## FIXME: missing table?
retval += table.get_html()
retval += nbsp("") # to keep tabs same height
if has_data:
retval += """ <SCRIPT LANGUAGE="JavaScript">setHasData("%s", 1)</SCRIPT>\n""" % cssid
return retval
def person_reference_table(obj, user, act):
retval = """<div style="overflow: auto; height:%spx;">""" % TAB_HEIGHT
has_data = False
@ -791,7 +846,7 @@ def person_reference_table(obj, user, act):
_("Reference"),
)
table2.column_widths = [10, 10, 82]
if user.is_authenticated() and act != "add":
if (user.is_authenticated() or obj.public) and act != "add":
count = 1
for through in models.MyFamilies.objects.filter(person=obj).order_by("order"):
reference = through.family
@ -852,7 +907,7 @@ def note_reference_table(obj, user, act):
_("Type"),
_("Reference"),
_("ID"))
if user.is_authenticated() and act != "add":
if (user.is_authenticated() or obj.public) and act != "add":
for reference in models.NoteRef.objects.filter(ref_object=obj):
ref_from_class = reference.object_type.model_class()
item = ref_from_class.objects.get(id=reference.object_id)
@ -876,7 +931,7 @@ def event_reference_table(obj, user, act):
_("Type"),
_("Reference"),
_("ID"))
if user.is_authenticated() and act != "add":
if (user.is_authenticated() or obj.public) and act != "add":
for reference in models.EventRef.objects.filter(ref_object=obj):
ref_from_class = reference.object_type.model_class()
try:
@ -904,7 +959,7 @@ def repository_reference_table(obj, user, act):
_("Type"),
_("Reference"),
_("ID"))
if user.is_authenticated() and act != "add":
if (user.is_authenticated() or obj.public) and act != "add":
for reference in models.RepositoryRef.objects.filter(ref_object=obj):
ref_from_class = reference.object_type.model_class()
item = ref_from_class.objects.get(id=reference.object_id)
@ -929,7 +984,7 @@ def citation_reference_table(obj, user, act):
_("Reference"),
# _("ID")
)
if user.is_authenticated() and act != "add":
if (user.is_authenticated() or obj.public) and act != "add":
for reference in models.CitationRef.objects.filter(citation=obj):
ref_from_class = reference.object_type.model_class()
item = ref_from_class.objects.get(id=reference.object_id)
@ -952,9 +1007,13 @@ def source_reference_table(obj, user, act):
_("Type"),
_("Reference"),
_("ID"))
if user.is_authenticated() and act != "add":
pass
# FIXME: where is source ref?
if (user.is_authenticated() or obj.public) and act != "add":
for item in obj.citation_set.all():
table.row(
item.__class__.__name__,
item,
item.gramps_id)
has_data = True
retval += table.get_html()
retval += nbsp("") # to keep tabs same height
if has_data:
@ -970,7 +1029,7 @@ def media_reference_table(obj, user, act):
_("Type"),
_("Reference"),
_("ID"))
if user.is_authenticated() and act != "add":
if (user.is_authenticated() or obj.public) and act != "add":
for reference in models.MediaRef.objects.filter(ref_object=obj):
ref_from_class = reference.object_type.model_class()
item = ref_from_class.objects.get(id=reference.object_id)
@ -992,11 +1051,16 @@ def place_reference_table(obj, user, act):
table = Table("place_reference_table")
table.columns(
_("Type"),
_("Reference"),
_("ID"))
if user.is_authenticated() and act != "add":
pass # FIXME
## FIXME: missing table
_("Reference"))
if (user.is_authenticated() or obj.public) and act != "add":
# location, url, event, lds
querysets = [obj.location_set, obj.url_set, obj.event_set, obj.lds_set]
for queryset in querysets:
for item in queryset.all():
table.row(
item.__class__.__name__,
item)
has_data = True
retval += table.get_html()
retval += nbsp("") # to keep tabs same height
if has_data:
@ -1012,7 +1076,7 @@ def tag_reference_table(obj, user, act):
_("Type"),
_("Reference"),
_("ID"))
if user.is_authenticated() and act != "add":
if (user.is_authenticated() or obj.public) and act != "add":
querysets = [obj.person_set, obj.family_set, obj.note_set, obj.media_set]
for queryset in querysets:
for item in queryset.all():
@ -1061,7 +1125,7 @@ def children_table(obj, user, act, url=None, *args):
count = 1
for childref in childrefs:
child = childref.ref_object
if user.is_authenticated():
if user.is_authenticated() or obj.public:
table.row(Link("[[x%d]][[^%d]][[v%d]]" % (count, count, count)) if user.is_superuser and url and act == "view" else "",
str(count),
"[%s]" % child.gramps_id,
@ -1069,7 +1133,7 @@ def children_table(obj, user, act, url=None, *args):
child.gender_type,
childref.father_rel_type,
childref.mother_rel_type,
date_as_text(child.birth, user),
date_as_text(child.birth, user) if child.birth else "",
)
has_data = True
links.append(('URL', childref.get_url()))
@ -1116,20 +1180,6 @@ def get_title(place):
else:
return ""
def person_get_birth_date(person):
#db = DbDjango()
#event = get_birth_or_fallback(db, db.get_person_from_handle(person.handle))
#if event:
# return event.date
return None
def person_get_death_date(person):
#db = DbDjango()
#event = get_death_or_fallback(db, db.get_person_from_handle(person.handle))
#if event:
# return event.date
return None
def display_date(obj):
date_tuple = dji.get_date(obj)
if date_tuple:
@ -1162,10 +1212,16 @@ def render(formfield, user, act, id=None, url=None, *args):
else:
retval = str(item)
#### Some cleanup:
if retval == "True":
retval = "Yes"
elif retval == "False":
retval = "No"
if fieldname == "private": # obj.private
if retval == "True":
retval = "Private"
elif retval == "False":
retval = "Not private"
else:
if retval == "True":
retval = "Yes"
elif retval == "False":
retval = "No"
except:
# name, "prefix"
try:
@ -1177,6 +1233,8 @@ def render(formfield, user, act, id=None, url=None, *args):
retval = formfield.as_widget(attrs={"id": id})
else:
retval = formfield.as_widget()
if formfield.name == "private":
retval += " Private"
return retval
def render_name(name, user, act=None):
@ -1236,15 +1294,15 @@ def date_as_text(obj, user):
Given a Django object, render the date as text and return. This
function uses authentication settings.
"""
if (user.is_authenticated() or
(not user.is_authenticated() and obj and not obj.private)):
if user.is_authenticated() or (obj and obj.public):
if obj:
date_tuple = dji.get_date(obj)
if date_tuple:
gdate = GDate().unserialize(date_tuple)
return dd(gdate)
return ""
return "[Private]"
else:
return ""
def person_get_event(person, event_type=None):
event_ref_list = dji.get_event_ref_list(person)
@ -1489,3 +1547,17 @@ def make_log(obj, log_type, last_changed_by, reason, cache):
cache=cache)
log.save()
def person_get_birth_date(person):
#db = DbDjango()
#event = get_birth_or_fallback(db, db.get_person_from_handle(person.handle))
#if event:
# return event.date
return None
def person_get_death_date(person):
#db = DbDjango()
#event = get_death_or_fallback(db, db.get_person_from_handle(person.handle))
#if event:
# return event.date
return None