Compare commits
1 Commits
master
...
sam-m888-p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
04d61dbc07 |
126
.travis.yml
126
.travis.yml
@ -60,6 +60,69 @@ addons:
|
||||
# https://github.com/deanmalmgren/textract/issues/19
|
||||
- zlib1g-dev
|
||||
|
||||
before_install:
|
||||
|
||||
install:
|
||||
# The working directory is set to /home/travis/build/gramps-project/gramps
|
||||
# by the automatic git checkout.
|
||||
|
||||
# Download Sean Ross-Ross's Pure Python module containing a framework to
|
||||
# manipulate and analyze python ast<73>s and bytecode. This is loaded to
|
||||
# /home/travis/build/gramps-project/gramps/meta
|
||||
# FIXME: This should be loaded from the release directory at
|
||||
# https://pypi.python.org/pypi/meta
|
||||
- git clone -b master https://github.com/srossross/meta
|
||||
|
||||
# Build Gramps package. This seems to copy everything to
|
||||
# /home/travis/build/scripts-3.3
|
||||
- python setup.py build
|
||||
|
||||
before_script:
|
||||
# Create the Gramps database directory.
|
||||
- mkdir -p ~/.gramps/grampsdb/
|
||||
# set PYTHONPATH so the directly installed module (meta) is picked up from
|
||||
# /home/travis/build/gramps-project/gramps/meta
|
||||
- export PYTHONPATH=meta
|
||||
# set module exclusions. --exclude=TestUser because of older version of mock
|
||||
# without configure_mock
|
||||
- export EXCLUDE="--exclude=TestcaseGenerator"
|
||||
# --exclude=merge_ref_test"
|
||||
# set GRAMPS_RESOURCES for locale, data,image and documentation
|
||||
- export GRAMPS_RESOURCES=.
|
||||
# Install addons
|
||||
- mkdir -p ~/.gramps/gramps52/plugins/
|
||||
- wget https://github.com/gramps-project/addons/raw/master/gramps52/download/CliMerge.addon.tgz
|
||||
- tar -C ~/.gramps/gramps52/plugins -xzf CliMerge.addon.tgz
|
||||
- wget https://github.com/gramps-project/addons/raw/master/gramps52/download/ExportRaw.addon.tgz
|
||||
- tar -C ~/.gramps/gramps52/plugins -xzf ExportRaw.addon.tgz
|
||||
|
||||
script:
|
||||
# Ignore the virtualenv entirely. Use nosetests3, python3 (3.4.0) and coverage
|
||||
# from /usr/bin. Use libraries from /usr/lib/python3.4,
|
||||
# /usr/local/lib/python3.4/dist-packages and /usr/lib/python3/dist-packages
|
||||
- nosetests3 --nologcapture --with-coverage --cover-package=gramps $EXCLUDE
|
||||
gramps
|
||||
# FIXME: This should have run from the current directory, rather than from
|
||||
# gramps, because there is some test code in that directory.
|
||||
|
||||
# give an error for any trailing whitespace
|
||||
- if git --no-pager grep --color -n --full-name '[ ]$' -- \*.py; then
|
||||
echo "ERROR - Trailing whitespace found in source file(s)";
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
after_success:
|
||||
# apt-get installs python3-coverage, but codecov only invokes coverage, so make
|
||||
# a link
|
||||
- sudo ln /usr/bin/python3-coverage /usr/bin/coverage
|
||||
|
||||
# We have to use the bash script because the apt-get coverage does not install
|
||||
# codecov. If we used pip to install codecov, it would run inside the
|
||||
# virtualenv, and that doesn't work. Change the path to ensure that codecov
|
||||
# picks up coverage from /usr/bin, rather than from
|
||||
# /home/travis/virtualenv/python3.3.6/bin/
|
||||
- PATH=/usr/bin:$PATH bash <(curl -s https://codecov.io/bash)
|
||||
|
||||
stages:
|
||||
- test
|
||||
# Only execute deployment stage on tagged commits, and from our repository
|
||||
@ -73,69 +136,6 @@ env:
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- stage: test
|
||||
name: Run unit tests
|
||||
install:
|
||||
# The working directory is set to /home/travis/build/gramps-project/gramps
|
||||
# by the automatic git checkout.
|
||||
|
||||
# Download Sean Ross-Ross's Pure Python module containing a framework to
|
||||
# manipulate and analyze python ast<73>s and bytecode. This is loaded to
|
||||
# /home/travis/build/gramps-project/gramps/meta
|
||||
# FIXME: This should be loaded from the release directory at
|
||||
# https://pypi.python.org/pypi/meta
|
||||
- git clone -b master https://github.com/srossross/meta
|
||||
|
||||
# Build Gramps package. This seems to copy everything to
|
||||
# /home/travis/build/scripts-3.3
|
||||
- python setup.py build
|
||||
|
||||
before_script:
|
||||
# Create the Gramps database directory.
|
||||
- mkdir -p ~/.gramps/grampsdb/
|
||||
# set PYTHONPATH so the directly installed module (meta) is picked up from
|
||||
# /home/travis/build/gramps-project/gramps/meta
|
||||
- export PYTHONPATH=meta
|
||||
# set module exclusions. --exclude=TestUser because of older version of mock
|
||||
# without configure_mock
|
||||
- export EXCLUDE="--exclude=TestcaseGenerator"
|
||||
# --exclude=merge_ref_test"
|
||||
# set GRAMPS_RESOURCES for locale, data,image and documentation
|
||||
- export GRAMPS_RESOURCES=.
|
||||
# Install addons
|
||||
- mkdir -p ~/.gramps/gramps52/plugins/
|
||||
- wget https://github.com/gramps-project/addons/raw/master/gramps52/download/CliMerge.addon.tgz
|
||||
- tar -C ~/.gramps/gramps52/plugins -xzf CliMerge.addon.tgz
|
||||
- wget https://github.com/gramps-project/addons/raw/master/gramps52/download/ExportRaw.addon.tgz
|
||||
- tar -C ~/.gramps/gramps52/plugins -xzf ExportRaw.addon.tgz
|
||||
|
||||
script:
|
||||
# Ignore the virtualenv entirely. Use nosetests3, python3 (3.4.0) and coverage
|
||||
# from /usr/bin. Use libraries from /usr/lib/python3.4,
|
||||
# /usr/local/lib/python3.4/dist-packages and /usr/lib/python3/dist-packages
|
||||
- nosetests3 --nologcapture --with-coverage --cover-package=gramps $EXCLUDE
|
||||
gramps
|
||||
# FIXME: This should have run from the current directory, rather than from
|
||||
# gramps, because there is some test code in that directory.
|
||||
|
||||
# give an error for any trailing whitespace
|
||||
- if git --no-pager grep --color -n --full-name '[ ]$' -- \*.py; then
|
||||
echo "ERROR - Trailing whitespace found in source file(s)";
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
after_success:
|
||||
# apt-get installs python3-coverage, but codecov only invokes coverage, so make
|
||||
# a link
|
||||
- sudo ln /usr/bin/python3-coverage /usr/bin/coverage
|
||||
|
||||
# We have to use the bash script because the apt-get coverage does not install
|
||||
# codecov. If we used pip to install codecov, it would run inside the
|
||||
# virtualenv, and that doesn't work. Change the path to ensure that codecov
|
||||
# picks up coverage from /usr/bin, rather than from
|
||||
# /home/travis/virtualenv/python3.3.6/bin/
|
||||
- PATH=/usr/bin:$PATH bash <(curl -s https://codecov.io/bash)
|
||||
|
||||
# Deploy source distribution
|
||||
- stage: deploy
|
||||
name: Deploy source distribution and wheel
|
||||
|
||||
156
FAQ
156
FAQ
@ -1,7 +1,7 @@
|
||||
**** This is Gramps Frequently Asked Questions ****
|
||||
|
||||
The questions below frequently come up in mailing list discussions and forums.
|
||||
This list is by no means complete. If you would like to add questions/answers
|
||||
This list is by no means complete. If you would like to add questions/answers
|
||||
to this list, please email your suggestions to gramps-devel@lists.sf.net
|
||||
|
||||
|
||||
@ -65,13 +65,13 @@ to this list, please email your suggestions to gramps-devel@lists.sf.net
|
||||
|
||||
24. What is the maximum database size (bytes) Gramps can handle?
|
||||
|
||||
25. How many people can Gramps database handle?
|
||||
25. How many people can Gramps database handle?
|
||||
|
||||
26. My database is really big. Is there a way around loading all the data into memory?
|
||||
|
||||
27. Can I run Gramps from a database on a NFS share?
|
||||
|
||||
28. Is the database format portable?
|
||||
28. Why is the database format not portable?
|
||||
|
||||
==Bugs and requests==
|
||||
|
||||
@ -90,41 +90,37 @@ to this list, please email your suggestions to gramps-devel@lists.sf.net
|
||||
|
||||
1. What is Gramps?
|
||||
|
||||
Gramps is the Genealogical Research and Analysis Management Program System.
|
||||
In other words, it is a personal genealogy program letting you store, edit,
|
||||
and research genealogical data using the powers of your computer.
|
||||
Gramps is the Genealogical Research and Analysis Management Program System.
|
||||
In other words, it is a personal genealogy program letting you store, edit,
|
||||
and research genealogical data using the powers of your computer.
|
||||
|
||||
|
||||
2. Where do I get it and how much does it cost?
|
||||
|
||||
Gramps can be downloaded from http://sf.net/projects/gramps at no charge.
|
||||
Gramps is an Open Source project covered by the GNU General Public License.
|
||||
You have full access to the source code and are allowed to distribute the
|
||||
program and source code freely.
|
||||
Gramps can be downloaded from http://sf.net/projects/gramps at no charge.
|
||||
Gramps is an Open Source project covered by the GNU General Public License.
|
||||
You have full access to the source code and are allowed to distribute the
|
||||
program and source code freely.
|
||||
|
||||
|
||||
3. Does Gramps exist in other languages?
|
||||
|
||||
Yes. Although developed in English, Gramps is actively translated into dozens
|
||||
of languages including: Catalan, Chinese, Croatian, Czech, Danish, Dutch,
|
||||
Esperanto, Finnish, French, German, Greek, Hebrew, Hungarian, Icelandic,
|
||||
Italian, Japanese, Lithuanian, Norwegian, Portuguese, Russian, Serbian,
|
||||
Slovak, Slovenian, Spanish, Swedish, Ukrainian and Vietnamese.
|
||||
Note: See https://www.gramps-project.org/wiki/index.php/Template:Gramps_translations for more information.
|
||||
Yes, at the moment Gramps is translated in 15 languages
|
||||
|
||||
|
||||
4. How do I keep backups?
|
||||
|
||||
Use a recent version of Gramps! From 5.0.0 onwards there is an automatic backup utility.
|
||||
It is extremely important to keep backups of your data, and keep them in a safe place. Gramps has a specific portable file format which is small, and human readable, denoted by .gramps. If you have allowed this in the preferences (In Edit->Preferences->Family Tree menu), Gramps will keep a backup of your database on exit or on shedule (every 15 minutes, 30 minutes, 1 hour, 12 hours, or 1 day). You can copy this backup file from time to time to a save location (e.g. a USB stick).
|
||||
Note: The .gramps files are compressed. Clicking them will open Gramps. To see the XML select them and open them with a decompressing utility (like ark, gunzip), after which you can extract the XML file which is human readable.
|
||||
Use a recent version of Gramps! From 2.2.5 onwards there is an automatic backup utility.
|
||||
It is extremely important to keep backups of your data, and keep them in a safe place. Gramps has a specific portable file format which is small, and human readable, denoted by .gramps. If you have allowed this in the preferences (In Edit menu->Preferences->General), Gramps will keep a backup of your database on exit. You can copy this backup file from time to time to a save location (eg a usb stick).
|
||||
|
||||
Note: The .gramps files are compressed. Clicking them will open Gramps. To see the XML select them and open them with a decompressing utility (like ark, gunzip), after which you can extract the XML file which is human readable.
|
||||
Do not keep backups in GEDCOM. Not all information Gramps stores can be written in the GEDCOM. Hence, an export/import operation Gramps --> GEDCOM --> Gramps, will mean you lose data. Use the .gramps file format for backups!
|
||||
Do not keep backups in GRDB format. GRDB is a database, which might be computer dependent (read, not working on a different PC). Small damage to a GRDB file can also not be repaired. Use the .gramps file format for backups!
|
||||
|
||||
|
||||
5. Does Gramps support Unicode fonts? In particular, does it support non-Roman Unicode fonts?
|
||||
|
||||
Yes. Gramps works internally with Unicode (UTF-8), so all alphabets can be used on all entry fields. All reports fully support this, although for PDF/PS you need to work with gnome-print or OpenOffice.
|
||||
Note: To use genealogical symbols you must install a font that provides the miscellaneous symbols in the unicode range 2600-26FF.
|
||||
Yes. Gramps works internally with Unicode (UTF-8), so all alphabets can be used on all entry fields. All reports fully support this, although for PDF/PS you need to work with gnome-print or openoffice.
|
||||
|
||||
==Installation==
|
||||
|
||||
@ -144,7 +140,7 @@ An Windows installer is available for 32 and 64 bit versions of windows from Win
|
||||
|
||||
The Fink project has ported some older versions of Gramps to OS X (tm). The Mac OS X port is not directly supported by the Gramps project, primarily because none of the Gramps developers have access to Mac OS X and because OS X is not Free Software.
|
||||
|
||||
This present version of Gramps (2.2.x) does not appear to have been ported by the Fink project. Please contact the Fink project for more information. However, some users had success in installing 2.2.x on Mac OSX either running in native mode or running on X11 using some of the fink packages.
|
||||
This present version of Gramps (2.2.x) does not appear to have been ported by the Fink project. Please contact the Fink project for more information. However, some users had success in installing 2.2.x on Mac OSX either running in native mode or running on X11 using some of the fink packages.
|
||||
|
||||
|
||||
9. What are the Minimum Specs to run Gramps?
|
||||
@ -156,7 +152,7 @@ We would recommend at least an 800x600 video display. For Gramps 5.x, Gramps can
|
||||
|
||||
10. Can I change the dates in reports to 'day month year'
|
||||
|
||||
Yes, change in the preferences ("Edit->Preferences") the date for Gramps to the required format (e.g. 'YYYY-MM-DD' or 'day month year'), and make the report. Your global date preferences will be used.
|
||||
Yes, change in the preferences ("Edit->Preferences") the date for Gramps to the required format (eg YYYY-MM-DD or day mont year), and make the report. Your global date preferences will be used.
|
||||
|
||||
|
||||
==Collaboration-Portability==
|
||||
@ -185,7 +181,7 @@ The nice thing about standards is that there never is a shortage of them. Gramps
|
||||
|
||||
15. How do I import data from another genealogy program into Gramps?
|
||||
|
||||
The best way is to create a new Gramps database file, and select the import option in the file menu. Here you select the GEDCOM you generated with the other program, and import it.
|
||||
The best way is to create a new gramps database file, and select the import option in the file menu. Here you select the GEDCOM you generated with the other program, and import it.
|
||||
|
||||
|
||||
16. Can I install Gramps on a Linux Web Server and use it via a web browser? This would enable my relations worldwide to access and update it.
|
||||
@ -203,15 +199,15 @@ You may also want to consider the effects of possible downtime of your site if y
|
||||
|
||||
17. Can Gramps print a genealogical tree for my family?
|
||||
|
||||
Yes. Different people have different ideas of what a genealogical tree is.
|
||||
Some think of it as a chart going from the distant ancestor and listing
|
||||
all his/her descendants and their families. Others think it should be a
|
||||
chart going from the person back in time, listing the ancestors and their
|
||||
families. Yet other people think of a table, text report, etc.
|
||||
Yes. Different people have different ideas of what a genealogical tree is.
|
||||
Some think of it as a chart going from the distant ancestor and listing
|
||||
all his/her descendants and their families. Others think it should be a
|
||||
chart going from the person back in time, listing the ancestors and their
|
||||
families. Yet other people think of a table, text report, etc.
|
||||
|
||||
Gramps can produce any of the above, and many more different charts and
|
||||
reports. Moreover, the plugin architechture enables users (you) to create
|
||||
their own plugins which could be new reports, charts, or research tools.
|
||||
Gramps can produce any of the above, and many more different charts and
|
||||
reports. Moreover, the plugin architechture enables users (you) to create
|
||||
their own plugins which could be new reports, charts, or research tools.
|
||||
|
||||
|
||||
18. In what formats can Gramps output its reports?
|
||||
@ -219,33 +215,33 @@ their own plugins which could be new reports, charts, or research tools.
|
||||
Text reports are available in HTML, PDF, ODT, LaTeX, and RTF formats. Graphical reports (charts and diagrams) are available in PostScript, PDF, SVG, ODS, and Graphviz formats.
|
||||
|
||||
|
||||
19. How can I change the default language in reports?
|
||||
19. How can I change the default language in reports?
|
||||
|
||||
The reports are in the language of your Linux installation. You can change it by installing extra language packs, see [Howto: Change the language of reports] on wiki.
|
||||
The reports are in the language of your linux installation. You can change it by installing extra language packs, see [Howto: Change the language of reports] on wiki.
|
||||
|
||||
|
||||
20. Is Gramps compatible with the Internet?
|
||||
|
||||
Gramps can store web addresses and direct your browser to them. It can import
|
||||
data that you download from the Internet. It can export data that you could
|
||||
send over the Internet. Gramps is familiar with the standard file formats
|
||||
widely used on the Internet (e.g. JPEG, PNG, and GIF images, MP3, OGG, and
|
||||
WAV sound files, QuickTime, MPEG, and AVI movie files, etc). Other than that,
|
||||
there is little that a genealogical program can do with the Internet :-)
|
||||
data that you download from the Internet. It can export data that you could
|
||||
send over the Internet. Gramps is familiar with the standard file formats
|
||||
widely used on the Internet (e.g. JPEG, PNG, and GIF images, MP3, OGG, and
|
||||
WAV sound files, QuickTime, MPEG, and AVI movie files, etc). Other than that,
|
||||
there is little that a genealogical program can do with the Internet :-)
|
||||
|
||||
|
||||
21. Can I create custom reports/filters/whatever?
|
||||
|
||||
Yes. There are many levels of customization. One is creating or modifying
|
||||
the templates used for the reports. This gives you some control over
|
||||
the fonts, colors, and some layout of the reports. You can also use Gramps
|
||||
controls in the report dialogs to tell what contents should be used for a
|
||||
particular report. In addition to this, you have an ability to create your
|
||||
own filters -- this is useful in selecting people based on criteria set
|
||||
by you. You can combine these filters to create new, more complex filters.
|
||||
Finally, you have an option to create your own plugins. These may be new
|
||||
reports, research tools, import/export filters, etc. This assumes some
|
||||
knowledge of programming in Python.
|
||||
Yes. There are many levels of customization. One is creating or modifying
|
||||
the templates used for the reports. This gives you some control over
|
||||
the fonts, colors, and some layout of the reports. You can also use Gramps
|
||||
controls in the report dialogs to tell what contents should be used for a
|
||||
particular report. In addition to this, you have an ability to create your
|
||||
own filters -- this is useful in selecting people based on criteria set
|
||||
by you. You can combine these filters to create new, more complex filters.
|
||||
Finally, you have an option to create your own plugins. These may be new
|
||||
reports, research tools, import/export filters, etc. This assumes some
|
||||
knowledge of programming in Python.
|
||||
|
||||
|
||||
22. Why are non-latin characters displayed as garbage in PDF/PS reports?
|
||||
@ -269,17 +265,17 @@ If you are happy with your plugin and would like to contribute your code back to
|
||||
|
||||
24. What is the maximum database size (bytes) Gramps can handle?
|
||||
|
||||
Gramps has no hard limits on the size of a database that it can handle. Starting with 2.0.0 release, Gramps no longer loads all data into memory, which allows it to work with a much larger database than before. In reality, however, there are practical limits. The main limiting factors are the available memory on the system. With common memory sizes these days, Gramps should have no problem using databases with tens of thousands of people.
|
||||
Gramps has no hard limits on the size of a database that it can handle. Starting with 2.0.0 release, Gramps no longer loads all data into memory, which allows it to work with a much larger database than before. In reality, however, there are practical limits. The main limiting factors are the available memory on the system and the cache size used for BSDDB database access. With common memory sizes these days, Gramps should have no problem using databases with tens of thousands of people.
|
||||
|
||||
|
||||
25. How many people can Gramps database handle?
|
||||
25. How many people can Gramps database handle?
|
||||
|
||||
See above. Again, this is dependent on how much memory you have, see [Gramps Performance] on wiki.
|
||||
|
||||
|
||||
26. My database is really big. Is there a way around loading all the data into memory?
|
||||
|
||||
Starting with 2.0.0 release, Gramps no longer loads all data into memory, which allows it to work with a much larger database than before.
|
||||
Starting with 2.0.0 release, Gramps no longer loads all data into memory, which allows it to work with a much larger database than before. The fileformat used is .grdb which means gramps database.
|
||||
|
||||
|
||||
27. Can I run Gramps from a database on a NFS share?
|
||||
@ -287,45 +283,55 @@ Starting with 2.0.0 release, Gramps no longer loads all data into memory, which
|
||||
Yes you can.
|
||||
|
||||
|
||||
28. Is the database format portable?
|
||||
28. Why is the database format not portable?
|
||||
|
||||
Prior to 5.0, Gramps used BSDDB as its database backend. The BSDDB database
|
||||
format is not portable.
|
||||
The biggest issue with Gramps portability lies with 'transactions'. With
|
||||
Gramps 2.2, we added support for atomic transactions to protect data.
|
||||
With atomic transactions, multiple changes are committed as a single
|
||||
unit. Either all the changes make it, or none of the changes make it.
|
||||
You are never left in a situation with a partial set of changes. A side
|
||||
benefit of using transactions is that database access (reads and writes)
|
||||
are faster.
|
||||
|
||||
Starting with 5.0, Gramps allowed the user to choose from other datbase
|
||||
backends, including SqLite. The SqLite database format is portable.
|
||||
The problem with transactions (at least using BSDDB) is that it does not
|
||||
allow all the data to be stored in a single file. Logging files are
|
||||
needed to keep track of things. These logging files are kept in a DB
|
||||
Environment directory. We need a separate directory for each file,
|
||||
otherwise the log files can interfere with each other.
|
||||
|
||||
In 2.2, we keep the log files under the ~/.gramps/ path directory,
|
||||
creating a unique directory for each database. The problem is that your
|
||||
GRDB file needs the log files, which are in a different directory.
|
||||
Copying the GRDB file is only copying a portion of the database.
|
||||
|
||||
As of 5.2, the BSDDB backend is no longer available. SqLite is used by default.
|
||||
|
||||
==Bugs and requests==
|
||||
|
||||
29. I found a bug and I want it fixed right now! What do I do?
|
||||
|
||||
The best thing you can do is to fix the bug and submit a pull request on
|
||||
GitHub :-)
|
||||
The best thing you can do is to fix the bug and send the patch to
|
||||
gramps-devel@lists.sf.net :-)
|
||||
|
||||
The next best thing would be to submit a good bug report. This can be done by
|
||||
filing your report with the bug tracker system at
|
||||
https://gramps-project.org/bugs/ (this function is also
|
||||
available by selecting "Help->Report a bug" from Gramps main menu).
|
||||
The next best thing would be to submit a good bug report. This can be done in
|
||||
one of the two ways: (1) send your report to gramps-bugs@lists.sf.net
|
||||
or (2) file your report with the bug tracker system at
|
||||
https://gramps-project.org/bugs/ (this function is also
|
||||
available by selecting "Help->Report a bug" from gramps main menu).
|
||||
|
||||
You may also discuss the problem first on our mailing list or Discourse forum.
|
||||
https://gramps-project.org/blog/contact
|
||||
|
||||
A good bug report would include:
|
||||
(1) Version of Gramps you were using when you encountered the bug
|
||||
A good bug report would include:
|
||||
(1) Version of gramps you were using when you encountered the bug
|
||||
(available through Help->About menu item)
|
||||
(2) Language under which Gramps was run
|
||||
(also available through Help->About menu item)
|
||||
(2) Language under which gramps was run
|
||||
(available by executing "echo $LANG" in your terminal)
|
||||
(3) Symptoms indicating that this is indeed a bug
|
||||
(4) Any Traceback messages, error messages, warnings, etc, that showed up
|
||||
in your terminal or a in separate traceback window
|
||||
|
||||
Most problems can be fixed quickly provided there is enough information.
|
||||
To ensure this, please follow up on your bug reports.
|
||||
Most problems can be fixed quickly provided there is enough information.
|
||||
To ensure this, please follow up on your bug reports.
|
||||
|
||||
If the above explanations seem vague, please follow this link:
|
||||
https://www.chiark.greenend.org.uk/~sgtatham/bugs.html
|
||||
http://www.chiark.greenend.org.uk/~sgtatham/bugs.html
|
||||
|
||||
|
||||
30. Gramps should be a .... type of application
|
||||
@ -333,7 +339,7 @@ https://www.chiark.greenend.org.uk/~sgtatham/bugs.html
|
||||
The surest way to see it happen is to get it done by yourself. Since Gramps is free/open source, nobody prevents you from taking all of the code and continuing its development in whatever direction you see fit. In doing so, you may consider giving your new project another name to avoid confusion with the continuing Gramps development. If you would like the Gramps project to provide advice, expertise, filters, etc., we will gladly cooperate with your new project, to ensure compatibility or import/export options to your new format of a project.
|
||||
|
||||
If, however, you would like the Gramps project to adopt your strategy, you would need to convince Gramps developers that your strategy is good for Gramps and superior to the present development strategy.
|
||||
|
||||
|
||||
HINT: if Gramps developers are still not convinced after about three
|
||||
messages sent to gramps-devel, maybe you are better off on your own
|
||||
rather than with a company of retards who can't fully realize the
|
||||
|
||||
35
INSTALL
35
INSTALL
@ -9,30 +9,30 @@ you need to remove the old version first. You can delete the old
|
||||
version by deleting the installed directories. For example, if your installation prefix is /usr/local, remove the following:
|
||||
/usr/local/share/gramps
|
||||
/usr/local/lib/pythonx.x/site-packages/gramps
|
||||
|
||||
If you installed with a package manager you might instead need to remove
|
||||
/usr/local/lib/pythonx.x/dist-packages/gramps
|
||||
|
||||
replacing pythonx.x with the Python version you used, e.g. python3.5.
|
||||
Also remove any gramps .egg files that are installed along with the Gramps
|
||||
replacing pythonx.x with the python version you used, e.g. python3.4.
|
||||
Also remove any gramps .egg files that are installed along with the gramps
|
||||
directory and the file /usr/local/bin/gramps.
|
||||
|
||||
|
||||
If you don't know the list of all files that Gramps installed, you can
|
||||
reinstall it with the --record option, and take a look at the list this
|
||||
produces (so python setup.py install --record grampsfiles.txt
|
||||
|
||||
Gramps is a Python application, so loading happens on reading the
|
||||
Gramps is a python application, so loading happens on reading the
|
||||
files, meaning that files of a previous version that are no longer
|
||||
present in the new version can still be loaded, making the new install
|
||||
unstable!
|
||||
|
||||
Distutils install
|
||||
distutils install
|
||||
-----------------
|
||||
We do not check all dependencies of Gramps, see README for a list of
|
||||
all required and optional dependencies. Missing dependencies will
|
||||
result in runtime errors.
|
||||
|
||||
To install all needed dependencies you can use (in Ubuntu):
|
||||
To install all needed dependences you can use (in Ubuntu):
|
||||
sudo apt-get build-dep gramps
|
||||
|
||||
To build and install, whether from a tarball or git repo:
|
||||
@ -42,7 +42,7 @@ To build and install, whether from a tarball or git repo:
|
||||
You can avoid using sudo for the install step by specifying a prefix to which you have write priviledge. The default is /usr/local, which is usually owned by root. You can learn of more options with
|
||||
python3 setup.py --help
|
||||
|
||||
One can use Gramps from the command line without installing it by
|
||||
One can use gramps from the command line without installing it by
|
||||
setting the following environment variables, but that won't provide
|
||||
things like MIME type and desktop entries.
|
||||
|
||||
@ -52,18 +52,19 @@ things like MIME type and desktop entries.
|
||||
See below for ways to invoke Gramps.
|
||||
|
||||
Typical install directories in linux (Ubuntu) are:
|
||||
* /usr/local/bin : the Gramps executable
|
||||
* /usr/local/lib/python3.5/dist-packages/gramps/ : the Gramps python module
|
||||
* /usr/local/share/doc/gramps : documentation, also example .gramps and .gedcom
|
||||
* /usr/local/share/icons/gnome : our icons
|
||||
* /usr/local/share/locale/xx/LC_MESSAGES : xx language code, translation
|
||||
* /usr/local/share/man/xx/man1 : xx language code, man file
|
||||
* /usr/local/lib/python3.4/dist-packages/gramps/ : the gramps python module
|
||||
* /usr/local/share/mime-info : mime info so gramps opens files automatically
|
||||
* /usr/local/share/icons/gnome : our icons
|
||||
* /usr/local/share/doc/gramps : documentation, also example .gramps and .gedcom
|
||||
* /usr/local/bin : the gramps executable
|
||||
* /usr/local/share/locale/xx/LC_MESSAGES : xx language code, translation
|
||||
* /usr/local/share/man/man1/xx/man1 : xx language code, man file
|
||||
* /usr/local/share/mime
|
||||
* /usr/local/share/mime-info : mime info so Gramps opens files automatically
|
||||
* /usr/local/share/mime-info
|
||||
|
||||
Running Gramps
|
||||
--------------
|
||||
Gramps is Python only, so no compilation is needed, you can even run Gramps
|
||||
Gramps is python only, so no compilation is needed, you can even run gramps
|
||||
from the source directory.
|
||||
|
||||
a) You installed Gramps, then you can run it with the command
|
||||
@ -78,7 +79,7 @@ from the source directory.
|
||||
The executable 'gramps' in /usr/local/bin or /usr/bin from a) does
|
||||
this for you.
|
||||
|
||||
c) You downloaded the Gramps source code to a directory, and want to run it.
|
||||
b) You downloaded the Gramps source code to a directory, and want to run it.
|
||||
You can start Gramps from the source code directory with
|
||||
|
||||
python3 Gramps.py
|
||||
@ -89,7 +90,7 @@ from the source directory.
|
||||
Custom directory installation
|
||||
-------------------------------------
|
||||
If you would like to install Gramps without being root, or in an
|
||||
alternative location on Windows, supply the --root argument to setup.py
|
||||
alternative location on windows, supply the --root argument to setup.py
|
||||
|
||||
For example:
|
||||
python3 setup.py install --root ~/test
|
||||
|
||||
57
README.md
57
README.md
@ -1,4 +1,4 @@
|
||||
The Gramps Project ( https://gramps-project.org ) [](https://travis-ci.org/gramps-project/gramps)[](https://codecov.io/github/gramps-project/gramps?branch=master)[](https://hosted.weblate.org/engage/gramps-project)
|
||||
The Gramps Project ( https://gramps-project.org ) [](https://travis-ci.org/gramps-project/gramps)[](https://codecov.io/github/gramps-project/gramps?branch=master)
|
||||
===================
|
||||
We strive to produce a genealogy program that is both intuitive for hobbyists and feature-complete for professional genealogists.
|
||||
|
||||
@ -8,13 +8,13 @@ Please read the **INSTALL** file if you intend to build from source.
|
||||
|
||||
Requirements
|
||||
============
|
||||
The following packages **MUST** be installed in order for Gramps to work:
|
||||
The following three packages **MUST** be installed in order for Gramps to work:
|
||||
|
||||
* **Python** 3.5 or greater - The programming language used by Gramps. https://www.python.org/
|
||||
* **Python** 3.3 or greater - The programming language used by Gramps. https://www.python.org/
|
||||
* **GTK** 3.12 or greater - A cross-platform widget toolkit for creating graphical user interfaces. http://www.gtk.org/
|
||||
* **pygobject** 3.12 or greater - Python Bindings for GLib/GObject/GIO/GTK+ https://wiki.gnome.org/Projects/PyGObject
|
||||
|
||||
The following three packages with GObject Introspection bindings (the gi packages)
|
||||
The following packages with GObject Introspection bindings (the gi packages)
|
||||
|
||||
* **cairo** 1.13.1 or greater - a 2D graphics library with support for multiple output devices. http://cairographics.org/
|
||||
* **Pycairo** 1.13.3 or greater - GObject Introspection bindings for cairo. https://github.com/pygobject/pycairo
|
||||
@ -34,7 +34,7 @@ to your language:
|
||||
Translation of GTK elements to your language, with
|
||||
xx your language code; e.g. for Dutch you need
|
||||
language-pack-gnome-nl. The translation of the
|
||||
Gramps strings is included with the Gramps source.
|
||||
Gramps strings is included with the gramps source.
|
||||
|
||||
|
||||
The following packages are **STRONGLY RECOMMENDED** to be installed:
|
||||
@ -45,7 +45,7 @@ The following packages are **STRONGLY RECOMMENDED** to be installed:
|
||||
It may be osmgpsmap, osm-gps-map, or python-osmgpsmap,
|
||||
but the Python bindings for this must also be present, so gir1.2-osmgpsmap-1.0.
|
||||
Without this the GeoView will not be active, see
|
||||
https://gramps-project.org/wiki/index.php?title=Gramps_5.1_Wiki_Manual_-_Categories#Geography_Category
|
||||
https://gramps-project.org/wiki/index.php?title=Gramps_5.0_Wiki_Manual_-_Categories#Geography_Category
|
||||
|
||||
* **Graphviz**
|
||||
|
||||
@ -63,27 +63,27 @@ The following packages are **STRONGLY RECOMMENDED** to be installed:
|
||||
sorting is done through built-in libraries. PyICU is
|
||||
fairly widely available through the package managers of
|
||||
distributions. See http://pyicu.osafoundation.org/
|
||||
(These are Python bindings for the ICU package
|
||||
https://pypi.python.org/pypi/PyICU/).
|
||||
(These are Python bindings for the ICU package.
|
||||
https://pypi.python.org/pypi/PyICU/)
|
||||
|
||||
* **Ghostscript**
|
||||
|
||||
Used by Graphviz reports to help create PDF files.
|
||||
Used by Graphviz reports to help create PDF's
|
||||
|
||||
The following packages are optional:
|
||||
------------------------------------
|
||||
* **gtkspell**
|
||||
* **gtkspell**
|
||||
|
||||
Enable spell checking in the notes. Gtkspell depends on
|
||||
enchant. A version of gtkspell with gobject introspection
|
||||
is needed, so minimally version 3.0.0.
|
||||
is needed, so minimally version 3.0.0
|
||||
|
||||
* **rcs**
|
||||
|
||||
The GNU Revision Control System (RCS) can be used to manage
|
||||
multiple revisions of your family trees. See info at
|
||||
https://gramps-project.org/wiki/index.php?title=Gramps_5.1_Wiki_Manual_-_Manage_Family_Trees#Archiving_a_Family_Tree
|
||||
Only rcs is needed, NO python bindings are required.
|
||||
https://gramps-project.org/wiki/index.php?title=Gramps_5.0_Wiki_Manual_-_Manage_Family_Trees#Archiving_a_Family_Tree
|
||||
Only rcs is needed, NO python bindings are required
|
||||
|
||||
* **PIL**
|
||||
|
||||
@ -91,7 +91,7 @@ The following packages are optional:
|
||||
images and also to convert non-JPG images to
|
||||
JPG so as to include them in LaTeX output.
|
||||
(For Python3 a different source may be needed,
|
||||
python-imaging or python-pillow or python3-pillow).
|
||||
python-imaging or python-pillow or python3-pillow)
|
||||
|
||||
* **GExiv2**
|
||||
|
||||
@ -101,7 +101,7 @@ The following packages are optional:
|
||||
|
||||
* **ttf-freefont**
|
||||
|
||||
Provides genealogical symbols and more fonts for reports
|
||||
More font support in the reports
|
||||
|
||||
* **geocodeglib**
|
||||
|
||||
@ -120,24 +120,6 @@ The following packages are optional:
|
||||
Python bindings of fontconfig are required for displaying
|
||||
genealogical symbols
|
||||
|
||||
* **magic**
|
||||
|
||||
Python magic bindings required to have better performances with image
|
||||
processing.
|
||||
If this module is not available, we continue to use Gdk.
|
||||
This avoid to load the image in memory. This is a real improvement
|
||||
when we have many big images.
|
||||
Used in odfdoc, rtfdoc and webreport and tested with png, gif, jpeg, bmp, tiff
|
||||
#
|
||||
# file size with magic without (Gdk) ratio
|
||||
# example 1 : 256k 0.00080 0.00575 7
|
||||
# example 2 : 21M 0.00171 0.55860 326
|
||||
|
||||
Debian, Ubuntu, ... : python3-magic
|
||||
Fedora, Redhat, ... : python3-magic
|
||||
openSUSE : python-magic
|
||||
ArchLinux : python-magic
|
||||
|
||||
Optional packages required by Third-party Addons
|
||||
------------------------------------------------
|
||||
|
||||
@ -181,12 +163,3 @@ The User Manual is maintained on the Gramps website:
|
||||
|
||||
* https://www.gramps-project.org/wiki/index.php?title=User_manual
|
||||
|
||||
Issue Tracker
|
||||
-------------
|
||||
Gramps bug and issue tracker can be found [here](https://gramps-project.org/bugs/my_view_page.php).
|
||||
|
||||
Translation
|
||||
-------------
|
||||
Gramps uses Hosted Weblate for its translations:
|
||||
|
||||
* https://hosted.weblate.org/engage/gramps-project
|
||||
|
||||
@ -162,7 +162,6 @@ a[href]:hover, a[href]:active {
|
||||
----------------------------------------------------- */
|
||||
div#nav, #subnavigation {
|
||||
border: solid 1px #EEE; /* needed by IE7 */
|
||||
position: relative;
|
||||
}
|
||||
#subnavigation ul {
|
||||
overflow: hidden;
|
||||
@ -200,35 +199,6 @@ div#nav ul li.CurrentSection a {
|
||||
#subnavigation ul li.CurrentSection a {
|
||||
background-color: white;
|
||||
}
|
||||
div#nav li.lang {
|
||||
font-size: smaller;
|
||||
font-family: sans-serif;
|
||||
padding-top: .4em;
|
||||
padding-bottom: .2em;
|
||||
font-weight: bold;
|
||||
}
|
||||
div#nav li.lang:hover > ul {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
div#nav ul.lang {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
z-index: 999;
|
||||
background-color: #EEE;
|
||||
top: -1em;
|
||||
font-size: larger;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
div#nav ul.lang:hover {
|
||||
float: initial;
|
||||
padding-left: 0px;
|
||||
}
|
||||
div#nav ul.lang li {
|
||||
float: none;
|
||||
padding: 2px;
|
||||
}
|
||||
/* Alphabet Navigation
|
||||
----------------------------------------------------- */
|
||||
div#alphanav {
|
||||
@ -346,21 +316,6 @@ div#nav::after {
|
||||
.content {
|
||||
padding: 0em 0.5em;
|
||||
}
|
||||
.lang {
|
||||
position: relative;
|
||||
}
|
||||
.lang > .lang {
|
||||
top: 0;
|
||||
left: 100%;
|
||||
margin-top: -6px;
|
||||
margin-left: -1px;
|
||||
-webkit-border-radius: 0 6px 6px 6px;
|
||||
-moz-border-radius: 0 6px 6px 6px;
|
||||
border-radius: 0 6px 6px 6px;
|
||||
}
|
||||
.lang:hover > .lang {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
/* Main Table
|
||||
@ -636,13 +591,11 @@ div#SourceDetail {
|
||||
|
||||
/* Subsection
|
||||
----------------------------------------------------- */
|
||||
#Home #GalleryDisplay, #Introduction #GalleryDisplay,
|
||||
#Contact #GalleryDisplay {
|
||||
#Home #GalleryDisplay, #Introduction #GalleryDisplay {
|
||||
float: right;
|
||||
margin: 1em;
|
||||
}
|
||||
#Home #GalleryDisplay img, #Introduction #GalleryDisplay img,
|
||||
#Contact #GalleryDisplay img {
|
||||
#Home #GalleryDisplay img, #Introduction #GalleryDisplay img {
|
||||
display: block;
|
||||
max-width: 950px;
|
||||
height: auto;
|
||||
@ -660,7 +613,7 @@ div#SourceDetail {
|
||||
}
|
||||
.subsection {
|
||||
clear: both;
|
||||
overflow-x: auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
.subsection p {
|
||||
margin: 0px;
|
||||
@ -672,10 +625,6 @@ div#SourceDetail {
|
||||
table.relationships tr:hover {
|
||||
background-color: #DDE;
|
||||
}
|
||||
div.content table.tags {
|
||||
text-align: left;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
div#families table.fixed_subtables table.eventlist {
|
||||
table-layout: fixed;
|
||||
@ -707,12 +656,6 @@ div#families table.fixed_subtables .Child table.eventlist .ColumnDate {
|
||||
#indivgallery {
|
||||
background-color: white;
|
||||
}
|
||||
#indivgallery a {
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
word-wrap: break-word;
|
||||
display: block;
|
||||
}
|
||||
#gallery .gallerycell {
|
||||
float: left;
|
||||
width: 130px;
|
||||
@ -729,8 +672,7 @@ div#families table.fixed_subtables .Child table.eventlist .ColumnDate {
|
||||
}
|
||||
#indivgallery .thumbnail {
|
||||
float: left;
|
||||
width: 160px;
|
||||
height: 220px;
|
||||
width: 130px;
|
||||
font-size: smaller;
|
||||
text-align: center;
|
||||
margin: 0.8em 0.5em;
|
||||
@ -801,14 +743,6 @@ i + div.grampsstylednote p {
|
||||
div.grampsstylednote p {
|
||||
padding-bottom: 0.6em;
|
||||
}
|
||||
div.grampsstylednote a {
|
||||
text-decoration: underline;
|
||||
font-weight: bold;
|
||||
color: #555;
|
||||
}
|
||||
div.grampsstylednote a:visited {
|
||||
color: red;
|
||||
}
|
||||
|
||||
/* Subsection : Family Map
|
||||
----------------------------------------------------- */
|
||||
@ -827,34 +761,8 @@ a.family_map {
|
||||
|
||||
/* Subsection : Source References
|
||||
----------------------------------------------------- */
|
||||
#sourcerefs ol#srcr {
|
||||
counter-reset: itema;
|
||||
list-style-type: none;
|
||||
display: block;
|
||||
margin-top: .1em;
|
||||
}
|
||||
#sourcerefs ol#citr {
|
||||
counter-reset: itemb;
|
||||
list-style-type: none;
|
||||
}
|
||||
#sourcerefs ol#srcr > li::before {
|
||||
content: counter(itema);
|
||||
}
|
||||
#sourcerefs ol#citr > li::before {
|
||||
content: counter(itema)counter(itemb, lower-alpha);
|
||||
}
|
||||
#sourcerefs ol#srcr > li {
|
||||
counter-increment: itema;
|
||||
margin-top: .1em;
|
||||
}
|
||||
#sourcerefs ol#citr > li {
|
||||
counter-increment: itemb;
|
||||
margin-top: .1em;
|
||||
}
|
||||
#sourcerefs ol#citr ul {
|
||||
list-style: none;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
#sourcerefs ol li ol {
|
||||
list-style-type: lower-alpha;
|
||||
}
|
||||
|
||||
/* Subsection : Pedigree
|
||||
@ -1074,43 +982,3 @@ body#fullyearlinked #YearGlance tbody td:hover .date {
|
||||
border-radius: 45px;
|
||||
border: 5px solid;
|
||||
}
|
||||
h4 button.icon {
|
||||
width: 0.9em;
|
||||
border: 0px solid;
|
||||
padding: 0;
|
||||
opacity: 1;
|
||||
transform: rotate(90deg);
|
||||
transition: transform 200ms ease-out 0s;
|
||||
background: transparent;
|
||||
}
|
||||
h4 button.icon-close {
|
||||
transform: rotate(90deg);
|
||||
transition: transform 0.2s linear;
|
||||
}
|
||||
h4 button.icon-open {
|
||||
transform: rotate(180deg);
|
||||
transition: transform 0.2s linear;
|
||||
}
|
||||
svg {
|
||||
fill: black;
|
||||
}
|
||||
/* Go to the top of the page */
|
||||
#gototop {
|
||||
display: none;
|
||||
position: fixed;
|
||||
bottom: 10px;
|
||||
right: 20px;
|
||||
z-index: 999;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
color: black;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#gototop:hover {
|
||||
background-color: #CCC;
|
||||
}
|
||||
|
||||
@ -254,7 +254,6 @@ p#user_header {
|
||||
div#nav, #subnavigation {
|
||||
border: solid 1px #EEE; /* needed by IE7 */
|
||||
background-color: #13A926;
|
||||
position: relative;
|
||||
}
|
||||
#subnavigation ul {
|
||||
overflow: hidden;
|
||||
@ -292,33 +291,6 @@ div#nav ul li.CurrentSection a {
|
||||
#nav ul li.CurrentSection a:hover {
|
||||
background-color: #903;
|
||||
}
|
||||
div#nav li.lang {
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
padding-top: .5em;
|
||||
}
|
||||
div#nav li.lang:hover > ul {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
div#nav ul.lang {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
z-index: 999;
|
||||
background-color: #EEE;
|
||||
border-bottom: solid 1px #999;
|
||||
padding: 2px 1px;
|
||||
top: -1em;
|
||||
}
|
||||
div#nav ul.lang:hover {
|
||||
float: initial;
|
||||
}
|
||||
div#nav ul.lang li {
|
||||
float: none;
|
||||
font-size: larger;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
/* Webcal
|
||||
----------------------------------------------------- */
|
||||
@ -498,21 +470,6 @@ div#nav::after {
|
||||
.content {
|
||||
padding: 0em 0.5em;
|
||||
}
|
||||
.lang {
|
||||
position: relative;
|
||||
}
|
||||
.lang > .lang {
|
||||
top: 0;
|
||||
left: 100%;
|
||||
margin-top: -6px;
|
||||
margin-left: -1px;
|
||||
-webkit-border-radius: 0 6px 6px 6px;
|
||||
-moz-border-radius: 0 6px 6px 6px;
|
||||
border-radius: 0 6px 6px 6px;
|
||||
}
|
||||
.lang:hover > .lang {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
/* Main Table
|
||||
@ -695,10 +652,6 @@ div#RelationshipList, div#RelationshipDetail {
|
||||
div#RelationshipDetail div#FamilyDetail table.infolist tbody tr td {
|
||||
border: none;
|
||||
}
|
||||
div.content table.tags {
|
||||
text-align: left;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
/* Places
|
||||
=================================================----- */
|
||||
@ -1440,8 +1393,7 @@ div.Residence table.infolist tr td {
|
||||
#indivgallery .thumbnail {
|
||||
margin: 0;
|
||||
float: left;
|
||||
width: 160px;
|
||||
height: 220px;
|
||||
width: 130px;
|
||||
text-align: center;
|
||||
background-color: white;
|
||||
}
|
||||
@ -1540,34 +1492,18 @@ div#References {
|
||||
|
||||
/* Subsections : Source References
|
||||
----------------------------------------------------- */
|
||||
#sourcerefs ol#srcr {
|
||||
counter-reset: itema;
|
||||
list-style-type: none;
|
||||
display: block;
|
||||
margin-top: .1em;
|
||||
div#sourcerefs {
|
||||
padding: 0;
|
||||
margin: 0 auto;
|
||||
}
|
||||
#sourcerefs ol#citr {
|
||||
counter-reset: itemb;
|
||||
list-style-type: none;
|
||||
div#sourcerefs ol {
|
||||
list-style-type: decimal;
|
||||
}
|
||||
#sourcerefs ol#srcr > li::before {
|
||||
content: counter(itema);
|
||||
div#sourcerefs ol li ol {
|
||||
list-style-type: lower-alpha;
|
||||
}
|
||||
#sourcerefs ol#citr > li::before {
|
||||
content: counter(itema)counter(itemb, lower-alpha);
|
||||
}
|
||||
#sourcerefs ol#srcr > li {
|
||||
counter-increment: itema;
|
||||
margin-top: .1em;
|
||||
}
|
||||
#sourcerefs ol#citr > li {
|
||||
counter-increment: itemb;
|
||||
margin-top: .1em;
|
||||
}
|
||||
#sourcerefs ol#citr ul {
|
||||
list-style: none;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
div#sourcerefs ol li a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Subsections : Summary Area
|
||||
@ -1899,43 +1835,3 @@ body#fullyearlinked #YearGlance tbody td:hover .date {
|
||||
border-radius: 45px;
|
||||
border: 5px solid;
|
||||
}
|
||||
h4 button.icon {
|
||||
width: 0.9em;
|
||||
border: 0px solid;
|
||||
padding: 0;
|
||||
opacity: 1;
|
||||
transform: rotate(90deg);
|
||||
transition: transform 200ms ease-out 0s;
|
||||
background: transparent;
|
||||
}
|
||||
h4 button.icon-close {
|
||||
transform: rotate(90deg);
|
||||
transition: transform 0.2s linear;
|
||||
}
|
||||
h4 button.icon-open {
|
||||
transform: rotate(180deg);
|
||||
transition: transform 0.2s linear;
|
||||
}
|
||||
svg {
|
||||
fill: #13A926;
|
||||
}
|
||||
/* Go to the top of the page */
|
||||
#gototop {
|
||||
display: none;
|
||||
position: fixed;
|
||||
bottom: 10px;
|
||||
right: 20px;
|
||||
z-index: 999;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
color: black;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#gototop:hover {
|
||||
background-color: #BCEAF6;
|
||||
}
|
||||
|
||||
@ -163,7 +163,6 @@ a[href]:hover, a[href]:active {
|
||||
----------------------------------------------------- */
|
||||
div#nav, #subnavigation {
|
||||
border: solid 1px #454; /* needed by IE7 */
|
||||
position: relative;
|
||||
}
|
||||
#subnavigation ul {
|
||||
overflow: hidden;
|
||||
@ -204,36 +203,6 @@ div#nav ul li.CurrentSection a {
|
||||
color: #454;
|
||||
background-color: white;
|
||||
}
|
||||
div#nav li.lang {
|
||||
color: #E0E6E0;
|
||||
font-size: smaller;
|
||||
font-family: sans-serif;
|
||||
padding-top: .3em;
|
||||
padding-bottom: .3em;
|
||||
font-weight: bold;
|
||||
}
|
||||
div#nav li.lang:hover > ul {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
div#nav ul.lang {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
z-index: 999;
|
||||
padding: 0px;
|
||||
background-color: #454;
|
||||
top: -1em;
|
||||
font-size: larger;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
div#nav ul.lang:hover {
|
||||
float: initial;
|
||||
}
|
||||
div#nav ul.lang li {
|
||||
float: none;
|
||||
padding: 1px 2px;
|
||||
}
|
||||
/* Alphabet Navigation
|
||||
----------------------------------------------------- */
|
||||
div#alphanav {
|
||||
@ -357,21 +326,6 @@ div#nav::after {
|
||||
.content {
|
||||
padding: 0em 0.5em;
|
||||
}
|
||||
.lang {
|
||||
position: relative;
|
||||
}
|
||||
.lang > .lang {
|
||||
top: 0;
|
||||
left: 100%;
|
||||
margin-top: -6px;
|
||||
margin-left: -1px;
|
||||
-webkit-border-radius: 0 6px 6px 6px;
|
||||
-moz-border-radius: 0 6px 6px 6px;
|
||||
border-radius: 0 6px 6px 6px;
|
||||
}
|
||||
.lang:hover > .lang {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
/* Main Table
|
||||
@ -724,7 +678,7 @@ div#SourceDetail {
|
||||
}
|
||||
.subsection {
|
||||
clear: both;
|
||||
overflow-x: auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
.subsection p {
|
||||
margin: 0px;
|
||||
@ -736,10 +690,6 @@ div#SourceDetail {
|
||||
table.relationships tr:hover {
|
||||
background-color: #9DBF9D;
|
||||
}
|
||||
div.content table.tags {
|
||||
text-align: left;
|
||||
width: auto;
|
||||
}
|
||||
div#families table.fixed_subtables table.eventlist {
|
||||
table-layout: fixed;
|
||||
}
|
||||
@ -761,12 +711,6 @@ div#families table.attrlist td.ColumnType {
|
||||
#indivgallery {
|
||||
background-color: white;
|
||||
}
|
||||
#indivgallery a {
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
word-wrap: break-word;
|
||||
display: block;
|
||||
}
|
||||
#gallery .gallerycell {
|
||||
float: left;
|
||||
width: 130px;
|
||||
@ -783,8 +727,7 @@ div#families table.attrlist td.ColumnType {
|
||||
}
|
||||
#indivgallery .thumbnail {
|
||||
float: left;
|
||||
width: 160px;
|
||||
height: 220px;
|
||||
width: 130px;
|
||||
font-size: smaller;
|
||||
text-align: center;
|
||||
margin: 0.8em 0.5em;
|
||||
@ -855,14 +798,6 @@ i + div.grampsstylednote p {
|
||||
div.grampsstylednote p {
|
||||
padding-bottom: 0.6em;
|
||||
}
|
||||
div.grampsstylednote a {
|
||||
text-decoration: underline;
|
||||
font-weight: bold;
|
||||
color: #9DBF9D;
|
||||
}
|
||||
div.grampsstylednote a:visited {
|
||||
color: red;
|
||||
}
|
||||
|
||||
/* Subsection : References
|
||||
----------------------------------------------------- */
|
||||
@ -881,34 +816,8 @@ a.family_map {
|
||||
|
||||
/* Subsection : Source References
|
||||
----------------------------------------------------- */
|
||||
#sourcerefs ol#srcr {
|
||||
counter-reset: itema;
|
||||
list-style-type: none;
|
||||
display: block;
|
||||
margin-top: .1em;
|
||||
}
|
||||
#sourcerefs ol#citr {
|
||||
counter-reset: itemb;
|
||||
list-style-type: none;
|
||||
}
|
||||
#sourcerefs ol#srcr > li::before {
|
||||
content: counter(itema);
|
||||
}
|
||||
#sourcerefs ol#citr > li::before {
|
||||
content: counter(itema)counter(itemb, lower-alpha);
|
||||
}
|
||||
#sourcerefs ol#srcr > li {
|
||||
counter-increment: itema;
|
||||
margin-top: .1em;
|
||||
}
|
||||
#sourcerefs ol#citr > li {
|
||||
counter-increment: itemb;
|
||||
margin-top: .1em;
|
||||
}
|
||||
#sourcerefs ol#citr ul {
|
||||
list-style: none;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
#sourcerefs ol li ol {
|
||||
list-style-type: lower-alpha;
|
||||
}
|
||||
|
||||
/* Subsection : Pedigree
|
||||
@ -1136,43 +1045,3 @@ body#fullyearlinked #YearGlance tbody td:hover .date {
|
||||
border-radius: 45px;
|
||||
border: 5px solid;
|
||||
}
|
||||
h4 button.icon {
|
||||
width: 0.9em;
|
||||
border: 0px solid;
|
||||
padding: 0;
|
||||
opacity: 1;
|
||||
transform: rotate(90deg);
|
||||
transition: transform 200ms ease-out 0s;
|
||||
background: transparent;
|
||||
}
|
||||
h4 button.icon-close {
|
||||
transform: rotate(90deg);
|
||||
transition: transform 0.2s linear;
|
||||
}
|
||||
h4 button.icon-open {
|
||||
transform: rotate(180deg);
|
||||
transition: transform 0.2s linear;
|
||||
}
|
||||
svg {
|
||||
fill: #9DBF9D;
|
||||
}
|
||||
/* Go to the top of the page */
|
||||
#gototop {
|
||||
display: none;
|
||||
position: fixed;
|
||||
bottom: 10px;
|
||||
right: 20px;
|
||||
z-index: 999;
|
||||
border: none;
|
||||
background-color: white;
|
||||
color: black;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#gototop:hover {
|
||||
background-color: #E0E6E0;
|
||||
}
|
||||
|
||||
@ -164,7 +164,6 @@ a[href]:hover, a[href]:active {
|
||||
----------------------------------------------------- */
|
||||
div#nav, #subnavigation {
|
||||
border: solid 1px #E0E0E9; /* needed by IE7 */
|
||||
position: relative;
|
||||
}
|
||||
#subnavigation ul {
|
||||
overflow: hidden;
|
||||
@ -202,35 +201,6 @@ div#nav ul li.CurrentSection a {
|
||||
#subnavigation ul li.CurrentSection a {
|
||||
background-color: #FAFAFF;
|
||||
}
|
||||
div#nav li.lang {
|
||||
font-size: smaller;
|
||||
font-family: sans-serif;
|
||||
padding-top: .3em;
|
||||
padding-bottom: .3em;
|
||||
font-weight: bold;
|
||||
}
|
||||
div#nav li.lang:hover > ul {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
div#nav ul.lang {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
z-index: 999;
|
||||
padding: 2px;
|
||||
background-color: #E0E0E9;
|
||||
top: -1em;
|
||||
font-size: larger;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
div#nav ul.lang:hover {
|
||||
float: initial;
|
||||
}
|
||||
div#nav ul.lang li {
|
||||
float: none;
|
||||
padding: 1px 2px;
|
||||
}
|
||||
|
||||
/* Alphabet Navigation
|
||||
----------------------------------------------------- */
|
||||
@ -349,21 +319,6 @@ div#nav::after {
|
||||
.content {
|
||||
padding: 0em 0.5em;
|
||||
}
|
||||
.lang {
|
||||
position: relative;
|
||||
}
|
||||
.lang > .lang {
|
||||
top: 0;
|
||||
left: 100%;
|
||||
margin-top: -6px;
|
||||
margin-left: -1px;
|
||||
-webkit-border-radius: 0 6px 6px 6px;
|
||||
-moz-border-radius: 0 6px 6px 6px;
|
||||
border-radius: 0 6px 6px 6px;
|
||||
}
|
||||
.lang:hover > .lang {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
/* Main Table
|
||||
@ -720,7 +675,7 @@ div#SourceDetail {
|
||||
}
|
||||
.subsection {
|
||||
clear: both;
|
||||
overflow-x: auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
.subsection p {
|
||||
margin: 0px;
|
||||
@ -732,10 +687,6 @@ div#SourceDetail {
|
||||
table.relationships tr:hover {
|
||||
background-color: #B4B4CB;
|
||||
}
|
||||
div.content table.tags {
|
||||
text-align: left;
|
||||
width: auto;
|
||||
}
|
||||
div#families table.fixed_subtables table.eventlist {
|
||||
table-layout: fixed;
|
||||
}
|
||||
@ -757,12 +708,6 @@ div#families table.attrlist td.ColumnType {
|
||||
#indivgallery {
|
||||
background-color: white;
|
||||
}
|
||||
#indivgallery a {
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
word-wrap: break-word;
|
||||
display: block;
|
||||
}
|
||||
#gallery .gallerycell {
|
||||
float: left;
|
||||
width: 130px;
|
||||
@ -779,8 +724,7 @@ div#families table.attrlist td.ColumnType {
|
||||
}
|
||||
#indivgallery .thumbnail {
|
||||
float: left;
|
||||
width: 160px;
|
||||
height: 220px;
|
||||
width: 130px;
|
||||
font-size: smaller;
|
||||
text-align: center;
|
||||
margin: 0.8em 0.5em;
|
||||
@ -851,14 +795,6 @@ i + div.grampsstylednote p {
|
||||
div.grampsstylednote p {
|
||||
padding-bottom: 0.6em;
|
||||
}
|
||||
div.grampsstylednote a {
|
||||
text-decoration: underline;
|
||||
font-weight: bold;
|
||||
color: #2E2E61;
|
||||
}
|
||||
div.grampsstylednote a:visited {
|
||||
color: red;
|
||||
}
|
||||
|
||||
/* Subsection : References
|
||||
----------------------------------------------------- */
|
||||
@ -877,34 +813,8 @@ a.family_map {
|
||||
|
||||
/* Subsection : Source References
|
||||
----------------------------------------------------- */
|
||||
#sourcerefs ol#srcr {
|
||||
counter-reset: itema;
|
||||
list-style-type: none;
|
||||
display: block;
|
||||
margin-top: .1em;
|
||||
}
|
||||
#sourcerefs ol#citr {
|
||||
counter-reset: itemb;
|
||||
list-style-type: none;
|
||||
}
|
||||
#sourcerefs ol#srcr > li::before {
|
||||
content: counter(itema);
|
||||
}
|
||||
#sourcerefs ol#citr > li::before {
|
||||
content: counter(itema)counter(itemb, lower-alpha);
|
||||
}
|
||||
#sourcerefs ol#srcr > li {
|
||||
counter-increment: itema;
|
||||
margin-top: .1em;
|
||||
}
|
||||
#sourcerefs ol#citr > li {
|
||||
counter-increment: itemb;
|
||||
margin-top: .1em;
|
||||
}
|
||||
#sourcerefs ol#citr ul {
|
||||
list-style: none;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
#sourcerefs ol li ol {
|
||||
list-style-type: lower-alpha;
|
||||
}
|
||||
|
||||
/* Subsection : Pedigree
|
||||
@ -1135,43 +1045,3 @@ body#fullyearlinked #YearGlance tbody td:hover .date {
|
||||
border-radius: 45px;
|
||||
border: 5px solid;
|
||||
}
|
||||
h4 button.icon {
|
||||
width: 0.9em;
|
||||
border: 0px solid;
|
||||
padding: 0;
|
||||
opacity: 1;
|
||||
transform: rotate(90deg);
|
||||
transition: transform 200ms ease-out 0s;
|
||||
background: transparent;
|
||||
}
|
||||
h4 button.icon-close {
|
||||
transform: rotate(90deg);
|
||||
transition: transform 0.2s linear;
|
||||
}
|
||||
h4 button.icon-open {
|
||||
transform: rotate(180deg);
|
||||
transition: transform 0.2s linear;
|
||||
}
|
||||
svg {
|
||||
fill: #2E2E61;
|
||||
}
|
||||
/* Go to the top of the page */
|
||||
#gototop {
|
||||
display: none;
|
||||
position: fixed;
|
||||
bottom: 10px;
|
||||
right: 20px;
|
||||
z-index: 999;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
color: black;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#gototop:hover {
|
||||
background-color: #E0E0E9;
|
||||
}
|
||||
|
||||
@ -164,7 +164,6 @@ a[href]:hover, a[href]:active {
|
||||
----------------------------------------------------- */
|
||||
div#nav, #subnavigation {
|
||||
border: solid 1px #FFE09F; /* needed by IE7 */
|
||||
position: relative;
|
||||
}
|
||||
#subnavigation ul {
|
||||
overflow: hidden;
|
||||
@ -202,35 +201,6 @@ div#nav ul li.CurrentSection a {
|
||||
#subnavigation ul li.CurrentSection a {
|
||||
background-color: #FFFBE7;
|
||||
}
|
||||
div#nav li.lang {
|
||||
font-size: smaller;
|
||||
font-family: sans-serif;
|
||||
padding-top: .3em;
|
||||
padding-bottom: .3em;
|
||||
font-weight: bold;
|
||||
}
|
||||
div#nav li.lang:hover > ul {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
div#nav ul.lang {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
z-index: 999;
|
||||
padding: 5px 2px;
|
||||
background-color: #FFE09F;
|
||||
top: -1em;
|
||||
font-size: larger;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
div#nav ul.lang:hover {
|
||||
float: initial;
|
||||
}
|
||||
div#nav ul.lang li {
|
||||
float: none;
|
||||
padding: 1px 2px;
|
||||
}
|
||||
|
||||
/* Alphabet Navigation
|
||||
----------------------------------------------------- */
|
||||
@ -349,21 +319,6 @@ div#nav::after {
|
||||
.content {
|
||||
padding: 0em 0.5em;
|
||||
}
|
||||
.lang {
|
||||
position: relative;
|
||||
}
|
||||
.lang > .lang {
|
||||
top: 0;
|
||||
left: 100%;
|
||||
margin-top: -6px;
|
||||
margin-left: -1px;
|
||||
-webkit-border-radius: 0 6px 6px 6px;
|
||||
-moz-border-radius: 0 6px 6px 6px;
|
||||
border-radius: 0 6px 6px 6px;
|
||||
}
|
||||
.lang:hover > .lang {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
/* Main Table
|
||||
@ -721,7 +676,7 @@ div#SourceDetail {
|
||||
}
|
||||
.subsection {
|
||||
clear: both;
|
||||
overflow-x: auto;
|
||||
overflow: visible;
|
||||
}
|
||||
.subsection p {
|
||||
margin: 0px;
|
||||
@ -733,10 +688,6 @@ div#SourceDetail {
|
||||
table.relationships tr:hover {
|
||||
background-color: #FFC35E;
|
||||
}
|
||||
div.content table.tags {
|
||||
text-align: left;
|
||||
width: auto;
|
||||
}
|
||||
div#families table.fixed_subtables table.eventlist {
|
||||
table-layout: fixed;
|
||||
}
|
||||
@ -758,12 +709,6 @@ div#families table.attrlist td.ColumnType {
|
||||
#indivgallery {
|
||||
background-color: white;
|
||||
}
|
||||
#indivgallery a {
|
||||
color: #36220B;
|
||||
text-decoration: none;
|
||||
word-wrap: break-word;
|
||||
display: block;
|
||||
}
|
||||
#gallery .gallerycell {
|
||||
float: left;
|
||||
width: 130px;
|
||||
@ -780,8 +725,7 @@ div#families table.attrlist td.ColumnType {
|
||||
}
|
||||
#indivgallery .thumbnail {
|
||||
float: left;
|
||||
width: 160px;
|
||||
height: 220px;
|
||||
width: 130px;
|
||||
font-size: smaller;
|
||||
text-align: center;
|
||||
margin: 0.8em 0.5em;
|
||||
@ -852,14 +796,6 @@ i + div.grampsstylednote p {
|
||||
div.grampsstylednote p {
|
||||
padding-bottom: 0.6em;
|
||||
}
|
||||
div.grampsstylednote a {
|
||||
text-decoration: underline;
|
||||
font-weight: bold;
|
||||
color: #EA8414;
|
||||
}
|
||||
div.grampsstylednote a:visited {
|
||||
color: red;
|
||||
}
|
||||
|
||||
/* Subsection : References
|
||||
----------------------------------------------------- */
|
||||
@ -878,34 +814,8 @@ a.family_map {
|
||||
|
||||
/* Subsection : Source References
|
||||
----------------------------------------------------- */
|
||||
#sourcerefs ol#srcr {
|
||||
counter-reset: itema;
|
||||
list-style-type: none;
|
||||
display: block;
|
||||
margin-top: .1em;
|
||||
}
|
||||
#sourcerefs ol#citr {
|
||||
counter-reset: itemb;
|
||||
list-style-type: none;
|
||||
}
|
||||
#sourcerefs ol#srcr > li::before {
|
||||
content: counter(itema);
|
||||
}
|
||||
#sourcerefs ol#citr > li::before {
|
||||
content: counter(itema)counter(itemb, lower-alpha);
|
||||
}
|
||||
#sourcerefs ol#srcr > li {
|
||||
counter-increment: itema;
|
||||
margin-top: .1em;
|
||||
}
|
||||
#sourcerefs ol#citr > li {
|
||||
counter-increment: itemb;
|
||||
margin-top: .1em;
|
||||
}
|
||||
#sourcerefs ol#citr ul {
|
||||
list-style: none;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
#sourcerefs ol li ol {
|
||||
list-style-type: lower-alpha;
|
||||
}
|
||||
|
||||
/* Subsection : Pedigree
|
||||
@ -1145,43 +1055,3 @@ body#fullyearlinked #YearGlance tbody td:hover .date {
|
||||
border-radius: 45px;
|
||||
border: 5px solid;
|
||||
}
|
||||
h4 button.icon {
|
||||
width: 0.9em;
|
||||
border: 0px solid;
|
||||
padding: 0;
|
||||
opacity: 1;
|
||||
transform: rotate(90deg);
|
||||
transition: transform 200ms ease-out 0s;
|
||||
background: transparent;
|
||||
}
|
||||
h4 button.icon-close {
|
||||
transform: rotate(90deg);
|
||||
transition: transform 0.2s linear;
|
||||
}
|
||||
h4 button.icon-open {
|
||||
transform: rotate(180deg);
|
||||
transition: transform 0.2s linear;
|
||||
}
|
||||
svg {
|
||||
fill: #EA8414;
|
||||
}
|
||||
/* Go to the top of the page */
|
||||
#gototop {
|
||||
display: none;
|
||||
position: fixed;
|
||||
bottom: 10px;
|
||||
right: 20px;
|
||||
z-index: 999;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
color: black;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#gototop:hover {
|
||||
background-color: #FFE09F;
|
||||
}
|
||||
|
||||
@ -165,7 +165,6 @@ a[href]:hover, a[href]:active {
|
||||
----------------------------------------------------- */
|
||||
div#nav, #subnavigation {
|
||||
border: solid 1px #EAEEF4; /* needed by IE7 */
|
||||
position: relative;
|
||||
}
|
||||
#subnavigation ul {
|
||||
overflow: hidden;
|
||||
@ -203,35 +202,6 @@ div#nav ul li.CurrentSection a {
|
||||
#subnavigation ul li.CurrentSection a {
|
||||
background-color: #FFF;
|
||||
}
|
||||
div#nav li.lang {
|
||||
font-size: smaller;
|
||||
font-family: sans-serif;
|
||||
padding-top: .3em;
|
||||
padding-bottom: .3em;
|
||||
font-weight: bold;
|
||||
}
|
||||
div#nav li.lang:hover > ul {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
div#nav ul.lang {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
padding: 0px;
|
||||
opacity: 0;
|
||||
z-index: 999;
|
||||
background-color: #EAEEF4;
|
||||
top: -1em;
|
||||
font-size: larger;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
div#nav ul.lang:hover {
|
||||
float: initial;
|
||||
}
|
||||
div#nav ul.lang li {
|
||||
float: none;
|
||||
padding: 1px 2px;
|
||||
}
|
||||
|
||||
/* Alphabet Navigation
|
||||
----------------------------------------------------- */
|
||||
@ -350,21 +320,6 @@ div#nav::after {
|
||||
.content {
|
||||
padding: 0em 0.5em;
|
||||
}
|
||||
.lang {
|
||||
position: relative;
|
||||
}
|
||||
.lang > .lang {
|
||||
top: 0;
|
||||
left: 100%;
|
||||
margin-top: -6px;
|
||||
margin-left: -1px;
|
||||
-webkit-border-radius: 0 6px 6px 6px;
|
||||
-moz-border-radius: 0 6px 6px 6px;
|
||||
border-radius: 0 6px 6px 6px;
|
||||
}
|
||||
.lang:hover > .lang {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
/* Main Table
|
||||
@ -633,7 +588,7 @@ table.eventlist td.ColumnPlace {
|
||||
font-weight: normal;
|
||||
}
|
||||
#GalleryDisplay {
|
||||
margin: 10px auto;
|
||||
margin: 0px auto;
|
||||
position: relative;
|
||||
}
|
||||
#GalleryDisplay img {
|
||||
@ -707,7 +662,6 @@ div#SourceDetail {
|
||||
#Contact #GalleryDisplay img {
|
||||
display: block;
|
||||
max-width: 950px;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
float: right;
|
||||
}
|
||||
@ -718,12 +672,12 @@ div#SourceDetail {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
#Home p, #Introduction p, #Contact p {
|
||||
#Home p, #Introduction p {
|
||||
padding-left: 15px;
|
||||
}
|
||||
.subsection {
|
||||
clear: both;
|
||||
overflow-x: auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
.subsection p {
|
||||
margin: 0px;
|
||||
@ -735,10 +689,6 @@ div#SourceDetail {
|
||||
table.relationships tr:hover {
|
||||
background-color: #BFD0EA;
|
||||
}
|
||||
div.content table.tags {
|
||||
text-align: left;
|
||||
width: auto;
|
||||
}
|
||||
div#families table.fixed_subtables table.eventlist {
|
||||
table-layout: fixed;
|
||||
}
|
||||
@ -760,16 +710,10 @@ div#families table.attrlist td.ColumnType {
|
||||
#indivgallery {
|
||||
background-color: white;
|
||||
}
|
||||
#indivgallery a {
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
word-wrap: break-word;
|
||||
display: block;
|
||||
}
|
||||
#gallery .gallerycell {
|
||||
float: left;
|
||||
width: 130px;
|
||||
height: 160px;
|
||||
height: 150px;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
background-color: white;
|
||||
@ -782,8 +726,7 @@ div#families table.attrlist td.ColumnType {
|
||||
}
|
||||
#indivgallery .thumbnail {
|
||||
float: left;
|
||||
width: 160px;
|
||||
height: 220px;
|
||||
width: 130px;
|
||||
font-size: smaller;
|
||||
text-align: center;
|
||||
margin: 0.8em 0.5em;
|
||||
@ -854,14 +797,6 @@ i + div.grampsstylednote p {
|
||||
div.grampsstylednote p {
|
||||
padding-bottom: 0.6em;
|
||||
}
|
||||
div.grampsstylednote a {
|
||||
text-decoration: underline;
|
||||
font-weight: bold;
|
||||
color: #204D91;
|
||||
}
|
||||
div.grampsstylednote a:visited {
|
||||
color: red;
|
||||
}
|
||||
|
||||
/* Subsection : References
|
||||
----------------------------------------------------- */
|
||||
@ -880,34 +815,8 @@ a.family_map {
|
||||
|
||||
/* Subsection : Source References
|
||||
----------------------------------------------------- */
|
||||
#sourcerefs ol#srcr {
|
||||
counter-reset: itema;
|
||||
list-style-type: none;
|
||||
display: block;
|
||||
margin-top: .1em;
|
||||
}
|
||||
#sourcerefs ol#citr {
|
||||
counter-reset: itemb;
|
||||
list-style-type: none;
|
||||
}
|
||||
#sourcerefs ol#srcr > li::before {
|
||||
content: counter(itema);
|
||||
}
|
||||
#sourcerefs ol#citr > li::before {
|
||||
content: counter(itema)counter(itemb, lower-alpha);
|
||||
}
|
||||
#sourcerefs ol#srcr > li {
|
||||
counter-increment: itema;
|
||||
margin-top: .1em;
|
||||
}
|
||||
#sourcerefs ol#citr > li {
|
||||
counter-increment: itemb;
|
||||
margin-top: .1em;
|
||||
}
|
||||
#sourcerefs ol#citr ul {
|
||||
list-style: none;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
#sourcerefs ol li ol {
|
||||
list-style-type: lower-alpha;
|
||||
}
|
||||
|
||||
/* Subsection : Pedigree
|
||||
@ -1138,43 +1047,3 @@ body#fullyearlinked #YearGlance tbody td:hover .date {
|
||||
border-radius: 45px;
|
||||
border: 5px solid;
|
||||
}
|
||||
h4 button.icon {
|
||||
width: 0.9em;
|
||||
border: 0px solid;
|
||||
padding: 0;
|
||||
opacity: 1;
|
||||
transform: rotate(90deg);
|
||||
transition: transform 200ms ease-out 0s;
|
||||
background: transparent;
|
||||
}
|
||||
h4 button.icon-close {
|
||||
transform: rotate(90deg);
|
||||
transition: transform 0.2s linear;
|
||||
}
|
||||
h4 button.icon-open {
|
||||
transform: rotate(180deg);
|
||||
transition: transform 0.2s linear;
|
||||
}
|
||||
svg {
|
||||
fill: #204D91;
|
||||
}
|
||||
/* Go to the top of the page */
|
||||
#gototop {
|
||||
display: none;
|
||||
position: fixed;
|
||||
bottom: 10px;
|
||||
right: 20px;
|
||||
z-index: 999;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
color: black;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#gototop:hover {
|
||||
background-color: #EAEEF4;
|
||||
}
|
||||
|
||||
@ -169,7 +169,6 @@ a[href]:hover, a[href]:active {
|
||||
-----------------------------------------------------------------*/
|
||||
div#nav, #subnavigation {
|
||||
background: url(../images/Web_Mainz_Mid.png) repeat-x top left;
|
||||
position: relative;
|
||||
}
|
||||
div#nav ul, #subnavigation ul {
|
||||
list-style-type: none;
|
||||
@ -200,31 +199,6 @@ div#nav ul li.CurrentSection a, #subnavigation ul li.CurrentSection a {
|
||||
#subnavigation ul li.CurrentSection a {
|
||||
border-width: 0px 1px 1px 1px;
|
||||
}
|
||||
div#nav li.lang {
|
||||
font-size: smaller;
|
||||
padding-top: 2px;
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
div#nav li.lang:hover > ul {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
div#nav ul.lang {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
z-index: 999;
|
||||
background-color: #D8C19F;
|
||||
top: -1em;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
div#nav ul.lang:hover {
|
||||
float: initial;
|
||||
}
|
||||
div#nav ul.lang li {
|
||||
float: none;
|
||||
font-size: larger;
|
||||
}
|
||||
|
||||
/* Alphabet Navigation
|
||||
-----------------------------------------------------------------*/
|
||||
@ -317,7 +291,7 @@ div#nav::after {
|
||||
background: url(../images/Web_Mainz_Mid.png) #FFF2C6 repeat;
|
||||
}
|
||||
|
||||
.nav.responsive {position: relative; display: block; z-index: 100;}
|
||||
.nav.responsive {position: absolute; display: block; z-index: 100;}
|
||||
.nav.responsive a.icon {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
@ -337,27 +311,11 @@ div#nav::after {
|
||||
|
||||
div#nav ul, #subnavigation ul {
|
||||
padding-left: 0px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 0em 0.5em;
|
||||
}
|
||||
.lang {
|
||||
position: relative;
|
||||
}
|
||||
.lang > .lang {
|
||||
top: 0;
|
||||
left: 100%;
|
||||
margin-top: -6px;
|
||||
margin-left: -1px;
|
||||
-webkit-border-radius: 0 6px 6px 6px;
|
||||
-moz-border-radius: 0 6px 6px 6px;
|
||||
border-radius: 0 6px 6px 6px;
|
||||
}
|
||||
.lang:hover > .lang {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
/* Main Table
|
||||
@ -594,7 +552,7 @@ table.IndividualList tr:hover td.ColumnSurname {
|
||||
position: relative;
|
||||
}
|
||||
#GalleryDisplay img {
|
||||
margin: 10px auto;
|
||||
margin: 0px auto;
|
||||
display:block;
|
||||
border: solid 1px #7D5925;
|
||||
height: auto;
|
||||
@ -623,6 +581,11 @@ div#SourceDetail {
|
||||
padding-bottom: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
#Contact #summaryarea #GalleryDisplay img {
|
||||
display: block;
|
||||
margin: 0px auto 1em auto;
|
||||
border: solid 1px #7D5925;
|
||||
}
|
||||
#Contact #researcher {
|
||||
text-align: center;
|
||||
}
|
||||
@ -648,19 +611,17 @@ div#SourceDetail {
|
||||
float: right;
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
margin: 10px auto;
|
||||
}
|
||||
#Home #GalleryDisplay img, #Introduction #GalleryDisplay img,
|
||||
#Contact #GalleryDisplay img {
|
||||
#Contact #GalleryDisplay {
|
||||
display: block;
|
||||
max-width: 950px;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
float: right;
|
||||
}
|
||||
@media only screen and (max-width: 1080px) {
|
||||
#Home #GalleryDisplay img, #Introduction #GalleryDisplay img,
|
||||
#Contact #GalleryDisplay img {
|
||||
#Contact #GalleryDisplay {
|
||||
margin: 0 auto;
|
||||
max-width: 100%;
|
||||
}
|
||||
@ -670,7 +631,7 @@ div#SourceDetail {
|
||||
}
|
||||
.subsection {
|
||||
clear: both;
|
||||
overflow-x: auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
.subsection p {
|
||||
margin: 0px;
|
||||
@ -682,10 +643,6 @@ div#SourceDetail {
|
||||
table.relationships tr:hover td {
|
||||
background-color: #D8C19F;
|
||||
}
|
||||
div.content table.tags {
|
||||
text-align: left;
|
||||
width: auto;
|
||||
}
|
||||
div#families table.fixed_subtables table.eventlist {
|
||||
table-layout: fixed;
|
||||
}
|
||||
@ -710,6 +667,7 @@ div#families .infolist h4 {
|
||||
height: 150px;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
background-color: white;
|
||||
border-top: solid 1px #999;
|
||||
border-right: solid 1px #999;
|
||||
}
|
||||
@ -721,18 +679,9 @@ div#families .infolist h4 {
|
||||
/* float container stretch, see www.quirksmode.org/css/clearing.html */
|
||||
overflow: hidden;
|
||||
}
|
||||
div#indivgallery div.thumbnail a,
|
||||
div#gallerycell div.thumbnail a {
|
||||
color: #7D5925;
|
||||
text-decoration: none;
|
||||
word-wrap: break-word;
|
||||
width: 160px;
|
||||
display: block;
|
||||
}
|
||||
#indivgallery .thumbnail {
|
||||
float: left;
|
||||
width: 160px;
|
||||
height: 220px;
|
||||
width: 130px;
|
||||
font-size: smaller;
|
||||
text-align: center;
|
||||
margin: 0.5em;
|
||||
@ -800,14 +749,6 @@ i + div.grampsstylednote p {
|
||||
div.grampsstylednote p {
|
||||
padding-bottom: 0.6em;
|
||||
}
|
||||
div.grampsstylednote a {
|
||||
text-decoration: underline;
|
||||
font-weight: bold;
|
||||
color: #7D5925;
|
||||
}
|
||||
div.grampsstylednote a:visited {
|
||||
color: red;
|
||||
}
|
||||
|
||||
/* Subsection : References
|
||||
----------------------------------------------------- */
|
||||
@ -817,43 +758,9 @@ div.grampsstylednote a:visited {
|
||||
|
||||
/* SubSection : Source References
|
||||
-----------------------------------------------------------------*/
|
||||
#sourcerefs ol#srcr {
|
||||
counter-reset: itema;
|
||||
list-style-type: none;
|
||||
display: block;
|
||||
margin-top: .1em;
|
||||
#sourcerefs ol li ol {
|
||||
list-style-type: lower-alpha;
|
||||
}
|
||||
#sourcerefs ol#citr {
|
||||
counter-reset: itemb;
|
||||
list-style-type: none;
|
||||
}
|
||||
#sourcerefs ol#srcr > li::before {
|
||||
content: counter(itema);
|
||||
}
|
||||
#sourcerefs ol#citr > li::before {
|
||||
content: counter(itema)counter(itemb, lower-alpha);
|
||||
}
|
||||
#sourcerefs ol#srcr > li {
|
||||
counter-increment: itema;
|
||||
margin-top: .1em;
|
||||
}
|
||||
#sourcerefs ol#citr > li {
|
||||
counter-increment: itemb;
|
||||
margin-top: .1em;
|
||||
}
|
||||
#sourcerefs ol#citr ul {
|
||||
list-style: none;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
/*
|
||||
#sourcerefs a {
|
||||
color: #767D25;
|
||||
}
|
||||
#sourcerefs a:visited {
|
||||
color: red;
|
||||
}
|
||||
*/
|
||||
|
||||
/* SubSection : Pedigree
|
||||
-----------------------------------------------------------------*/
|
||||
@ -1094,43 +1001,3 @@ body#fullyearlinked #YearGlance tbody td.highlight .date:hover {
|
||||
border: 5px solid;
|
||||
background: url(../images/Web_Mainz_Bkgd.png) black repeat;
|
||||
}
|
||||
h4 button.icon {
|
||||
width: 0.9em;
|
||||
border: 0px solid;
|
||||
padding: 0;
|
||||
opacity: 1;
|
||||
transform: rotate(90deg);
|
||||
transition: transform 200ms ease-out 0s;
|
||||
background: transparent;
|
||||
}
|
||||
h4 button.icon-close {
|
||||
transform: rotate(90deg);
|
||||
transition: transform 0.2s linear;
|
||||
}
|
||||
h4 button.icon-open {
|
||||
transform: rotate(180deg);
|
||||
transition: transform 0.2s linear;
|
||||
}
|
||||
svg {
|
||||
fill: #7D5925;
|
||||
}
|
||||
/* Go to the top of the page */
|
||||
#gototop {
|
||||
display: none;
|
||||
position: fixed;
|
||||
bottom: 10px;
|
||||
right: 20px;
|
||||
z-index: 999;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
color: black;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#gototop:hover {
|
||||
background-color: #FFF2C6;
|
||||
}
|
||||
|
||||
@ -238,10 +238,10 @@ div#alphanav, div#nav, div#subnavigation {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
background-color: #A97;
|
||||
position: relative;
|
||||
}
|
||||
div#alphanav ul, div#nav ul, div#subnavigation ul {
|
||||
list-style: none;
|
||||
min-width: 770px;
|
||||
height: 24px;
|
||||
margin: 0;
|
||||
padding: 0px 0px 0px 16px;
|
||||
@ -282,43 +282,6 @@ div#nav ul li.CurrentSection a:hover {
|
||||
div#subnavigation ul li.CurrentSection a {
|
||||
border-width: 0 0 1px 0;
|
||||
}
|
||||
div#nav li.lang {
|
||||
position: relative;
|
||||
padding-top: 3px;
|
||||
padding-left: 8px;
|
||||
font: bold .7em sans;
|
||||
}
|
||||
div#nav li.lang:hover > ul {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
div#nav ul.lang {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
height: auto;
|
||||
width: auto;
|
||||
z-index: 999;
|
||||
overflow: visible;
|
||||
background-color: #A97;
|
||||
top: -1em;
|
||||
border-width: 2px 0px 1px 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
div#nav ul.lang li:after {
|
||||
content: "";
|
||||
}
|
||||
div#nav li.lang ul.lang li {
|
||||
float: none;
|
||||
background-color: #A97;
|
||||
margin-left: 10px;
|
||||
padding: 0px 0px;
|
||||
}
|
||||
div#nav li.lang ul.lang li a {
|
||||
float: none;
|
||||
width: auto;
|
||||
font: bold .9em sans;
|
||||
}
|
||||
|
||||
/* Responsive navigation */
|
||||
button.navIcon {
|
||||
@ -384,6 +347,7 @@ div#nav::after {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.nav.responsive ::after {
|
||||
/* need to remove the "|" when we are in the dropdown menu. */
|
||||
@ -407,28 +371,6 @@ div#nav::after {
|
||||
.content {
|
||||
padding: 0em 0.5em;
|
||||
}
|
||||
div#nav ul li.lang {
|
||||
padding-top: 3px;
|
||||
padding-bottom: 6px;
|
||||
padding-left: 0px;
|
||||
}
|
||||
.lang {
|
||||
position: relative;
|
||||
padding-top: 3px;
|
||||
padding-left: 8px;
|
||||
}
|
||||
.lang > .lang {
|
||||
top: 0;
|
||||
left: 100%;
|
||||
margin-top: -6px;
|
||||
margin-left: -1px;
|
||||
-webkit-border-radius: 0 6px 6px 6px;
|
||||
-moz-border-radius: 0 6px 6px 6px;
|
||||
border-radius: 0 6px 6px 6px;
|
||||
}
|
||||
.lang:hover > .lang {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
/* Main Table
|
||||
@ -1171,10 +1113,6 @@ div#parents table.infolist tbody tr td.ColumnValue ol li {
|
||||
table.relationships tr:hover {
|
||||
background-color:#C1B398;
|
||||
}
|
||||
div.content table.tags {
|
||||
text-align: left;
|
||||
width: auto;
|
||||
}
|
||||
div#families table.infolist {
|
||||
margin-top:.5em;
|
||||
}
|
||||
@ -1247,8 +1185,7 @@ div#Addresses table.infolist tr td a, div#Addresses table.infolist tr td p a {
|
||||
#indivgallery .thumbnail {
|
||||
margin:0;
|
||||
float:left;
|
||||
width:160px;
|
||||
height:220px;
|
||||
width:130px;
|
||||
text-align:center;
|
||||
background-color: #F6F2EE;
|
||||
}
|
||||
@ -1326,14 +1263,6 @@ i + div.grampsstylednote p {
|
||||
div.grampsstylednote p {
|
||||
padding-bottom: 0.6em;
|
||||
}
|
||||
div.grampsstylednote a {
|
||||
text-decoration: underline;
|
||||
font-weight: bold;
|
||||
color: #542;
|
||||
}
|
||||
div.grampsstylednote a:visited {
|
||||
color: red;
|
||||
}
|
||||
.narrative p {
|
||||
margin: 0.1em 0 0.2em 0;
|
||||
font:normal .9em/1.4em sans-serif;
|
||||
@ -1347,34 +1276,11 @@ div.grampsstylednote a:visited {
|
||||
|
||||
/* Subsections : Source References
|
||||
----------------------------------------------------- */
|
||||
#sourcerefs ol#srcr {
|
||||
counter-reset: itema;
|
||||
list-style-type: none;
|
||||
display: block;
|
||||
margin-top: .1em;
|
||||
div#sourcerefs ol {
|
||||
list-style-type:decimal;
|
||||
}
|
||||
#sourcerefs ol#citr {
|
||||
counter-reset: itemb;
|
||||
list-style-type: none;
|
||||
}
|
||||
#sourcerefs ol#srcr > li::before {
|
||||
content: counter(itema);
|
||||
}
|
||||
#sourcerefs ol#citr > li::before {
|
||||
content: counter(itema)counter(itemb, lower-alpha);
|
||||
}
|
||||
#sourcerefs ol#srcr > li {
|
||||
counter-increment: itema;
|
||||
margin-top: .1em;
|
||||
}
|
||||
#sourcerefs ol#citr > li {
|
||||
counter-increment: itemb;
|
||||
margin-top: .1em;
|
||||
}
|
||||
#sourcerefs ol#citr ul {
|
||||
list-style: none;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
div#sourcerefs ol li ol {
|
||||
list-style-type:lower-alpha;
|
||||
}
|
||||
|
||||
/* Subsections : Summary Area
|
||||
@ -1726,43 +1632,3 @@ body#fullyearlinked #YearGlance tbody td:hover .date {
|
||||
border-radius: 45px;
|
||||
border: 5px solid;
|
||||
}
|
||||
h4 button.icon {
|
||||
width: 0.9em;
|
||||
border: 0px solid;
|
||||
padding: 0;
|
||||
opacity: 1;
|
||||
transform: rotate(90deg);
|
||||
transition: transform 200ms ease-out 0s;
|
||||
background: transparent;
|
||||
}
|
||||
h4 button.icon-close {
|
||||
transform: rotate(90deg);
|
||||
transition: transform 0.2s linear;
|
||||
}
|
||||
h4 button.icon-open {
|
||||
transform: rotate(180deg);
|
||||
transition: transform 0.2s linear;
|
||||
}
|
||||
svg {
|
||||
fill: #542;
|
||||
}
|
||||
/* Go to the top of the page */
|
||||
#gototop {
|
||||
display: none;
|
||||
position: fixed;
|
||||
bottom: 10px;
|
||||
right: 20px;
|
||||
z-index: 999;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
color: black;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#gototop:hover {
|
||||
background-color: #696969;
|
||||
}
|
||||
|
||||
@ -36,12 +36,7 @@ Females Web_Gender_Female.png
|
||||
# -------------------------------------------------------------------------- */
|
||||
/* Subsections : Ancestors Tree -------------------------------------------- */
|
||||
#tree {
|
||||
margin:0;
|
||||
padding:0;
|
||||
background:none;
|
||||
overflow-x:auto;
|
||||
}
|
||||
#toggle_anc {
|
||||
page-break-before:always;
|
||||
margin:0;
|
||||
padding:0;
|
||||
background:none;
|
||||
@ -51,6 +46,7 @@ Females Web_Gender_Female.png
|
||||
position:relative;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
overflow: visible;
|
||||
z-index:1;
|
||||
}
|
||||
#treeContainer div.boxbg {
|
||||
|
||||
@ -117,15 +117,7 @@ div#FamilyMapDetail div#references table.infolist tbody tr td.ColumnPlace {
|
||||
font: bold 0.9em sans-serif;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
padding: 5px 0.5em 5px 0.5em;
|
||||
}
|
||||
#map_canvas .thumbnail {
|
||||
padding: 5px 5px;
|
||||
text-align: center;
|
||||
}
|
||||
#map_canvas img {
|
||||
max-height: 300px;
|
||||
max-width: 400px;
|
||||
padding: 0 0.5em 15px 0.5em;
|
||||
}
|
||||
#map_canvas .ol-popup-content a {
|
||||
color: #111;
|
||||
|
||||
@ -1,22 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop-application">
|
||||
<id>org.gramps.gramps</id>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<name>Gramps</name>
|
||||
<summary>Manage genealogical information, perform genealogical research and analysis</summary>
|
||||
<summary>Genealogical research program</summary>
|
||||
|
||||
<description>
|
||||
<p>Gramps is a genealogy program that is both intuitive for hobbyists and feature-complete for professional genealogists.</p>
|
||||
<p>It gives you the ability to record the many details of the life of an individual as well as the complex relationships between various people, places and events.</p>
|
||||
<p>All of your research is kept organized, searchable and as precise as you need it to be.</p>
|
||||
<_p>Gramps is a genealogy program that is both intuitive for hobbyists and feature-complete for professional genealogists.</_p>
|
||||
<_p>It gives you the ability to record the many details of the life of an individual as well as the complex relationships between various people, places and events.</_p>
|
||||
<_p>All of your research is kept organized, searchable and as precise as you need it to be.</_p>
|
||||
</description>
|
||||
|
||||
<developer_name>Gramps Development Team</developer_name>
|
||||
<project_license>GPL-2.0-or-later</project_license>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
|
||||
<launchable type="desktop-id">gramps.desktop</launchable>
|
||||
<url type="homepage">https://gramps-project.org/</url>
|
||||
<url type="bugtracker">https://gramps-project.org/bugs/</url>
|
||||
<url type="help">https://gramps-project.org/wiki/index.php?title=Main_page</url>
|
||||
<url type="translate">https://www.gramps-project.org/wiki/index.php?title=Translating_Gramps</url>
|
||||
<project_license>GPL-2.0+</project_license>
|
||||
<developer_name>Gramps Development Team</developer_name>
|
||||
|
||||
<screenshots>
|
||||
<screenshot>
|
||||
@ -36,23 +36,8 @@
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
|
||||
<launchable type="desktop-id">gramps.desktop</launchable>
|
||||
<provides>
|
||||
<binary>gramps</binary>
|
||||
</provides>
|
||||
|
||||
<translation type="gettext">gramps</translation>
|
||||
|
||||
<content_rating type="oars-1.1" />
|
||||
|
||||
<releases>
|
||||
<release date="2020-08-12" version="5.1.3" />
|
||||
<release date="2020-01-10" version="5.1.2" />
|
||||
<release date="2019-09-15" version="5.1.1" />
|
||||
<release date="2019-08-21" version="5.1.0" />
|
||||
<release date="2019-08-18" version="5.0.2" />
|
||||
<release date="2018-12-20" version="5.0.1" />
|
||||
<release date="2018-07-24" version="5.0.0" />
|
||||
</releases>
|
||||
|
||||
</component>
|
||||
|
||||
@ -3,11 +3,11 @@
|
||||
|
||||
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
|
||||
<mime-type type="application/x-gramps">
|
||||
<comment>Gramps database</comment>
|
||||
<_comment>Gramps database</_comment>
|
||||
<glob pattern="*.grdb"/>
|
||||
</mime-type>
|
||||
<mime-type type="application/x-gedcom">
|
||||
<comment>GEDCOM</comment>
|
||||
<_comment>GEDCOM</_comment>
|
||||
<glob pattern="*.ged"/>
|
||||
<glob pattern="*.gedcom"/>
|
||||
<glob pattern="*.GED"/>
|
||||
@ -17,11 +17,11 @@
|
||||
</magic>
|
||||
</mime-type>
|
||||
<mime-type type="application/x-gramps-package">
|
||||
<comment>Gramps package</comment>
|
||||
<_comment>Gramps package</_comment>
|
||||
<glob pattern="*.gpkg"/>
|
||||
</mime-type>
|
||||
<mime-type type="application/x-gramps-xml">
|
||||
<comment>Gramps XML database</comment>
|
||||
<_comment>Gramps XML database</_comment>
|
||||
<glob pattern="*.gramps"/>
|
||||
<magic priority="80">
|
||||
<match type="string" value="<!DOCTYPE database" offset="0:256"/>
|
||||
@ -29,7 +29,7 @@
|
||||
</magic>
|
||||
</mime-type>
|
||||
<mime-type type="application/x-geneweb">
|
||||
<comment>GeneWeb source file</comment>
|
||||
<_comment>GeneWeb source file</_comment>
|
||||
<glob pattern="*.gw"/>
|
||||
<glob pattern="*.GW"/>
|
||||
<magic priority="80">
|
||||
|
||||
@ -387,15 +387,12 @@
|
||||
<country name="Russia">
|
||||
<date value="*/1/7" type="religious" name="Рождество Христово" />
|
||||
<date value="*/1/19" type="religious" name="Крещение Господне" />
|
||||
<date value="*/2/23" type="national" name="День Защитника Отечества" />
|
||||
<date value="*/2/23" type="national" name="День защитника" />
|
||||
<date value="*/3/8" type="national" name="Международный женский день" />
|
||||
<date value="*/4/12" type="national" name="День Космонавтики" />
|
||||
<date value="*/5/1" type="national" name="Праздник Весны и Труда" />
|
||||
<date value="*/5/1" type="national" name="День труда" />
|
||||
<date value="*/5/9" type="national" name="День Победы" />
|
||||
<date value="*/6/1" type="national" name="День защиты детей" />
|
||||
<date value="*/6/12" type="national" name="День России" />
|
||||
<date value="*/6/22" type="national" name="День памяти и скорби" />
|
||||
<date value="*/-4/sun/jul" type="national" name="День ВМФ" />
|
||||
<date value="*/9/1" type="national" name="День знаний" />
|
||||
<date value="*/11/4" type="national" name="День народного единства" />
|
||||
<date value="*/12/31" offset="+2" type="national" name="Новый год" />
|
||||
|
||||
@ -445,7 +445,7 @@ class ArgHandler:
|
||||
line_list = [(_('"%s"') % summary[_("Family Tree")])]
|
||||
for item in sorted(summary):
|
||||
if item != _("Family Tree"):
|
||||
# Translators: used in French+Russian, ignore otherwise
|
||||
# translators: used in French+Russian, ignore otherwise
|
||||
line_list += [(_('"%s"') % summary[item])]
|
||||
print("\t".join(line_list))
|
||||
return
|
||||
|
||||
@ -383,7 +383,7 @@ class ArgParser:
|
||||
converter = get_type_converter(setting_value)
|
||||
new_value = converter(new_value)
|
||||
config.set(cfg_name, new_value)
|
||||
# Translators: indent "New" to match "Current"
|
||||
# translators: indent "New" to match "Current"
|
||||
print(_(" New Gramps config setting: "
|
||||
"%(name)s:%(value)s"
|
||||
) % {'name' : cfg_name,
|
||||
|
||||
@ -197,7 +197,7 @@ class CLIDbManager:
|
||||
print(_('Family Tree "%s":') % summary[_("Family Tree")])
|
||||
for item in sorted(summary):
|
||||
if item != "Family Tree":
|
||||
# Translators: needed for French, ignore otherwise
|
||||
# translators: needed for French, ignore otherwise
|
||||
print(' ' + _("%(str1)s: %(str2)s"
|
||||
) % {'str1' : item,
|
||||
'str2' : summary[item]})
|
||||
|
||||
@ -102,7 +102,7 @@ class CLIDbLoader:
|
||||
_("Low level database corruption detected")
|
||||
+ '\n' +
|
||||
_("Gramps has detected a problem in the underlying "
|
||||
"database. This can sometimes be repaired from "
|
||||
"Berkeley database. This can be repaired from "
|
||||
"the Family Tree Manager. Select the database and "
|
||||
'click on the Repair button'
|
||||
) + '\n\n' + str(msg))
|
||||
|
||||
@ -412,7 +412,7 @@ class CommandLineReport:
|
||||
father = self.database.get_person_from_handle(fhandle)
|
||||
if father:
|
||||
fname = name_displayer.display(father)
|
||||
# Translators: needed for French, Hebrew and Arabic
|
||||
# translators: needed for French, Hebrew and Arabic
|
||||
text = _("%(id)s:\t%(father)s, %(mother)s"
|
||||
) % {'id': family.get_gramps_id(),
|
||||
'father': fname, 'mother': mname}
|
||||
|
||||
@ -22,8 +22,20 @@
|
||||
""" Unittest for argparser.py """
|
||||
|
||||
import unittest
|
||||
from unittest.mock import Mock
|
||||
from ..argparser import ArgParser
|
||||
import sys
|
||||
|
||||
try:
|
||||
if sys.version_info < (3,3):
|
||||
from mock import Mock
|
||||
else:
|
||||
from unittest.mock import Mock
|
||||
|
||||
MOCKING = True
|
||||
|
||||
except:
|
||||
MOCKING = False
|
||||
print ("Mocking disabled", sys.exc_info()[0:2])
|
||||
|
||||
class TestArgParser(unittest.TestCase):
|
||||
def setUp(self):
|
||||
|
||||
@ -22,10 +22,21 @@
|
||||
""" Unittest for user.py """
|
||||
|
||||
import unittest
|
||||
from unittest.mock import Mock, patch
|
||||
from .. import user
|
||||
import sys
|
||||
|
||||
try:
|
||||
if sys.version_info < (3,3):
|
||||
from mock import Mock, patch
|
||||
else:
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
MOCKING = True
|
||||
|
||||
except:
|
||||
MOCKING = False
|
||||
print ("Mocking disabled", sys.exc_info()[0:2])
|
||||
|
||||
class TestUser:
|
||||
TITLE = "Testing prompt"
|
||||
MSG = "Choices are hard. Nevertheless, please choose!"
|
||||
@ -35,9 +46,10 @@ class TestUser:
|
||||
class TestUser_prompt(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.real_user = user.User()
|
||||
self.user = user.User()
|
||||
self.user._fileout = Mock(spec=sys.stderr)
|
||||
self.user._input = Mock(spec=input)
|
||||
if MOCKING:
|
||||
self.user = user.User()
|
||||
self.user._fileout = Mock(spec=sys.stderr)
|
||||
self.user._input = Mock(spec=input)
|
||||
|
||||
def test_default_fileout_has_write(self):
|
||||
assert hasattr(self.real_user._fileout, 'write')
|
||||
@ -45,6 +57,7 @@ class TestUser_prompt(unittest.TestCase):
|
||||
def test_default_input(self):
|
||||
assert self.real_user._input.__name__.endswith('input')
|
||||
|
||||
@unittest.skipUnless(MOCKING, "Requires unittest.mock to run")
|
||||
def test_prompt_returns_True_if_ACCEPT_entered(self):
|
||||
self.user._input.configure_mock(return_value = TestUser.ACCEPT)
|
||||
assert self.user.prompt(
|
||||
@ -52,6 +65,7 @@ class TestUser_prompt(unittest.TestCase):
|
||||
), "True expected!"
|
||||
self.user._input.assert_called_once_with()
|
||||
|
||||
@unittest.skipUnless(MOCKING, "Requires unittest.mock to run")
|
||||
def test_prompt_returns_False_if_REJECT_entered(self):
|
||||
self.user._input.configure_mock(return_value = TestUser.REJECT)
|
||||
assert not self.user.prompt(
|
||||
@ -73,24 +87,37 @@ class TestUser_prompt(unittest.TestCase):
|
||||
"'{}' never printed in prompt: {}".format(
|
||||
text, self.user._fileout.method_calls))
|
||||
|
||||
@unittest.skipUnless(MOCKING, "Requires unittest.mock to run")
|
||||
def test_prompt_contains_title_text(self):
|
||||
self.assert_prompt_contains_text(TestUser.TITLE)
|
||||
|
||||
@unittest.skipUnless(MOCKING, "Requires unittest.mock to run")
|
||||
def test_prompt_contains_msg_text(self):
|
||||
self.assert_prompt_contains_text(TestUser.MSG)
|
||||
|
||||
@unittest.skipUnless(MOCKING, "Requires unittest.mock to run")
|
||||
def test_prompt_contains_accept_text(self):
|
||||
self.assert_prompt_contains_text(TestUser.ACCEPT)
|
||||
|
||||
@unittest.skipUnless(MOCKING, "Requires unittest.mock to run")
|
||||
def test_prompt_contains_reject_text(self):
|
||||
self.assert_prompt_contains_text(TestUser.REJECT)
|
||||
|
||||
@unittest.skipUnless(MOCKING, "Requires unittest.mock to run")
|
||||
def test_prompt_strips_underscore_in_accept(self):
|
||||
self.assert_prompt_contains_text("accepT", accept="accep_T")
|
||||
|
||||
@unittest.skipUnless(MOCKING, "Requires unittest.mock to run")
|
||||
def test_prompt_strips_underscore_in_reject(self):
|
||||
self.assert_prompt_contains_text("reJect", reject="re_Ject")
|
||||
|
||||
if not MOCKING: #don't use SKIP, to avoid counting a skipped test
|
||||
def test_manual_run(self):
|
||||
b = self.real_user.prompt(
|
||||
TestUser.TITLE, TestUser.MSG, TestUser.ACCEPT, TestUser.REJECT)
|
||||
print ("Returned: {}".format(b))
|
||||
|
||||
@unittest.skipUnless(MOCKING, "Requires unittest.mock to run")
|
||||
def test_auto_accept_accepts_without_prompting(self):
|
||||
u = user.User(auto_accept=True)
|
||||
u._fileout = Mock(spec=sys.stderr)
|
||||
@ -99,6 +126,7 @@ class TestUser_prompt(unittest.TestCase):
|
||||
), "True expected!"
|
||||
assert len(u._fileout.method_calls) == 0, list(u._fileout.method_calls)
|
||||
|
||||
@unittest.skipUnless(MOCKING, "Requires unittest.mock to run")
|
||||
def test_EOFError_in_prompt_caught_as_False(self):
|
||||
self.user._input.configure_mock(
|
||||
side_effect = EOFError,
|
||||
@ -108,6 +136,7 @@ class TestUser_prompt(unittest.TestCase):
|
||||
), "False expected!"
|
||||
self.user._input.assert_called_once_with()
|
||||
|
||||
@unittest.skipUnless(MOCKING, "Requires unittest.mock to run")
|
||||
class TestUser_quiet(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.user = user.User(quiet=True)
|
||||
@ -123,6 +152,7 @@ class TestUser_quiet(unittest.TestCase):
|
||||
assert len(self.user._fileout.method_calls
|
||||
) == 0, list(self.user._fileout.method_calls)
|
||||
|
||||
@unittest.skipUnless(MOCKING, "Requires unittest.mock to run")
|
||||
class TestUser_progress(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
||||
@ -199,7 +199,7 @@ class User(user.UserBase):
|
||||
self.notify_error(
|
||||
_("Low level database corruption detected"),
|
||||
_("Gramps has detected a problem in the underlying "
|
||||
"database. This can sometimes be repaired from "
|
||||
"Berkeley database. This can be repaired from "
|
||||
"the Family Tree Manager. Select the database and "
|
||||
'click on the Repair button') + '\n\n' + error)
|
||||
|
||||
|
||||
@ -262,7 +262,7 @@ NO_GIVEN = "(%s)" % _("none", "given-name")
|
||||
ARABIC_COMMA = "،"
|
||||
ARABIC_SEMICOLON = "؛"
|
||||
DOCGEN_OPTIONS = 'Docgen Options'
|
||||
COLON = _(':') # Translators: needed for French, ignore otherwise
|
||||
COLON = _(':') # translators: needed for French, ignore otherwise
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
|
||||
@ -67,27 +67,25 @@ class DateDisplay:
|
||||
|
||||
formats = (
|
||||
# format 0 - must always be ISO
|
||||
# Translators: Numeric year, month, day
|
||||
_T_("YYYY-MM-DD (ISO)"),
|
||||
|
||||
# format # 1 - must always be locale-preferred numerical format
|
||||
# such as YY.MM.DD, MM-DD-YY, or whatever your locale prefers.
|
||||
# This should be the format that is used under the locale by
|
||||
# strftime() for '%x'.
|
||||
# Translators: You may translate this as "Numerical",
|
||||
# "System preferred", or similar.
|
||||
# You may translate this as "Numerical", "System preferred", or similar.
|
||||
_T_("Numerical", "date format"),
|
||||
|
||||
# Translators: Full month name, day, year
|
||||
# Full month name, day, year
|
||||
_T_("Month Day, Year"),
|
||||
|
||||
# Translators: Abbreviated month name, day, year
|
||||
# Abbreviated month name, day, year
|
||||
_T_("MON DAY, YEAR"),
|
||||
|
||||
# Translators: Day, full month name, year
|
||||
# Day, full month name, year
|
||||
_T_("Day Month Year"),
|
||||
|
||||
# Translators: Day, abbreviated month name, year
|
||||
# Day, abbreviated month name, year
|
||||
_T_("DAY MON YEAR")
|
||||
)
|
||||
"""
|
||||
@ -184,67 +182,67 @@ class DateDisplay:
|
||||
|
||||
"from"
|
||||
# first date in a span
|
||||
# Translators: If "from <Month>" needs a special inflection
|
||||
# in your language, translate to "{long_month.f[X]} {year}"
|
||||
# If "from <Month>" needs a special inflection in your
|
||||
# language, translate this to "{long_month.f[X]} {year}"
|
||||
# (where X is one of the month-name inflections you defined)
|
||||
# else leave it untranslated
|
||||
: _("{long_month} {year}", "from"),
|
||||
|
||||
"to"
|
||||
# second date in a span
|
||||
# Translators: If "to <Month>" needs a special inflection
|
||||
# in your language, translate to "{long_month.f[X]} {year}"
|
||||
# If "to <Month>" needs a special inflection in your
|
||||
# language, translate this to "{long_month.f[X]} {year}"
|
||||
# (where X is one of the month-name inflections you defined)
|
||||
# else leave it untranslated
|
||||
: _("{long_month} {year}", "to"),
|
||||
|
||||
"between"
|
||||
# first date in a range
|
||||
# Translators: If "between <Month>" needs a special inflection
|
||||
# in your language, translate to "{long_month.f[X]} {year}"
|
||||
# If "between <Month>" needs a special inflection in your
|
||||
# language, translate this to "{long_month.f[X]} {year}"
|
||||
# (where X is one of the month-name inflections you defined)
|
||||
# else leave it untranslated
|
||||
: _("{long_month} {year}", "between"),
|
||||
|
||||
"and"
|
||||
# second date in a range
|
||||
# Translators: If "and <Month>" needs a special inflection
|
||||
# in your language, translate to "{long_month.f[X]} {year}"
|
||||
# If "and <Month>" needs a special inflection in your
|
||||
# language, translate this to "{long_month.f[X]} {year}"
|
||||
# (where X is one of the month-name inflections you defined)
|
||||
# else leave it untranslated
|
||||
: _("{long_month} {year}", "and"),
|
||||
|
||||
"before"
|
||||
# Translators: If "before <Month>" needs a special inflection
|
||||
# in your language, translate to "{long_month.f[X]} {year}"
|
||||
# If "before <Month>" needs a special inflection in your
|
||||
# language, translate this to "{long_month.f[X]} {year}"
|
||||
# (where X is one of the month-name inflections you defined)
|
||||
# else leave it untranslated
|
||||
: _("{long_month} {year}", "before"),
|
||||
|
||||
"after"
|
||||
# Translators: If "after <Month>" needs a special inflection
|
||||
# in your language, translate to "{long_month.f[X]} {year}"
|
||||
# If "after <Month>" needs a special inflection in your
|
||||
# language, translate this to "{long_month.f[X]} {year}"
|
||||
# (where X is one of the month-name inflections you defined)
|
||||
# else leave it untranslated
|
||||
: _("{long_month} {year}", "after"),
|
||||
|
||||
"about"
|
||||
# Translators: If "about <Month>" needs a special inflection
|
||||
# in your language, translate to "{long_month.f[X]} {year}"
|
||||
# If "about <Month>" needs a special inflection in your
|
||||
# language, translate this to "{long_month.f[X]} {year}"
|
||||
# (where X is one of the month-name inflections you defined)
|
||||
# else leave it untranslated
|
||||
: _("{long_month} {year}", "about"),
|
||||
|
||||
"estimated"
|
||||
# Translators: If "estimated <Month>" needs a special inflection
|
||||
# in your language, translate to "{long_month.f[X]} {year}"
|
||||
# If "estimated <Month>" needs a special inflection in your
|
||||
# language, translate this to "{long_month.f[X]} {year}"
|
||||
# (where X is one of the month-name inflections you defined)
|
||||
# else leave it untranslated
|
||||
: _("{long_month} {year}", "estimated"),
|
||||
|
||||
"calculated"
|
||||
# Translators: If "calculated <Month>" needs a special inflection
|
||||
# in your language, translate to "{long_month.f[X]} {year}"
|
||||
# If "calculated <Month>" needs a special inflection in your
|
||||
# language, translate this to "{long_month.f[X]} {year}"
|
||||
# (where X is one of the month-name inflections you defined)
|
||||
# else leave it untranslated
|
||||
: _("{long_month} {year}", "calculated"),
|
||||
@ -256,67 +254,67 @@ class DateDisplay:
|
||||
|
||||
"from"
|
||||
# first date in a span
|
||||
# Translators: If "from <Month>" needs a special inflection
|
||||
# in your language, translate to "{short_month.f[X]} {year}"
|
||||
# If "from <Month>" needs a special inflection in your
|
||||
# language, translate this to "{short_month.f[X]} {year}"
|
||||
# (where X is one of the month-name inflections you defined)
|
||||
# else leave it untranslated
|
||||
: _("{short_month} {year}", "from"),
|
||||
|
||||
"to"
|
||||
# second date in a span
|
||||
# Translators: If "to <Month>" needs a special inflection
|
||||
# in your language, translate to "{short_month.f[X]} {year}"
|
||||
# If "to <Month>" needs a special inflection in your
|
||||
# language, translate this to "{short_month.f[X]} {year}"
|
||||
# (where X is one of the month-name inflections you defined)
|
||||
# else leave it untranslated
|
||||
: _("{short_month} {year}", "to"),
|
||||
|
||||
"between"
|
||||
# first date in a range
|
||||
# Translators: If "between <Month>" needs a special inflection
|
||||
# in your language, translate to "{short_month.f[X]} {year}"
|
||||
# If "between <Month>" needs a special inflection in your
|
||||
# language, translate this to "{short_month.f[X]} {year}"
|
||||
# (where X is one of the month-name inflections you defined)
|
||||
# else leave it untranslated
|
||||
: _("{short_month} {year}", "between"),
|
||||
|
||||
"and"
|
||||
# second date in a range
|
||||
# Translators: If "and <Month>" needs a special inflection
|
||||
# in your language, translate to "{short_month.f[X]} {year}"
|
||||
# If "and <Month>" needs a special inflection in your
|
||||
# language, translate this to "{short_month.f[X]} {year}"
|
||||
# (where X is one of the month-name inflections you defined)
|
||||
# else leave it untranslated
|
||||
: _("{short_month} {year}", "and"),
|
||||
|
||||
"before"
|
||||
# Translators: If "before <Month>" needs a special inflection
|
||||
# in your language, translate to "{short_month.f[X]} {year}"
|
||||
# If "before <Month>" needs a special inflection in your
|
||||
# language, translate this to "{short_month.f[X]} {year}"
|
||||
# (where X is one of the month-name inflections you defined)
|
||||
# else leave it untranslated
|
||||
: _("{short_month} {year}", "before"),
|
||||
|
||||
"after"
|
||||
# Translators: If "after <Month>" needs a special inflection
|
||||
# in your language, translate to "{short_month.f[X]} {year}"
|
||||
# If "after <Month>" needs a special inflection in your
|
||||
# language, translate this to "{short_month.f[X]} {year}"
|
||||
# (where X is one of the month-name inflections you defined)
|
||||
# else leave it untranslated
|
||||
: _("{short_month} {year}", "after"),
|
||||
|
||||
"about"
|
||||
# Translators: If "about <Month>" needs a special inflection
|
||||
# in your language, translate to "{short_month.f[X]} {year}"
|
||||
# If "about <Month>" needs a special inflection in your
|
||||
# language, translate this to "{short_month.f[X]} {year}"
|
||||
# (where X is one of the month-name inflections you defined)
|
||||
# else leave it untranslated
|
||||
: _("{short_month} {year}", "about"),
|
||||
|
||||
"estimated"
|
||||
# Translators: If "estimated <Month>" needs a special inflection
|
||||
# in your language, translate to "{short_month.f[X]} {year}"
|
||||
# If "estimated <Month>" needs a special inflection in your
|
||||
# language, translate this to "{short_month.f[X]} {year}"
|
||||
# (where X is one of the month-name inflections you defined)
|
||||
# else leave it untranslated
|
||||
: _("{short_month} {year}", "estimated"),
|
||||
|
||||
"calculated"
|
||||
# Translators: If "calculated <Month>" needs a special inflection
|
||||
# in your language, translate to "{short_month.f[X]} {year}"
|
||||
# If "calculated <Month>" needs a special inflection in your
|
||||
# language, translate this to "{short_month.f[X]} {year}"
|
||||
# (where X is one of the month-name inflections you defined)
|
||||
# else leave it untranslated
|
||||
: _("{short_month} {year}", "calculated"),
|
||||
@ -423,14 +421,14 @@ class DateDisplay:
|
||||
qual_str = self._qual_str[date.get_quality()]
|
||||
scal = self.format_extras(cal, date.get_new_year())
|
||||
d1 = self.display_cal[cal](date.get_start_date(),
|
||||
# Translators: If there is no special inflection for
|
||||
# "from <Month>" in your language, DON'T translate this.
|
||||
# Otherwise, translate to "from" in ENGLISH!!! ENGLISH!!!
|
||||
# If there is no special inflection for "from <Month>"
|
||||
# in your language, DON'T translate this string. Otherwise,
|
||||
# "translate" this to "from" in ENGLISH!!! ENGLISH!!!
|
||||
inflect=self._("", "from-date"))
|
||||
d2 = self.display_cal[cal](date.get_stop_date(),
|
||||
# Translators: If there is no special inflection for
|
||||
# "to <Month>" in your language, DON'T translate this.
|
||||
# Otherwise, translate to "to" in ENGLISH!!! ENGLISH!!!
|
||||
# If there is no special inflection for "to <Month>"
|
||||
# in your language, DON'T translate this string. Otherwise,
|
||||
# "translate" this to "to" in ENGLISH!!! ENGLISH!!!
|
||||
inflect=self._("", "to-date"))
|
||||
return self._("{date_quality}from {date_start} to {date_stop}"
|
||||
"{nonstd_calendar_and_ny}").format(
|
||||
@ -448,14 +446,14 @@ class DateDisplay:
|
||||
qual_str = self._qual_str[date.get_quality()]
|
||||
scal = self.format_extras(cal, date.get_new_year())
|
||||
d1 = self.display_cal[cal](date.get_start_date(),
|
||||
# Translators: If there is no special inflection for
|
||||
# "between <Month>" in your language, DON'T translate this.
|
||||
# Otherwise, translate to "between" in ENGLISH!!! ENGLISH!!!
|
||||
# If there is no special inflection for "between <Month>"
|
||||
# in your language, DON'T translate this string. Otherwise,
|
||||
# "translate" this to "between" in ENGLISH!!! ENGLISH!!!
|
||||
inflect=self._("", "between-date"))
|
||||
d2 = self.display_cal[cal](date.get_stop_date(),
|
||||
# Translators: If there is no special inflection for
|
||||
# "and <Month>" in your language, DON'T translate this.
|
||||
# Otherwise, translate to "and" in ENGLISH!!! ENGLISH!!!
|
||||
# If there is no special inflection for "and <Month>"
|
||||
# in your language, DON'T translate this string. Otherwise,
|
||||
# "translate" this to "and" in ENGLISH!!! ENGLISH!!!
|
||||
inflect=self._("", "and-date"))
|
||||
return self._("{date_quality}between {date_start} and {date_stop}"
|
||||
"{nonstd_calendar_and_ny}").format(
|
||||
@ -487,29 +485,29 @@ class DateDisplay:
|
||||
return self.dd_range(date)
|
||||
else:
|
||||
if mod == Date.MOD_BEFORE:
|
||||
# Translators: If there is no special inflection for
|
||||
# "before <Month>" in your language, DON'T translate this.
|
||||
# Otherwise, translate to "before" in ENGLISH!!! ENGLISH!!!
|
||||
# If there is no special inflection for "before <Month>"
|
||||
# in your language, DON'T translate this string. Otherwise,
|
||||
# "translate" this to "before" in ENGLISH!!! ENGLISH!!!
|
||||
date_type = _("", "before-date")
|
||||
elif mod == Date.MOD_AFTER:
|
||||
# Translators: If there is no special inflection for
|
||||
# "after <Month>" in your language, DON'T translate this.
|
||||
# Otherwise, translate to "after" in ENGLISH!!! ENGLISH!!!
|
||||
# If there is no special inflection for "after <Month>"
|
||||
# in your language, DON'T translate this string. Otherwise,
|
||||
# "translate" this to "after" in ENGLISH!!! ENGLISH!!!
|
||||
date_type = _("", "after-date")
|
||||
elif mod == Date.MOD_ABOUT:
|
||||
# Translators: If there is no special inflection for
|
||||
# "about <Month>" in your language, DON'T translate this.
|
||||
# Otherwise, translate to "about" in ENGLISH!!! ENGLISH!!!
|
||||
# If there is no special inflection for "about <Month>"
|
||||
# in your language, DON'T translate this string. Otherwise,
|
||||
# "translate" this to "about" in ENGLISH!!! ENGLISH!!!
|
||||
date_type = _("", "about-date")
|
||||
elif qual == Date.QUAL_ESTIMATED:
|
||||
# Translators: If there is no special inflection for
|
||||
# "estimated <Month>" in your language, DON'T translate this.
|
||||
# Otherwise, translate to "estimated" in ENGLISH!!! ENGLISH!!!
|
||||
# If there is no special inflection for "estimated <Month>"
|
||||
# in your language, DON'T translate this string. Otherwise,
|
||||
# "translate" this to "estimated" in ENGLISH!!! ENGLISH!!!
|
||||
date_type = _("", "estimated-date")
|
||||
elif qual == Date.QUAL_CALCULATED:
|
||||
# Translators: If there is no special inflection for
|
||||
# "calculated <Month>" in your language, DON'T translate this.
|
||||
# Otherwise, translate to "calculated" in ENGLISH!!! ENGLISH!!!
|
||||
# If there is no special inflection for "calculated <Month>"
|
||||
# in your language, DON'T translate this string. Otherwise,
|
||||
# "translate" this to "calculated" in ENGLISH!!! ENGLISH!!!
|
||||
date_type = _("", "calculated-date")
|
||||
else:
|
||||
date_type = ""
|
||||
@ -647,7 +645,7 @@ class DateDisplay:
|
||||
elif date_val[1] == 0: # month is zero but day is not (see 8477)
|
||||
return self.display_iso(date_val)
|
||||
else:
|
||||
# Translators: this month is ALREADY inflected: ignore it
|
||||
# TRANSLATORS: this month is ALREADY inflected: ignore it
|
||||
return _("{long_month} {day:d}, {year}").format(
|
||||
long_month = self.format_long_month(date_val[1],
|
||||
inflect,
|
||||
@ -673,7 +671,7 @@ class DateDisplay:
|
||||
elif date_val[1] == 0: # month is zero but day is not (see 8477)
|
||||
return self.display_iso(date_val)
|
||||
else:
|
||||
# Translators: this month is ALREADY inflected: ignore it
|
||||
# TRANSLATORS: this month is ALREADY inflected: ignore it
|
||||
return _("{short_month} {day:d}, {year}").format(
|
||||
short_month = self.format_short_month(date_val[1],
|
||||
inflect,
|
||||
@ -699,7 +697,7 @@ class DateDisplay:
|
||||
elif date_val[1] == 0: # month is zero but day is not (see 8477)
|
||||
return self.display_iso(date_val)
|
||||
else:
|
||||
# Translators: this month is ALREADY inflected: ignore it
|
||||
# TRANSLATORS: this month is ALREADY inflected: ignore it
|
||||
return _("{day:d} {long_month} {year}").format(
|
||||
day = date_val[0],
|
||||
long_month = self.format_long_month(date_val[1],
|
||||
@ -725,7 +723,7 @@ class DateDisplay:
|
||||
elif date_val[1] == 0: # month is zero but day is not (see 8477)
|
||||
return self.display_iso(date_val)
|
||||
else:
|
||||
# Translators: this month is ALREADY inflected: ignore it
|
||||
# TRANSLATORS: this month is ALREADY inflected: ignore it
|
||||
return _("{day:d} {short_month} {year}").format(
|
||||
day = date_val[0],
|
||||
short_month = self.format_short_month(date_val[1],
|
||||
@ -763,8 +761,7 @@ class DateDisplay:
|
||||
# day month_abbreviation year
|
||||
value = self.dd_dformat05(date_val, inflect, short_months)
|
||||
if date_val[2] < 0:
|
||||
# TODO fix BUG 7064: non-Gregorian calendars wrongly use BCE notation
|
||||
# for negative dates
|
||||
# TODO fix BUG 7064: non-Gregorian calendars wrongly use BCE notation for negative dates
|
||||
return self._bce_str % value
|
||||
else:
|
||||
return value
|
||||
|
||||
@ -72,7 +72,7 @@ class DateStrings:
|
||||
_ = locale.translation.lexgettext
|
||||
|
||||
self.long_months = ( "",
|
||||
# Translators: see
|
||||
# TRANSLATORS: see
|
||||
# http://gramps-project.org/wiki/index.php?title=Translating_Gramps#Translating_dates
|
||||
# to learn how to select proper inflection to be used in your localized
|
||||
# DateDisplayer code!
|
||||
@ -90,7 +90,7 @@ class DateStrings:
|
||||
_("|December", "localized lexeme inflections") )
|
||||
|
||||
self.short_months = ( "",
|
||||
# Translators: see
|
||||
# TRANSLATORS: see
|
||||
# http://gramps-project.org/wiki/index.php?title=Translating_Gramps#Translating_dates
|
||||
# to learn how to select proper inflection to be used in your localized
|
||||
# DateDisplayer code!
|
||||
@ -109,7 +109,7 @@ class DateStrings:
|
||||
|
||||
_ = locale.translation.sgettext
|
||||
self.alt_long_months = ( "",
|
||||
# Translators: see
|
||||
# TRANSLATORS: see
|
||||
# http://gramps-project.org/wiki/index.php?title=Translating_Gramps#Translating_dates
|
||||
# to learn how to add proper alternatives to be recognized in your localized
|
||||
# DateParser code!
|
||||
@ -139,7 +139,7 @@ class DateStrings:
|
||||
|
||||
self.hebrew = (
|
||||
"",
|
||||
# Translators: see
|
||||
# TRANSLATORS: see
|
||||
# http://gramps-project.org/wiki/index.php?title=Translating_Gramps#Translating_dates
|
||||
# to learn how to select proper inflection to be used in your localized
|
||||
# DateDisplayer code!
|
||||
@ -160,7 +160,7 @@ class DateStrings:
|
||||
|
||||
self.french = (
|
||||
"",
|
||||
# Translators: see
|
||||
# TRANSLATORS: see
|
||||
# http://gramps-project.org/wiki/index.php?title=Translating_Gramps#Translating_dates
|
||||
# to learn how to select proper inflection to be used in your localized
|
||||
# DateDisplayer code!
|
||||
@ -181,7 +181,7 @@ class DateStrings:
|
||||
|
||||
self.islamic = (
|
||||
"",
|
||||
# Translators: see
|
||||
# TRANSLATORS: see
|
||||
# http://gramps-project.org/wiki/index.php?title=Translating_Gramps#Translating_dates
|
||||
# to learn how to select proper inflection to be used in your localized
|
||||
# DateDisplayer code!
|
||||
@ -201,7 +201,7 @@ class DateStrings:
|
||||
|
||||
self.persian = (
|
||||
"",
|
||||
# Translators: see
|
||||
# TRANSLATORS: see
|
||||
# http://gramps-project.org/wiki/index.php?title=Translating_Gramps#Translating_dates
|
||||
# to learn how to select proper inflection to be used in your localized
|
||||
# DateDisplayer code!
|
||||
@ -220,13 +220,13 @@ class DateStrings:
|
||||
)
|
||||
|
||||
self.modifiers = ("",
|
||||
# Translators: if the modifier is after the date
|
||||
# TRANSLATORS: if the modifier is after the date
|
||||
# put the space ahead of the word instead of after it
|
||||
_("before ", "date modifier"),
|
||||
# Translators: if the modifier is after the date
|
||||
# TRANSLATORS: if the modifier is after the date
|
||||
# put the space ahead of the word instead of after it
|
||||
_("after ", "date modifier"),
|
||||
# Translators: if the modifier is after the date
|
||||
# TRANSLATORS: if the modifier is after the date
|
||||
# put the space ahead of the word instead of after it
|
||||
_("about ", "date modifier"),
|
||||
"", "", "")
|
||||
|
||||
@ -35,7 +35,6 @@ import ast
|
||||
import sys
|
||||
import datetime
|
||||
import glob
|
||||
from pathlib import Path
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
@ -68,6 +67,17 @@ LOG = logging.getLogger(DBLOGNAME)
|
||||
SIGBASE = ('person', 'family', 'source', 'event', 'media',
|
||||
'place', 'repository', 'reference', 'note', 'tag', 'citation')
|
||||
|
||||
def touch(fname, mode=0o666, dir_fd=None, **kwargs):
|
||||
## After http://stackoverflow.com/questions/1158076/implement-touch-using-python
|
||||
if sys.version_info < (3, 3, 0):
|
||||
with open(fname, 'a'):
|
||||
os.utime(fname, None) # set to now
|
||||
else:
|
||||
flags = os.O_CREAT | os.O_APPEND
|
||||
with os.fdopen(os.open(fname, flags=flags, mode=mode, dir_fd=dir_fd)) as f:
|
||||
os.utime(f.fileno() if os.utime in os.supports_fd else fname,
|
||||
dir_fd=None if os.supports_fd else dir_fd, **kwargs)
|
||||
|
||||
class DbGenericUndo(DbUndo):
|
||||
def __init__(self, grampsdb, path):
|
||||
super(DbGenericUndo, self).__init__(grampsdb)
|
||||
@ -681,7 +691,7 @@ class DbGeneric(DbWriteBase, DbReadBase, UpdateCallback, Callback):
|
||||
# This is just a dummy file to indicate last modified time of
|
||||
# the database for gramps.cli.clidbman:
|
||||
filename = os.path.join(self._directory, "meta_data.db")
|
||||
Path(filename).touch()
|
||||
touch(filename)
|
||||
|
||||
# Save metadata
|
||||
self._set_metadata('name_formats', self.name_formats)
|
||||
|
||||
@ -345,7 +345,7 @@ class NameDisplay:
|
||||
global WITH_GRAMPS_CONFIG
|
||||
global PAT_AS_SURN
|
||||
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore otherwise
|
||||
COMMAGLYPH = xlocale.translation.gettext(',')
|
||||
|
||||
self.STANDARD_FORMATS = [
|
||||
@ -358,7 +358,7 @@ class NameDisplay:
|
||||
(Name.FNLN, _("Given Surname Suffix"),
|
||||
'%f %l %s', _ACT),
|
||||
# primary name primconnector other, given pa/matronynic suffix, primprefix
|
||||
# Translators: long string, have a look at Preferences dialog
|
||||
# translators: long string, have a look at Preferences dialog
|
||||
(Name.LNFNP, _("Main Surnames, Given Patronymic Suffix Prefix"),
|
||||
'%1m %2m %o' + COMMAGLYPH + ' %f %1y %s %0m', _ACT),
|
||||
# DEPRECATED FORMATS
|
||||
|
||||
@ -423,23 +423,23 @@ class Span:
|
||||
retval = ""
|
||||
detail = 0
|
||||
if diff_tuple[0] != 0:
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
retval += ngettext("{number_of} year", "{number_of} years",
|
||||
diff_tuple[0]
|
||||
).format(number_of=diff_tuple[0])
|
||||
detail += 1
|
||||
if self.precision == detail:
|
||||
if diff_tuple[1] >= 6: # round up years
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
retval = ngettext("{number_of} year", "{number_of} years",
|
||||
diff_tuple[0] + 1
|
||||
).format(number_of=diff_tuple[0] + 1)
|
||||
return retval
|
||||
if diff_tuple[1] != 0:
|
||||
if retval != "":
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore otherwise
|
||||
retval += trans_text(", ")
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
retval += ngettext("{number_of} month", "{number_of} months",
|
||||
diff_tuple[1]
|
||||
).format(number_of=diff_tuple[1])
|
||||
@ -448,9 +448,9 @@ class Span:
|
||||
return retval
|
||||
if diff_tuple[2] != 0:
|
||||
if retval != "":
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore otherwise
|
||||
retval += trans_text(", ")
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
retval += ngettext("{number_of} day", "{number_of} days",
|
||||
diff_tuple[2]
|
||||
).format(number_of=diff_tuple[2])
|
||||
|
||||
@ -457,11 +457,11 @@ class Name(SecondaryObject, PrivacyBase, SurnameBase, CitationBase, NoteBase,
|
||||
first = self.first_name
|
||||
surname = self.get_surname()
|
||||
if self.suffix:
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore otherwise
|
||||
return _("%(surname)s, %(first)s %(suffix)s"
|
||||
) % {'surname':surname, 'first':first, 'suffix':self.suffix}
|
||||
else:
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore otherwise
|
||||
return _("%(str1)s, %(str2)s") % {'str1':surname, 'str2':first}
|
||||
|
||||
def get_upper_name(self):
|
||||
@ -472,11 +472,11 @@ class Name(SecondaryObject, PrivacyBase, SurnameBase, CitationBase, NoteBase,
|
||||
first = self.first_name
|
||||
surname = self.get_surname().upper()
|
||||
if self.suffix:
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore otherwise
|
||||
return _("%(surname)s, %(first)s %(suffix)s"
|
||||
) % {'surname':surname, 'first':first, 'suffix':self.suffix}
|
||||
else:
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore otherwise
|
||||
return _("%(str1)s, %(str2)s") % {'str1':surname, 'str2':first}
|
||||
|
||||
def get_regular_name(self):
|
||||
@ -489,7 +489,7 @@ class Name(SecondaryObject, PrivacyBase, SurnameBase, CitationBase, NoteBase,
|
||||
if self.suffix == "":
|
||||
return "%s %s" % (first, surname)
|
||||
else:
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore otherwise
|
||||
return _("%(first)s %(surname)s, %(suffix)s"
|
||||
) % {'surname':surname, 'first':first, 'suffix':self.suffix}
|
||||
|
||||
|
||||
@ -114,7 +114,7 @@ def cite_source(bibliography, database, obj, elocale=glocale):
|
||||
first = True
|
||||
for ref in slist:
|
||||
if not first:
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore otherwise
|
||||
txt += trans_text(', ')
|
||||
first = False
|
||||
citation = database.get_citation_from_handle(ref)
|
||||
@ -171,7 +171,7 @@ def write_endnotes(bibliography, database, doc, printnotes=False, links=False,
|
||||
'Endnotes-Source-Notes', links)
|
||||
|
||||
for key, ref in citation.get_ref_list():
|
||||
# Translators: needed for French, ignore otherwise
|
||||
# translators: needed for French, ignore otherwise
|
||||
doc.start_paragraph('Endnotes-Ref', trans_text('%s:') % key)
|
||||
doc.write_text(_format_ref_text(ref, key, elocale), links=links)
|
||||
doc.end_paragraph()
|
||||
@ -193,20 +193,20 @@ def _format_source_text(source, elocale):
|
||||
|
||||
if source.get_title():
|
||||
if src_txt:
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore otherwise
|
||||
src_txt += trans_text(', ')
|
||||
# Translators: used in French+Russian, ignore otherwise
|
||||
# translators: used in French+Russian, ignore otherwise
|
||||
src_txt += trans_text('"%s"') % source.get_title()
|
||||
|
||||
if source.get_publication_info():
|
||||
if src_txt:
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore otherwise
|
||||
src_txt += trans_text(', ')
|
||||
src_txt += source.get_publication_info()
|
||||
|
||||
if source.get_abbreviation():
|
||||
if src_txt:
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore otherwise
|
||||
src_txt += trans_text(', ')
|
||||
src_txt += "(%s)" % source.get_abbreviation()
|
||||
|
||||
|
||||
@ -65,22 +65,6 @@ def add_localization_option(menu, category):
|
||||
menu.add_option(category, "trans", trans)
|
||||
return trans
|
||||
|
||||
def add_extra_localization_option(menu, category, name, optname):
|
||||
"""
|
||||
Insert an option for localizing the report into a different locale
|
||||
than the default one
|
||||
"""
|
||||
|
||||
trans = EnumeratedListOption(_(name),
|
||||
glocale.DEFAULT_TRANSLATION_STR)
|
||||
trans.add_item(glocale.DEFAULT_TRANSLATION_STR, _("Default"))
|
||||
languages = glocale.get_language_dict()
|
||||
for language in sorted(languages, key=glocale.sort_key):
|
||||
trans.add_item(languages[language], language)
|
||||
trans.set_help(_("The additional translation to be used for the report."))
|
||||
menu.add_option(category, optname, trans)
|
||||
return trans
|
||||
|
||||
def add_name_format_option(menu, category):
|
||||
"""
|
||||
Insert an option for changing the report's name format to a
|
||||
@ -317,24 +301,6 @@ def run_date_format_option(report, menu):
|
||||
format_to_be = 0 # ISO always exists
|
||||
report._ldd.set_format(format_to_be)
|
||||
|
||||
def add_tags_option(menu, category):
|
||||
"""
|
||||
Insert an option for deciding whether to include tags
|
||||
in the report
|
||||
|
||||
:param menu: The menu the options should be added to.
|
||||
:type menu: :class:`.Menu`
|
||||
:param category: A label that describes the category that the option
|
||||
belongs to, e.g. "Report Options"
|
||||
:type category: string
|
||||
"""
|
||||
|
||||
include_tags = EnumeratedListOption(_('Tags'), 0)
|
||||
include_tags.add_item(0, _('Do not include'))
|
||||
include_tags.add_item(1, _('Include'))
|
||||
include_tags.set_help(_("Whether to include tags"))
|
||||
menu.add_option(category, 'inc_tags', include_tags)
|
||||
|
||||
def add_gramps_id_option(menu, category, ownline=False):
|
||||
"""
|
||||
Insert an option for deciding whether to include Gramps IDs
|
||||
|
||||
@ -252,7 +252,7 @@ def get_address_str(addr):
|
||||
if addr_str == "":
|
||||
addr_str = info
|
||||
else:
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore otherwise
|
||||
addr_str = _("%(str1)s, %(str2)s"
|
||||
) % {'str1' : addr_str, 'str2' : info}
|
||||
return addr_str
|
||||
|
||||
@ -75,7 +75,6 @@ _LOCALE_NAMES = {
|
||||
'cs': ('Czech_Czech Republic', '1250', _("Czech")),
|
||||
'da': ('Danish_Denmark', '1252', _("Danish")),
|
||||
'de': ('German_Germany', '1252', _("German")),
|
||||
'de_AT': ('German_Austria', '1252', _("German (Austria)")),
|
||||
'el': ('Greek_Greece', '1253', _("Greek")),
|
||||
'en': ('English_United States', '1252', _("English (USA)")),
|
||||
'en_GB': ('English_United Kingdom', '1252', _("English")),
|
||||
@ -1038,12 +1037,10 @@ class Lexeme(str):
|
||||
|
||||
Translation database (Russian example)::
|
||||
|
||||
msgctxt "localized lexeme inflections"
|
||||
msgid "|December"
|
||||
msgid "lexeme||December"
|
||||
msgstr "NOMINATIVE=декабрь|GENITIVE=декабря|ABLATIVE=декабрём|LOCATIVE=декабре"
|
||||
|
||||
msgctxt "lexeme"
|
||||
msgid "|Christmas"
|
||||
msgid "lexeme||Christmas"
|
||||
msgstr "NOMINATIVE=рождество|GENITIVE=рождества|ABLATIVE=рождеством"
|
||||
|
||||
msgid "{holiday} is celebrated in {month}"
|
||||
|
||||
@ -163,39 +163,13 @@ def image_size(source):
|
||||
from gi.repository import GdkPixbuf
|
||||
from gi.repository import GLib
|
||||
try:
|
||||
import re
|
||||
import magic
|
||||
# For performance reasons, we'll try to get image size from magic.
|
||||
# This avoid to load the image in memory. This is a real improvement
|
||||
# when we have many big images.
|
||||
# Used in odfdoc, rtfdoc and webreport and tested with png, gif, jpeg,
|
||||
# bmp, tiff
|
||||
#
|
||||
# file size with magic without (Gdk) ratio
|
||||
# example 1 : 256k 0.00080 0.00575 7
|
||||
# example 2 : 21M 0.00171 0.55860 326
|
||||
img = magic.from_file(source)
|
||||
found = img.find("TIFF")
|
||||
if found == 0:
|
||||
width = re.search('width=(\d+)', img).groups()
|
||||
height = re.search('height=(\d+)', img).groups()
|
||||
return (int(width[0]), int(height[0]))
|
||||
found = img.find("precision")
|
||||
if found > 0:
|
||||
img = img[found:]
|
||||
size = re.search('(\d+)\s*x\s*(\d+)', img).groups()
|
||||
return (int(size[0]), int(size[1]))
|
||||
except (ImportError, FileNotFoundError):
|
||||
# python-magic is not installed or the file does not exist.
|
||||
# So Trying to get image size with Gdk.
|
||||
try:
|
||||
img = GdkPixbuf.Pixbuf.new_from_file(source)
|
||||
width = img.get_width()
|
||||
height = img.get_height()
|
||||
except GLib.GError:
|
||||
width = 0
|
||||
height = 0
|
||||
return (width, height)
|
||||
img = GdkPixbuf.Pixbuf.new_from_file(source)
|
||||
width = img.get_width()
|
||||
height = img.get_height()
|
||||
except GLib.GError:
|
||||
width = 0
|
||||
height = 0
|
||||
return (width, height)
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
|
||||
@ -20,7 +20,19 @@
|
||||
#
|
||||
|
||||
import unittest
|
||||
from unittest.mock import Mock
|
||||
import sys
|
||||
|
||||
try:
|
||||
if sys.version_info < (3,3):
|
||||
from mock import Mock
|
||||
else:
|
||||
from unittest.mock import Mock
|
||||
|
||||
MOCKING = True
|
||||
|
||||
except:
|
||||
MOCKING = False
|
||||
print ("Mocking disabled, some testing skipped", sys.exc_info()[0:2])
|
||||
|
||||
class LexGettextTest(unittest.TestCase):
|
||||
SRC_WORD = "Inflect-me"
|
||||
@ -33,15 +45,19 @@ class LexGettextTest(unittest.TestCase):
|
||||
self.trans = GrampsTranslations()
|
||||
|
||||
def setup_sgettext_mock(self, msgval_expected):
|
||||
mock = Mock(return_value=msgval_expected)
|
||||
if MOCKING:
|
||||
mock = Mock(return_value=msgval_expected)
|
||||
else:
|
||||
mock = lambda msgid: msgval_expected
|
||||
self.trans.sgettext = mock
|
||||
|
||||
def tearDown(self):
|
||||
try:
|
||||
self.trans.sgettext.assert_called_once_with(
|
||||
self.MSGID, self.CONTEXT)
|
||||
except AttributeError as e:
|
||||
print ("Apparently the test has never set up the mock: ", e)
|
||||
if MOCKING:
|
||||
try:
|
||||
self.trans.sgettext.assert_called_once_with(
|
||||
self.MSGID, self.CONTEXT)
|
||||
except AttributeError as e:
|
||||
print ("Apparently the test has never set up the mock: ", e)
|
||||
|
||||
def testSrcWordOnlyIfNoTranslation(self):
|
||||
self.setup_sgettext_mock(self.SRC_WORD)
|
||||
|
||||
@ -102,7 +102,7 @@ except:
|
||||
# code. That unfortunately initializes GrampsLocale, so it has its own
|
||||
# logging setup during initialization.
|
||||
#-------------------------------------------------------------------------
|
||||
"""Set up basic logging support."""
|
||||
"""Setup basic logging support."""
|
||||
|
||||
# Setup a formatter
|
||||
form = logging.Formatter(fmt="%(asctime)s.%(msecs).03d: %(levelname)s: "
|
||||
@ -167,10 +167,10 @@ from .gen.mime import mime_type_is_defined
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
MIN_PYTHON_VERSION = (3, 5, 0, '', 0)
|
||||
MIN_PYTHON_VERSION = (3, 3, 0, '', 0)
|
||||
if not sys.version_info >= MIN_PYTHON_VERSION:
|
||||
logging.warning(_("Your Python version does not meet the "
|
||||
"requirements. At least Python %(v1)d.%(v2)d.%(v3)d is needed to"
|
||||
"requirements. At least python %(v1)d.%(v2)d.%(v3)d is needed to"
|
||||
" start Gramps.\n\n"
|
||||
"Gramps will terminate now.") % {
|
||||
'v1': MIN_PYTHON_VERSION[0],
|
||||
@ -397,7 +397,7 @@ def show_settings():
|
||||
for folder in sys.path:
|
||||
print(" ", folder)
|
||||
print('')
|
||||
print("Non-Python dependencies:")
|
||||
print("Non-python dependencies:")
|
||||
print("------------------------")
|
||||
print(' Graphviz : %s' % dotversion_str)
|
||||
print(' Ghostscr. : %s' % gsversion_str)
|
||||
@ -428,15 +428,15 @@ def run():
|
||||
error += [(_("Configuration error:"), str(msg))]
|
||||
return error
|
||||
except msg:
|
||||
LOG.error("Could not read configuration.", exc_info=True)
|
||||
return [(_("Could not read configuration"), str(msg))]
|
||||
LOG.error("Error reading configuration.", exc_info=True)
|
||||
return [(_("Error reading configuration"), str(msg))]
|
||||
|
||||
if not mime_type_is_defined(APP_GRAMPS):
|
||||
error += [(_("Configuration error:"),
|
||||
_("A definition for the media type %s could not "
|
||||
_("A definition for the MIME-type %s could not "
|
||||
"be found \n\n Possibly the installation of Gramps "
|
||||
"was incomplete. Make sure something to handle the "
|
||||
"media types of Gramps is installed.")
|
||||
"was incomplete. Make sure the MIME-types "
|
||||
"of Gramps are properly installed.")
|
||||
% APP_GRAMPS)]
|
||||
|
||||
# we start with parsing the arguments to determine if we have a cli or a
|
||||
@ -480,7 +480,7 @@ def run():
|
||||
LOG.debug('environment: LANGUAGE is not defined')
|
||||
|
||||
if argpars.need_gui():
|
||||
LOG.debug("A GUI is needed. Set one up.")
|
||||
LOG.debug("A GUI is needed, set it up")
|
||||
try:
|
||||
from .gui.grampsgui import startgramps
|
||||
# no DISPLAY is a RuntimeError in an older pygtk (e.g. 2.17 in Fedora 14)
|
||||
|
||||
@ -116,7 +116,7 @@ class GrampsAboutDialog(Gtk.AboutDialog):
|
||||
if len(contributors) > 0:
|
||||
self.add_credit_section(_('Contributions by'), contributors)
|
||||
|
||||
# Translators: Translate this to your name in your native language
|
||||
# TRANSLATORS: Translate this to your name in your native language
|
||||
self.set_translator_credits(_("translator-credits"))
|
||||
|
||||
self.set_documenters(DOCUMENTERS)
|
||||
|
||||
@ -410,7 +410,7 @@ class ConfigureDialog(ManagedWindow):
|
||||
if not callback:
|
||||
callback = self.update_entry
|
||||
if label:
|
||||
lwidget = BasicLabel(_("%s: ") % label) # Translators: for French
|
||||
lwidget = BasicLabel(_("%s: ") % label) # translators: for French
|
||||
entry = Gtk.Entry()
|
||||
if localized_config:
|
||||
entry.set_text(config.get(constant))
|
||||
|
||||
@ -294,7 +294,7 @@ class DBErrorDialog(ErrorDialog):
|
||||
self,
|
||||
_("Low level database corruption detected"),
|
||||
_("Gramps has detected a problem in the underlying "
|
||||
"database. This can sometimes be repaired from "
|
||||
"Berkeley database. This can be repaired from "
|
||||
"the Family Tree Manager. Select the database and "
|
||||
'click on the Repair button') + '\n\n' + msg, parent)
|
||||
|
||||
|
||||
@ -75,4 +75,9 @@ def display_url(link, uistate=None):
|
||||
"""
|
||||
Open the specified URL in a browser.
|
||||
"""
|
||||
webbrowser.open_new_tab(link)
|
||||
if (mac() and sys.version_info.major == 3 and sys.version_info.minor < 5):
|
||||
import subprocess
|
||||
proc = subprocess.call(['/usr/bin/open', link],
|
||||
stderr=subprocess.STDOUT)
|
||||
else:
|
||||
webbrowser.open_new_tab(link)
|
||||
|
||||
@ -25,13 +25,14 @@
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import logging
|
||||
LOG = logging.getLogger(".citation")
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GTK/Gnome modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gi.repository import GLib
|
||||
from gi.repository import GObject, GLib
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -39,6 +40,7 @@ from gi.repository import GLib
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.translation.gettext
|
||||
from gramps.gen.errors import WindowActiveError
|
||||
from gramps.gen.lib import Citation, Source
|
||||
from ...dbguielement import DbGUIElement
|
||||
@ -47,8 +49,6 @@ from .citationrefmodel import CitationRefModel
|
||||
from .embeddedlist import EmbeddedList, TEXT_COL, MARKUP_COL, ICON_COL
|
||||
from ...ddtargets import DdTargets
|
||||
|
||||
LOG = logging.getLogger(".citation")
|
||||
_ = glocale.translation.gettext
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# CitationEmbedList
|
||||
@ -61,7 +61,7 @@ class CitationEmbedList(EmbeddedList, DbGUIElement):
|
||||
Derives from the EmbeddedList class.
|
||||
"""
|
||||
|
||||
_HANDLE_COL = 9 # Column number from CitationRefModel
|
||||
_HANDLE_COL = 5 # Column number from CitationRefModel
|
||||
_DND_TYPE = DdTargets.CITATION_LINK
|
||||
_DND_EXTRA = DdTargets.SOURCE_LINK
|
||||
|
||||
@ -77,15 +77,11 @@ class CitationEmbedList(EmbeddedList, DbGUIElement):
|
||||
#index = column in model. Value =
|
||||
# (name, sortcol in model, width, markup/text, weigth_col
|
||||
_column_names = [
|
||||
(_('Title'), 0, 350, TEXT_COL, -1, None),
|
||||
(_('Author'), 1, 200, TEXT_COL, -1, None),
|
||||
(_('Date'), 8, 180, MARKUP_COL, -1, None),
|
||||
(_('Publisher'), 3, 200, TEXT_COL, -1, None),
|
||||
(_('Confidence Level'), 4, 120, TEXT_COL, -1, None),
|
||||
(_('Page'), 5, 100, TEXT_COL, -1, None),
|
||||
(_('ID'), 6, 80, TEXT_COL, -1, None),
|
||||
(_('Private'), 7, 30, ICON_COL, -1, 'gramps-lock'),
|
||||
(_('Sorted date'), 8, 80, TEXT_COL, -1, None)
|
||||
(_('Title'), 0, 200, TEXT_COL, -1, None),
|
||||
(_('Author'), 1, 125, TEXT_COL, -1, None),
|
||||
(_('Page'), 2, 100, TEXT_COL, -1, None),
|
||||
(_('ID'), 3, 75, TEXT_COL, -1, None),
|
||||
(_('Private'), 4, 30, ICON_COL, -1, 'gramps-lock')
|
||||
]
|
||||
|
||||
def __init__(self, dbstate, uistate, track, data, callertitle=None):
|
||||
@ -104,9 +100,9 @@ class CitationEmbedList(EmbeddedList, DbGUIElement):
|
||||
#citation: citation-rebuild closes the editors, so no need to connect
|
||||
# to it
|
||||
self.callman.register_callbacks(
|
||||
{'citation-delete': self.citation_delete,
|
||||
'citation-update': self.citation_update,
|
||||
})
|
||||
{'citation-delete': self.citation_delete,
|
||||
'citation-update': self.citation_update,
|
||||
})
|
||||
self.callman.connect_all(keys=['citation'])
|
||||
|
||||
def get_icon_name(self):
|
||||
@ -125,7 +121,7 @@ class CitationEmbedList(EmbeddedList, DbGUIElement):
|
||||
"""
|
||||
Return the column order of the columns in the display tab.
|
||||
"""
|
||||
return ((1, 0), (1, 1), (1, 5), (1, 2), (1, 3), (1, 6), (1, 4), (1, 7))
|
||||
return ((1, 4), (1, 0), (1, 1), (1, 2), (1, 3))
|
||||
|
||||
def add_button_clicked(self, obj):
|
||||
"""
|
||||
@ -159,15 +155,15 @@ class CitationEmbedList(EmbeddedList, DbGUIElement):
|
||||
SelectCitation = SelectorFactory('Citation')
|
||||
|
||||
sel = SelectCitation(self.dbstate, self.uistate, self.track)
|
||||
objct = sel.run()
|
||||
LOG.debug("selected object: %s" % objct)
|
||||
object = sel.run()
|
||||
LOG.debug("selected object: %s" % object)
|
||||
# the object returned should either be a Source or a Citation
|
||||
if objct:
|
||||
if isinstance(objct, Source):
|
||||
if object:
|
||||
if isinstance(object, Source):
|
||||
try:
|
||||
from .. import EditCitation
|
||||
EditCitation(self.dbstate, self.uistate, self.track,
|
||||
Citation(), objct,
|
||||
Citation(), object,
|
||||
callback=self.add_callback,
|
||||
callertitle=self.callertitle)
|
||||
except WindowActiveError:
|
||||
@ -175,11 +171,11 @@ class CitationEmbedList(EmbeddedList, DbGUIElement):
|
||||
WarningDialog(_("Cannot share this reference"),
|
||||
self.__blocked_text(),
|
||||
parent=self.uistate.window)
|
||||
elif isinstance(objct, Citation):
|
||||
elif isinstance(object, Citation):
|
||||
try:
|
||||
from .. import EditCitation
|
||||
EditCitation(self.dbstate, self.uistate, self.track,
|
||||
objct, callback=self.add_callback,
|
||||
object, callback=self.add_callback,
|
||||
callertitle=self.callertitle)
|
||||
except WindowActiveError:
|
||||
from ...dialog import WarningDialog
|
||||
@ -194,10 +190,10 @@ class CitationEmbedList(EmbeddedList, DbGUIElement):
|
||||
Return the common text used when citation cannot be edited
|
||||
"""
|
||||
return _("This citation cannot be created at this time. "
|
||||
"Either the associated Source object is already being "
|
||||
"edited, or another citation associated with the same "
|
||||
"source is being edited.\n\nTo edit this "
|
||||
"citation, you need to close the object.")
|
||||
"Either the associated Source object is already being "
|
||||
"edited, or another citation associated with the same "
|
||||
"source is being edited.\n\nTo edit this "
|
||||
"citation, you need to close the object.")
|
||||
|
||||
def edit_button_clicked(self, obj):
|
||||
"""
|
||||
@ -214,7 +210,7 @@ class CitationEmbedList(EmbeddedList, DbGUIElement):
|
||||
try:
|
||||
from .. import EditCitation
|
||||
EditCitation(self.dbstate, self.uistate, self.track, citation,
|
||||
callertitle=self.callertitle)
|
||||
callertitle = self.callertitle)
|
||||
except WindowActiveError:
|
||||
pass
|
||||
|
||||
@ -226,7 +222,7 @@ class CitationEmbedList(EmbeddedList, DbGUIElement):
|
||||
so this method need not do this
|
||||
"""
|
||||
rebuild = False
|
||||
for handle in del_citation_handle_list:
|
||||
for handle in del_citation_handle_list :
|
||||
while self.data.count(handle) > 0:
|
||||
self.data.remove(handle)
|
||||
rebuild = True
|
||||
@ -238,7 +234,7 @@ class CitationEmbedList(EmbeddedList, DbGUIElement):
|
||||
Outside of this tab citation objects have been updated. Check if tab
|
||||
and object must be updated.
|
||||
"""
|
||||
for handle in upd_citation_handle_list:
|
||||
for handle in upd_citation_handle_list :
|
||||
if handle in self.data:
|
||||
self.rebuild()
|
||||
break
|
||||
@ -248,12 +244,12 @@ class CitationEmbedList(EmbeddedList, DbGUIElement):
|
||||
A CITATION_LINK has been dragged
|
||||
"""
|
||||
if handle:
|
||||
objct = self.dbstate.db.get_citation_from_handle(handle)
|
||||
if isinstance(objct, Citation):
|
||||
object = self.dbstate.db.get_citation_from_handle(handle)
|
||||
if isinstance(object, Citation):
|
||||
try:
|
||||
from .. import EditCitation
|
||||
EditCitation(self.dbstate, self.uistate, self.track,
|
||||
objct, callback=self.add_callback,
|
||||
object, callback=self.add_callback,
|
||||
callertitle=self.callertitle)
|
||||
except WindowActiveError:
|
||||
from ...dialog import WarningDialog
|
||||
@ -268,12 +264,12 @@ class CitationEmbedList(EmbeddedList, DbGUIElement):
|
||||
A SOURCE_LINK object has been dragged
|
||||
"""
|
||||
if handle:
|
||||
objct = self.dbstate.db.get_source_from_handle(handle)
|
||||
if isinstance(objct, Source):
|
||||
object = self.dbstate.db.get_source_from_handle(handle)
|
||||
if isinstance(object, Source):
|
||||
try:
|
||||
from .. import EditCitation
|
||||
EditCitation(self.dbstate, self.uistate, self.track,
|
||||
Citation(), objct,
|
||||
Citation(), object,
|
||||
callback=self.add_callback,
|
||||
callertitle=self.callertitle)
|
||||
except WindowActiveError:
|
||||
|
||||
@ -25,10 +25,6 @@
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gi.repository import Gtk
|
||||
from gramps.gen.utils.string import conf_strings
|
||||
from gramps.gen.datehandler import (get_date, get_date_valid)
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -38,32 +34,11 @@ _ = glocale.translation.gettext
|
||||
class CitationRefModel(Gtk.ListStore):
|
||||
|
||||
def __init__(self, citation_list, db):
|
||||
Gtk.ListStore.__init__(self, str, str, str, str, str, str, str,
|
||||
bool, str, str)
|
||||
Gtk.ListStore.__init__(self, str, str, str, str, bool, str)
|
||||
self.db = db
|
||||
dbgsfh = self.db.get_source_from_handle
|
||||
for handle in citation_list:
|
||||
citation = self.db.get_citation_from_handle(handle)
|
||||
src = dbgsfh(citation.get_reference_handle())
|
||||
confidence = citation.get_confidence_level()
|
||||
self.append(row=[src.title, src.author,
|
||||
self.column_date(citation),
|
||||
src.get_publication_info(),
|
||||
_(conf_strings[confidence]), citation.page,
|
||||
src = self.db.get_source_from_handle(citation.get_reference_handle())
|
||||
self.append(row=[src.title, src.author, citation.page,
|
||||
citation.gramps_id, citation.get_privacy(),
|
||||
self.column_sort_date(citation),
|
||||
handle, ])
|
||||
|
||||
def column_date(self, citation):
|
||||
retval = get_date(citation)
|
||||
if not get_date_valid(citation):
|
||||
return invalid_date_format % escape(retval)
|
||||
else:
|
||||
return retval
|
||||
|
||||
def column_sort_date(self, citation):
|
||||
date = citation.get_date_object()
|
||||
if date:
|
||||
return "%09d" % date.get_sort_value()
|
||||
else:
|
||||
return ""
|
||||
|
||||
@ -991,14 +991,14 @@ class EditFamily(EditPrimary):
|
||||
if birth:
|
||||
#if event changes it view needs to update
|
||||
self.callman.register_handles({'event': [birth.get_handle()]})
|
||||
# Translators: needed for French, ignore otherwise
|
||||
# translators: needed for French, ignore otherwise
|
||||
birth_label.set_label(_("%s:") % birth.get_type())
|
||||
|
||||
death = get_death_or_fallback(db, person)
|
||||
if death:
|
||||
#if event changes it view needs to update
|
||||
self.callman.register_handles({'event': [death.get_handle()]})
|
||||
# Translators: needed for French, ignore otherwise
|
||||
# translators: needed for French, ignore otherwise
|
||||
death_label.set_label(_("%s:") % death.get_type())
|
||||
|
||||
btn_edit.set_tooltip_text(_('Edit %s') % name)
|
||||
|
||||
@ -326,7 +326,6 @@ class EditMedia(EditPrimary):
|
||||
with DbTxn(_("Add Media Object (%s)") % self.obj.get_description(),
|
||||
self.db) as trans:
|
||||
self.db.add_media(self.obj, trans)
|
||||
self.uistate.set_active(self.obj.handle, "Media")
|
||||
else:
|
||||
if self.data_has_changed():
|
||||
with DbTxn(_("Edit Media Object (%s)") % self.obj.get_description(),
|
||||
|
||||
@ -187,13 +187,9 @@ class EditPlace(EditPrimary):
|
||||
|
||||
def set_latlongitude(self, value):
|
||||
try:
|
||||
parts = value.index(', ')
|
||||
if len(parts) == 2:
|
||||
longitude = parts[0].strip().replace(',', '.')
|
||||
latitude = parts[1].strip().replace(',', '.')
|
||||
else:
|
||||
longitude, latitude = value.split(',')
|
||||
|
||||
coma = value.index(', ')
|
||||
longitude = value[coma+2:].strip().replace(',','.')
|
||||
latitude = value[:coma].strip().replace(',','.')
|
||||
self.longitude.set_text(longitude)
|
||||
self.latitude.set_text(latitude)
|
||||
self.top.get_object("lat_entry").validate(force=True)
|
||||
@ -209,12 +205,12 @@ class EditPlace(EditPrimary):
|
||||
def _validate_coordinate(self, widget, text, typedeg):
|
||||
if (typedeg == 'lat') and not conv_lat_lon(text, "0", "ISO-D"):
|
||||
return ValidationError(
|
||||
# Translators: translate the "S" too (and the "or" of course)
|
||||
# translators: translate the "S" too (and the "or" of course)
|
||||
_('Invalid latitude\n(syntax: '
|
||||
'18\u00b09\'48.21"S, -18.2412 or -18:9:48.21)'))
|
||||
elif (typedeg == 'lon') and not conv_lat_lon("0", text, "ISO-D"):
|
||||
return ValidationError(
|
||||
# Translators: translate the "E" too (and the "or" of course)
|
||||
# translators: translate the "E" too (and the "or" of course)
|
||||
_('Invalid longitude\n(syntax: '
|
||||
'18\u00b09\'48.21"E, -18.2412 or -18:9:48.21)'))
|
||||
|
||||
|
||||
@ -181,13 +181,9 @@ class EditPlaceRef(EditReference):
|
||||
|
||||
def set_latlongitude(self, value):
|
||||
try:
|
||||
parts = value.index(', ')
|
||||
if len(parts) == 2:
|
||||
longitude = parts[0].strip().replace(',', '.')
|
||||
latitude = parts[1].strip().replace(',', '.')
|
||||
else:
|
||||
longitude, latitude = value.split(',')
|
||||
|
||||
coma = value.index(', ')
|
||||
longitude = value[coma+2:].strip().replace(',','.')
|
||||
latitude = value[:coma].strip().replace(',','.')
|
||||
self.longitude.set_text(longitude)
|
||||
self.latitude.set_text(latitude)
|
||||
self.top.get_object("lat_entry").validate(force=True)
|
||||
@ -203,12 +199,12 @@ class EditPlaceRef(EditReference):
|
||||
def _validate_coordinate(self, widget, text, typedeg):
|
||||
if (typedeg == 'lat') and not conv_lat_lon(text, "0", "ISO-D"):
|
||||
return ValidationError(
|
||||
# Translators: translate the "S" too (and the "or" of course)
|
||||
# translators: translate the "S" too (and the "or" of course)
|
||||
_('Invalid latitude\n(syntax: '
|
||||
'18\u00b09\'48.21"S, -18.2412 or -18:9:48.21)'))
|
||||
elif (typedeg == 'lon') and not conv_lat_lon("0", text, "ISO-D"):
|
||||
return ValidationError(
|
||||
# Translators: translate the "E" too (and the "or" of course)
|
||||
# translators: translate the "E" too (and the "or" of course)
|
||||
_('Invalid longitude\n(syntax: '
|
||||
'18\u00b09\'48.21"E, -18.2412 or -18:9:48.21)'))
|
||||
|
||||
|
||||
@ -21,8 +21,16 @@
|
||||
""" Unittest for editreference.py """
|
||||
|
||||
import unittest
|
||||
from unittest.mock import Mock, patch
|
||||
import sys
|
||||
import os
|
||||
try:
|
||||
if sys.version_info < (3,3):
|
||||
from mock import Mock, patch
|
||||
else:
|
||||
from unittest.mock import Mock, patch
|
||||
MOCKING = True
|
||||
except:
|
||||
MOCKING = False
|
||||
|
||||
from gramps.gen.lib import (Person, Family, Event, Source, Place, Citation,
|
||||
Repository, Media, Note, Tag)
|
||||
@ -46,6 +54,7 @@ class MockEditReference(EditReference):
|
||||
|
||||
class TestEditReference(unittest.TestCase):
|
||||
|
||||
@unittest.skipUnless(MOCKING, "Requires unittest.mock to run")
|
||||
def test_editreference(self):
|
||||
dbstate = DbState()
|
||||
db = make_database("sqlite")
|
||||
|
||||
@ -163,43 +163,16 @@ class FamilySidebarFilter(SidebarFilter):
|
||||
generic_filter.add_rule(rule)
|
||||
|
||||
if father:
|
||||
# if the name is not empty, split the name in multiple part if
|
||||
# we don't use regexp. if the regexp is used, don't split the
|
||||
# field
|
||||
if not regex:
|
||||
name_parts = father.split(sep=" ")
|
||||
for name_part in name_parts:
|
||||
rule = RegExpFatherName([name_part], use_regex=regex)
|
||||
generic_filter.add_rule(rule)
|
||||
else:
|
||||
rule = RegExpFatherName([father], use_regex=regex)
|
||||
generic_filter.add_rule(rule)
|
||||
rule = RegExpFatherName([father], use_regex=regex)
|
||||
generic_filter.add_rule(rule)
|
||||
|
||||
if mother:
|
||||
# if the name is not empty, split the name in multiple part if
|
||||
# we don't use regexp. if the regexp is used, don't split the
|
||||
# field
|
||||
if not regex:
|
||||
name_parts = mother.split(sep=" ")
|
||||
for name_part in name_parts:
|
||||
rule = RegExpMotherName([name_part], use_regex=regex)
|
||||
generic_filter.add_rule(rule)
|
||||
else:
|
||||
rule = RegExpMotherName([mother], use_regex=regex)
|
||||
generic_filter.add_rule(rule)
|
||||
rule = RegExpMotherName([mother], use_regex=regex)
|
||||
generic_filter.add_rule(rule)
|
||||
|
||||
if child:
|
||||
# if the name is not empty, split the name in multiple part if
|
||||
# we don't use regexp. if the regexp is used, don't split the
|
||||
# field
|
||||
if not regex:
|
||||
name_parts = child.split(sep=" ")
|
||||
for name_part in name_parts:
|
||||
rule = RegExpChildName([name_part], use_regex=regex)
|
||||
generic_filter.add_rule(rule)
|
||||
else:
|
||||
rule = RegExpChildName([child], use_regex=regex)
|
||||
generic_filter.add_rule(rule)
|
||||
rule = RegExpChildName([child], use_regex=regex)
|
||||
generic_filter.add_rule(rule)
|
||||
|
||||
if etype:
|
||||
rule = HasEvent([etype, '', '', '', ''], use_regex=regex)
|
||||
|
||||
@ -178,7 +178,7 @@
|
||||
<object class="ValidatableMaskedEntry" id="date_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="tooltip_text" translatable="yes">The date of the entry in the source you are referencing, e.g. the date a house was visited during a census, or the date an entry was made in a birth log/registry.</property>
|
||||
<property name="tooltip_text" translatable="yes">The date of the entry in the source you are referencing, e.g. the date a house was visited during a census, or the date an entry was made in a birth log/registry. </property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="invisible_char">•</property>
|
||||
<property name="primary_icon_activatable">False</property>
|
||||
|
||||
@ -203,7 +203,7 @@
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="tooltip_text" translatable="yes">Path of the media object on your computer.
|
||||
Gramps does not store the media internally, it only stores the path! Set the 'Relative Path' in the Preferences to avoid retyping the common base directory where all your media is stored. The 'Media Manager' tool can help managing paths of a collection of media objects.</property>
|
||||
Gramps does not store the media internally, it only stores the path! Set the 'Relative Path' in the Preferences to avoid retyping the common base directory where all your media is stored. The 'Media Manager' tool can help managing paths of a collection of media objects. </property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="invisible_char">●</property>
|
||||
</object>
|
||||
|
||||
@ -330,7 +330,7 @@
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Given Name(s)</property>
|
||||
<property name="label" translatable="yes">Given Name(s) </property>
|
||||
<attributes>
|
||||
<attribute name="style" value="italic"/>
|
||||
</attributes>
|
||||
|
||||
@ -235,7 +235,7 @@ You can set these values via the Geography View by searching the place, or via a
|
||||
<object class="ValidatableMaskedEntry" id="latlon_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="tooltip_text" translatable="yes">Field used to paste info from a web page like Google, OpenStreetMap...</property>
|
||||
<property name="tooltip_text" translatable="yes">Field used to paste info from a web page like google, openstreetmap, ... </property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="invisible_char">●</property>
|
||||
</object>
|
||||
|
||||
@ -373,7 +373,7 @@
|
||||
<object class="ValidatableMaskedEntry" id="latlon_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="tooltip_text" translatable="yes">Field used to paste info from a web page like Google, OpenStreetMap...</property>
|
||||
<property name="tooltip_text" translatable="yes">Field used to paste info from a web page like google, openstreetmap, ... </property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="invisible_char">●</property>
|
||||
</object>
|
||||
|
||||
@ -58,7 +58,7 @@ WIKI_HELP_PAGE = URL_MANUAL_SECT3
|
||||
WIKI_HELP_SEC = _("Merge_People", "manual")
|
||||
_GLADE_FILE = "mergeperson.glade"
|
||||
|
||||
# Translators: needed for French, ignore otherwise
|
||||
# translators: needed for French, ignore otherwise
|
||||
KEYVAL = _("%(key)s:\t%(value)s")
|
||||
|
||||
sex = ( _("female"), _("male"), _("unknown") )
|
||||
@ -214,7 +214,7 @@ class MergePerson(ManagedWindow):
|
||||
self.add(tobj, normal,
|
||||
KEYVAL % {'key': name, 'value': ev_info})
|
||||
else:
|
||||
self.add(tobj, normal, # Translators: needed for French
|
||||
self.add(tobj, normal, # translators: needed for French
|
||||
"%(name)s (%(role)s):\t%(info)s"
|
||||
% {'name': name, 'role': role,
|
||||
'info': ev_info})
|
||||
|
||||
@ -49,7 +49,7 @@ UICATEGORY = ''' <section id="ViewsInCatagory">
|
||||
%s
|
||||
</section>
|
||||
'''
|
||||
UICATEGORYBAR = ''' <placeholder id='ViewsInCategoryBar'>
|
||||
UICATAGORYBAR = ''' <placeholder id='ViewsInCategoryBar'>
|
||||
%s
|
||||
</placeholder>
|
||||
'''
|
||||
@ -195,7 +195,7 @@ class Navigator:
|
||||
if len(cat_views) > 1:
|
||||
#allow for switching views in a category
|
||||
self.ui_category[cat_num] = [UICATEGORY % uimenuitems,
|
||||
UICATEGORYBAR % uibaritems]
|
||||
UICATAGORYBAR % uibaritems]
|
||||
|
||||
for pdata in plugman.get_reg_sidebars():
|
||||
module = plugman.load_plugin(pdata)
|
||||
|
||||
@ -1117,7 +1117,7 @@ class UpdateAddons(ManagedWindow):
|
||||
last_category = None
|
||||
for (status,plugin_url,plugin_dict) in addon_update_list:
|
||||
count = get_count(addon_update_list, plugin_dict["t"])
|
||||
# Translators: needed for French, ignore otherwise
|
||||
# translators: needed for French, ignore otherwise
|
||||
category = _("%(str1)s: %(str2)s") % {'str1' : status,
|
||||
'str2' : _(plugin_dict["t"])}
|
||||
if last_category != category:
|
||||
@ -1220,7 +1220,7 @@ class UpdateAddons(ManagedWindow):
|
||||
if count:
|
||||
self.rescan = True
|
||||
OkDialog(_("Done downloading and installing addons"),
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
"%s %s" % (ngettext("{number_of} addon was installed.",
|
||||
"{number_of} addons were installed.",
|
||||
count).format(number_of=count),
|
||||
|
||||
@ -163,7 +163,7 @@ class WriterOptionBox:
|
||||
label = Gtk.Label(label=_("Unfiltered Family Tree:"))
|
||||
full_database_row.pack_start(label, True, True, 0)
|
||||
people_count = len(self.dbstate.db.get_person_handles())
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
button = Gtk.Button(label=ngettext("{number_of} Person",
|
||||
"{number_of} People", people_count
|
||||
).format(number_of=people_count))
|
||||
@ -270,7 +270,7 @@ class WriterOptionBox:
|
||||
# Make a box and put the option in it:
|
||||
from gi.repository import Gtk
|
||||
from ...widgets import SimpleButton
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
button = Gtk.Button(label=ngettext("{number_of} Person",
|
||||
"{number_of} People", 0
|
||||
).format(number_of=0))
|
||||
@ -578,7 +578,7 @@ class WriterOptionBox:
|
||||
self.preview_proxy_button[proxy_name].set_sensitive(1)
|
||||
people_count = len(dbase.get_person_handles())
|
||||
self.preview_proxy_button[proxy_name].set_label(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext("{number_of} Person",
|
||||
"{number_of} People", people_count
|
||||
).format(number_of=people_count) )
|
||||
|
||||
@ -373,7 +373,7 @@ class ReportDialog(ManagedWindow):
|
||||
for (text, widget) in self.widgets:
|
||||
widget.set_hexpand(True)
|
||||
if text:
|
||||
# Translators: needed for French, ignore otherwise
|
||||
# translators: needed for French, ignore otherwise
|
||||
text_widget = Gtk.Label(label=_("%s:") % text)
|
||||
text_widget.set_halign(Gtk.Align.START)
|
||||
grid.attach(text_widget, 1, row, 1, 1)
|
||||
|
||||
@ -22,8 +22,20 @@
|
||||
""" Unittest for user.py """
|
||||
|
||||
import unittest
|
||||
from unittest.mock import Mock, patch
|
||||
from .. import user
|
||||
import sys
|
||||
|
||||
try:
|
||||
if sys.version_info < (3,3):
|
||||
from mock import Mock, patch
|
||||
else:
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
MOCKING = True
|
||||
|
||||
except:
|
||||
MOCKING = False
|
||||
print ("Mocking disabled", sys.exc_info()[0:2])
|
||||
|
||||
class TestUser:
|
||||
TITLE = "Testing prompt"
|
||||
@ -35,6 +47,7 @@ class TestUser_prompt(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.user = user.User()
|
||||
|
||||
@unittest.skipUnless(MOCKING, "Requires unittest.mock to run")
|
||||
def test_prompt_runs_QuestionDialog2(self):
|
||||
with patch('gramps.gui.user.QuestionDialog2') as MockQD:
|
||||
self.user.prompt(TestUser.TITLE, TestUser.MSG,
|
||||
|
||||
@ -173,10 +173,10 @@ class UIManager():
|
||||
if((len(child) == 1 and child.tag == "submenu") or
|
||||
(len(child) == 0 and child.tag == "section")):
|
||||
# remove empty submenus and sections
|
||||
LOG.debug(('del', child.tag, child.attrib))
|
||||
# print('del', child.tag, child.attrib)
|
||||
del parents[indx]
|
||||
continue
|
||||
LOG.debug((child.attrib))
|
||||
# print(child.attrib)
|
||||
groups = child.get('groups')
|
||||
if not groups:
|
||||
indx += 1
|
||||
@ -187,8 +187,8 @@ class UIManager():
|
||||
indx += 1
|
||||
break
|
||||
else:
|
||||
LOG.debug(('del', child.tag, child.attrib, parents.tag,
|
||||
parents.attrib))
|
||||
#print('del', child.tag, child.attrib, parents.tag,
|
||||
# parents.attrib)
|
||||
del parents[indx]
|
||||
break
|
||||
# The following looks for 'placeholder' elements and if found,
|
||||
@ -198,8 +198,8 @@ class UIManager():
|
||||
while indx < len(parents):
|
||||
if parents[indx].tag == "placeholder":
|
||||
subtree = parents[indx]
|
||||
LOG.debug(('placholder del', parents[indx].tag,
|
||||
parents[indx].attrib, parents.tag, parents.attrib))
|
||||
#print('placholder del', parents[indx].tag,
|
||||
# parents[indx].attrib, parents.tag, parents.attrib)
|
||||
del parents[indx]
|
||||
for child in subtree:
|
||||
parents.insert(indx, child)
|
||||
@ -223,7 +223,7 @@ class UIManager():
|
||||
# file.write(xml_str)
|
||||
# with open('try.xml', encoding='utf8') as file:
|
||||
# xml_str = file.read()
|
||||
#LOG.info(xml_str)
|
||||
# print(xml_str)
|
||||
self.builder = Gtk.Builder()
|
||||
self.builder.set_translation_domain(glocale.get_localedomain())
|
||||
self.builder.add_from_string(xml_str)
|
||||
@ -251,7 +251,7 @@ class UIManager():
|
||||
toolbar.show_all()
|
||||
else:
|
||||
toolbar.hide()
|
||||
LOG.info('*** Update ui')
|
||||
#print('*** Update ui')
|
||||
|
||||
def add_ui_from_string(self, changexml):
|
||||
""" This performs a merge operation on the xml elements that have
|
||||
@ -284,14 +284,14 @@ class UIManager():
|
||||
# This allow addition of popups etc.
|
||||
self.et_xml.append(update)
|
||||
#results = ET.tostring(self.et_xml, encoding="unicode")
|
||||
#LOG.info(results)
|
||||
LOG.info('*** Add ui')
|
||||
#print(results)
|
||||
#print ('*** Add ui')
|
||||
return changexml
|
||||
except:
|
||||
# the following is only here to assist debug
|
||||
LOG.debug('*****', sys.exc_info())
|
||||
LOG.debug(xml)
|
||||
LOG.debug(changexml)
|
||||
print('*****', sys.exc_info())
|
||||
print(xml)
|
||||
print(changexml)
|
||||
assert False
|
||||
|
||||
def remove_ui(self, change_xml):
|
||||
@ -317,8 +317,8 @@ class UIManager():
|
||||
for dummy in range(len(element)):
|
||||
del element[0]
|
||||
#results = ET.tostring(self.et_xml, encoding="unicode")
|
||||
#LOG.info(results)
|
||||
LOG.info('*** Remove ui')
|
||||
#print(results)
|
||||
#print ('*** Remove ui')
|
||||
return
|
||||
|
||||
def get_widget(self, obj):
|
||||
@ -411,7 +411,7 @@ class UIManager():
|
||||
self.set_actions_sensitive(group, False)
|
||||
except:
|
||||
# the following is only to assist in debug
|
||||
LOG.debug(group.name, item)
|
||||
print(group.name, item)
|
||||
assert False
|
||||
|
||||
def remove_action_group(self, group):
|
||||
|
||||
@ -422,14 +422,11 @@ class PeopleBaseModel(BaseModel):
|
||||
def _get_parents_data(self, data):
|
||||
parents = 0
|
||||
if data[COLUMN_PARENT]:
|
||||
person = self.db.get_person_from_gramps_id(data[COLUMN_ID])
|
||||
family_list = person.get_parent_family_handle_list()
|
||||
for fam_hdle in family_list:
|
||||
family = self.db.get_family_from_handle(fam_hdle)
|
||||
if family.get_father_handle():
|
||||
parents += 1
|
||||
if family.get_mother_handle():
|
||||
parents += 1
|
||||
family = self.db.get_family_from_handle(data[COLUMN_PARENT][0])
|
||||
if family.get_father_handle():
|
||||
parents += 1
|
||||
if family.get_mother_handle():
|
||||
parents += 1
|
||||
return parents
|
||||
|
||||
def _get_marriages_data(self, data):
|
||||
|
||||
@ -963,7 +963,7 @@ class AncestorTreeOptions(MenuReportOptions):
|
||||
repldisp = TextOption(
|
||||
_("Replace Display Format:\n'Replace this'/' with this'"),
|
||||
[])
|
||||
repldisp.set_help(_("i.e.\nUnited States of America/U.S.A."))
|
||||
repldisp.set_help(_("i.e.\nUnited States of America/U.S.A"))
|
||||
menu.add_option(category_name, "replace_list", repldisp)
|
||||
|
||||
# TODO this code is never used and so I conclude it is for future use
|
||||
|
||||
@ -361,7 +361,7 @@ class Calendar(Report):
|
||||
text = self._('%(person)s, birth') % {
|
||||
'person' : short_name }
|
||||
else:
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
text = ngettext('{person}, {age}',
|
||||
'{person}, {age}',
|
||||
nyears).format(person=short_name,
|
||||
@ -423,7 +423,7 @@ class Calendar(Report):
|
||||
'person' : short_name,
|
||||
}
|
||||
else:
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
text = ngettext("{spouse} and\n {person}, {nyears}",
|
||||
"{spouse} and\n {person}, {nyears}",
|
||||
nyears).format(spouse=spouse_name, person=short_name, nyears=nyears)
|
||||
|
||||
@ -354,7 +354,7 @@ class TitleC(DescendantTitleBase):
|
||||
for kid in family.get_child_ref_list()]
|
||||
|
||||
#ok we have the children. Make a title off of them
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore otherwise
|
||||
cousin_names = self._(', ').join(self._get_names(kids, self._nd))
|
||||
|
||||
self.text = self._(
|
||||
@ -1696,7 +1696,7 @@ class DescendTreeOptions(MenuReportOptions):
|
||||
repldisp = TextOption(
|
||||
_("Replace Display Format:\n'Replace this'/' with this'"),
|
||||
[])
|
||||
repldisp.set_help(_("i.e.\nUnited States of America/U.S.A."))
|
||||
repldisp.set_help(_("i.e.\nUnited States of America/U.S.A"))
|
||||
menu.add_option(category_name, "replace_list", repldisp)
|
||||
|
||||
self.usenote = BooleanOption(_('Include a note'), False)
|
||||
|
||||
@ -35,7 +35,6 @@ from gramps.gen.utils.db import navigation_label
|
||||
from gramps.gen.plug import Gramplet
|
||||
from gramps.gui.utils import edit_object
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
from gramps.gen.datehandler import displayer
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
class Backlinks(Gramplet):
|
||||
@ -43,8 +42,6 @@ class Backlinks(Gramplet):
|
||||
Displays the back references for an object.
|
||||
"""
|
||||
def init(self):
|
||||
self.date_column = None
|
||||
self.evts = False
|
||||
self.gui.WIDGET = self.build_gui()
|
||||
self.gui.get_container_widget().remove(self.gui.textview)
|
||||
self.gui.get_container_widget().add(self.gui.WIDGET)
|
||||
@ -54,50 +51,22 @@ class Backlinks(Gramplet):
|
||||
"""
|
||||
Build the GUI interface.
|
||||
"""
|
||||
self.top = Gtk.TreeView()
|
||||
top = Gtk.TreeView()
|
||||
titles = [(_('Type'), 1, 100),
|
||||
(_('Name'), 2, 100),
|
||||
(_('Date'), 4, 200),
|
||||
('sd', 4, 120), # sorted date column
|
||||
('', 5, 1), #hidden column for the handle
|
||||
('', 6, 1), #hidden column for non-localized object type
|
||||
]
|
||||
self.model = ListModel(self.top, titles,
|
||||
event_func=self.cb_double_click)
|
||||
self.date_column = self.top.get_column(2)
|
||||
self.sdate = self.top.get_column(3)
|
||||
self.top.get_column(1).set_expand(True) # The name use the max
|
||||
# possible size
|
||||
return self.top
|
||||
('', 3, 1), #hidden column for the handle
|
||||
('', 4, 1)] #hidden column for non-localized object type
|
||||
self.model = ListModel(top, titles, event_func=self.cb_double_click)
|
||||
return top
|
||||
|
||||
def display_backlinks(self, active_handle):
|
||||
"""
|
||||
Display the back references for an object.
|
||||
"""
|
||||
self.evts = False
|
||||
for classname, handle in \
|
||||
self.dbstate.db.find_backlink_handles(active_handle):
|
||||
name = navigation_label(self.dbstate.db, classname, handle)[0]
|
||||
sdcolumn = self.top.get_column(3)
|
||||
dcolumn = self.top.get_column(2)
|
||||
if classname == "Event":
|
||||
obj = self.dbstate.db.get_event_from_handle(handle)
|
||||
o_date = obj.get_date_object()
|
||||
date = displayer.display(o_date)
|
||||
sdate = "%09d" % o_date.get_sort_value()
|
||||
sdcolumn.set_sort_column_id(3)
|
||||
dcolumn.set_sort_column_id(3)
|
||||
self.evts = True
|
||||
else:
|
||||
sdcolumn.set_sort_column_id(1)
|
||||
date = sdate = ""
|
||||
self.model.add((_(classname), name, date, sdate, handle, classname))
|
||||
if self.evts:
|
||||
self.date_column.set_visible(True)
|
||||
sdcolumn.set_visible(False)
|
||||
else:
|
||||
self.date_column.set_visible(False)
|
||||
sdcolumn.set_visible(False)
|
||||
self.model.add((_(classname), name, handle, classname))
|
||||
self.set_has_data(self.model.count > 0)
|
||||
|
||||
def get_has_data(self, active_handle):
|
||||
@ -118,8 +87,8 @@ class Backlinks(Gramplet):
|
||||
if not iter_:
|
||||
return
|
||||
|
||||
(objclass, handle) = (model.get_value(iter_, 5),
|
||||
model.get_value(iter_, 4))
|
||||
(objclass, handle) = (model.get_value(iter_, 3),
|
||||
model.get_value(iter_, 2))
|
||||
|
||||
edit_object(self.dbstate, self.uistate, objclass, handle)
|
||||
|
||||
@ -304,3 +273,4 @@ class NoteBacklinks(Backlinks):
|
||||
self.display_backlinks(active_handle)
|
||||
else:
|
||||
self.set_has_data(False)
|
||||
|
||||
|
||||
@ -33,23 +33,20 @@ from gi.repository import Gtk
|
||||
from gramps.gui.editors import EditSource, EditCitation
|
||||
from gramps.gui.listmodel import ListModel, NOSORT
|
||||
from gramps.gen.plug import Gramplet
|
||||
from gramps.gen.utils.string import conf_strings
|
||||
from gramps.gen.datehandler._dateutils import get_date
|
||||
from gramps.gui.dbguielement import DbGUIElement
|
||||
from gramps.gen.errors import WindowActiveError
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
class Citations(Gramplet, DbGUIElement):
|
||||
"""
|
||||
Displays the citations for an object.
|
||||
"""
|
||||
|
||||
def __init__(self, gui, nav_group=0):
|
||||
Gramplet.__init__(self, gui, nav_group)
|
||||
DbGUIElement.__init__(self, self.dbstate.db)
|
||||
self.source_nodes = {}
|
||||
|
||||
"""
|
||||
Displays the citations for an object.
|
||||
"""
|
||||
def init(self):
|
||||
self.gui.WIDGET = self.build_gui()
|
||||
self.gui.get_container_widget().remove(self.gui.textview)
|
||||
@ -83,11 +80,9 @@ class Citations(Gramplet, DbGUIElement):
|
||||
self.set_tooltip(tip)
|
||||
top = Gtk.TreeView()
|
||||
titles = [('', NOSORT, 50,),
|
||||
(_('Source/Date'), 1, 350),
|
||||
(_('Volume/Page'), 2, 150),
|
||||
(_('Confidence Level'), 3, 150),
|
||||
(_('Author'), 4, 200),
|
||||
(_('Publisher'), 5, 150)]
|
||||
(_('Source/Citation'), 1, 350),
|
||||
(_('Author'), 2, 200),
|
||||
(_('Publisher'), 3, 150)]
|
||||
self.model = ListModel(top, titles, list_mode="tree",
|
||||
event_func=self.invoke_editor)
|
||||
return top
|
||||
@ -164,21 +159,18 @@ class Citations(Gramplet, DbGUIElement):
|
||||
citation = self.dbstate.db.get_citation_from_handle(citation_handle)
|
||||
page = citation.get_page()
|
||||
if not page:
|
||||
page = _('<No Volume/Page>')
|
||||
page = _('<No Citation>')
|
||||
source_handle = citation.get_reference_handle()
|
||||
source = self.dbstate.db.get_source_from_handle(source_handle)
|
||||
title = source.get_title()
|
||||
author = source.get_author()
|
||||
publisher = source.get_publication_info()
|
||||
confidence = citation.get_confidence_level()
|
||||
|
||||
if source_handle not in self.source_nodes:
|
||||
node = self.model.add([source_handle, title, '', '',
|
||||
author, publisher])
|
||||
node = self.model.add([source_handle, title, author, publisher])
|
||||
self.source_nodes[source_handle] = node
|
||||
|
||||
self.model.add([citation_handle, get_date(citation), page,
|
||||
_(conf_strings[confidence]), '', ''],
|
||||
self.model.add([citation_handle, page, '', ''],
|
||||
node=self.source_nodes[source_handle])
|
||||
|
||||
def check_citations(self, obj):
|
||||
|
||||
@ -268,7 +268,7 @@ class PedigreeGramplet(Gramplet):
|
||||
tooltip=_("Double-click to see people in generation %d") % g)
|
||||
percent = glocale.format('%.2f', float(count)/2**(g-1) * 100) + percent_sign
|
||||
self.append_text(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext(" has {count_person} of {max_count_person} "
|
||||
"individuals ({percent} complete)\n",
|
||||
" has {count_person} of {max_count_person} "
|
||||
@ -279,7 +279,7 @@ class PedigreeGramplet(Gramplet):
|
||||
self.link(_("All generations"), 'PersonList', all,
|
||||
tooltip=_("Double-click to see all generations"))
|
||||
self.append_text(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext(" have {number_of} individual\n",
|
||||
" have {number_of} individuals\n", len(all)
|
||||
).format(number_of=len(all)))
|
||||
|
||||
@ -234,7 +234,7 @@ class PersonDetails(Gramplet):
|
||||
if attr.get_type() == attr_key:
|
||||
values.append(attr.get_value())
|
||||
if values:
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore otherwise
|
||||
self.add_row(attr_key, _(', ').join(values))
|
||||
|
||||
def display_type(self, active_person, event_type):
|
||||
|
||||
@ -86,7 +86,7 @@ class LogGramplet(Gramplet):
|
||||
continue
|
||||
self.last_log = (ltype, action, handle)
|
||||
self.timestamp()
|
||||
# Translators: needed for French, ignore otherwise
|
||||
# translators: needed for French, ignore otherwise
|
||||
self.append_text(_("%s: ") % _(action))
|
||||
if action == 'Deleted':
|
||||
transaction = self.dbstate.db.transaction
|
||||
|
||||
@ -490,7 +490,7 @@ class WhatNextGramplet(Gramplet):
|
||||
missingbits.append(_("place unknown"))
|
||||
|
||||
if missingbits:
|
||||
# Translators: needed for French, ignore otherwise
|
||||
# translators: needed for French, ignore otherwise
|
||||
return [_("%(str1)s: %(str2)s"
|
||||
) % {'str1' : event.get_type(),
|
||||
'str2' : _(", ").join(missingbits)}] # Arabic OK
|
||||
|
||||
@ -487,7 +487,7 @@ class FamilyLinesReport(Report):
|
||||
person = self._db.get_person_from_handle(handle)
|
||||
gid = person.get_gramps_id()
|
||||
name = person.get_primary_name().get_regular_name()
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore othewise
|
||||
id_n = self._("%(str1)s, %(str2)s") % {'str1':gid, 'str2':name}
|
||||
self.doc.add_comment('# -> ' + id_n)
|
||||
|
||||
@ -978,7 +978,7 @@ class FamilyLinesReport(Report):
|
||||
if self._incchildcount:
|
||||
child_count = len(family.get_child_ref_list())
|
||||
if child_count >= 1:
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
children_str = ngettext("{number_of} child",
|
||||
"{number_of} children", child_count
|
||||
).format(number_of=child_count)
|
||||
|
||||
@ -370,7 +370,7 @@ class CSVParser:
|
||||
self.db.enable_signals()
|
||||
self.db.request_rebuild()
|
||||
tym = time.time() - tym
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
msg = ngettext('Import Complete: {number_of} second',
|
||||
'Import Complete: {number_of} seconds', tym
|
||||
).format(number_of=tym)
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
<col id="0" translatable="yes">ANSEL</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes">ANSI (ISO-8859-1)</col>
|
||||
<col id="0" translatable="yes">ANSI (iso-8859-1)</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes">ASCII</col>
|
||||
|
||||
@ -270,7 +270,7 @@ class GeneWebParser:
|
||||
self.errmsg(str(err))
|
||||
|
||||
t = time.time() - t
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
msg = ngettext('Import Complete: {number_of} second',
|
||||
'Import Complete: {number_of} seconds', t
|
||||
).format(number_of=t)
|
||||
@ -906,7 +906,7 @@ class GeneWebParser:
|
||||
date.set(Date.QUAL_NONE,mod, cal1,
|
||||
(sub1[0],sub1[1],sub1[2],0,sub2[0],sub2[1],sub2[2],0))
|
||||
except DateError as e:
|
||||
# Translators: leave the {date} and {gw_snippet} untranslated
|
||||
# TRANSLATORS: leave the {date} and {gw_snippet} untranslated
|
||||
# in the format string, but you may re-order them if needed.
|
||||
LOG.warning(_(
|
||||
"Invalid date {date} in {gw_snippet}, "
|
||||
|
||||
@ -245,7 +245,7 @@ class VCardParser:
|
||||
self.database.enable_signals()
|
||||
self.database.request_rebuild()
|
||||
tym = time.time() - tym
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
msg = ngettext('Import Complete: {number_of} second',
|
||||
'Import Complete: {number_of} seconds', tym
|
||||
).format(number_of=tym)
|
||||
@ -511,7 +511,7 @@ class VCardParser:
|
||||
try:
|
||||
date.set(value=(d, m, y, False))
|
||||
except DateError:
|
||||
# Translators: leave the {vcard_snippet} untranslated
|
||||
# TRANSLATORS: leave the {vcard_snippet} untranslated
|
||||
# in the format string, but you may re-order it if needed.
|
||||
self.__add_msg(_(
|
||||
"Invalid date in BDAY {vcard_snippet}, "
|
||||
@ -520,7 +520,7 @@ class VCardParser:
|
||||
date.set(modifier=Date.MOD_TEXTONLY, text=data)
|
||||
else:
|
||||
if date_str:
|
||||
# Translators: leave the {vcard_snippet} untranslated.
|
||||
# TRANSLATORS: leave the {vcard_snippet} untranslated.
|
||||
self.__add_msg(_(
|
||||
"Date {vcard_snippet} not in appropriate format "
|
||||
"yyyy-mm-dd, preserving date as text."
|
||||
|
||||
@ -299,12 +299,12 @@ class ImportInfo:
|
||||
else:
|
||||
txt += key2string[key] % self.data_newobject[self.key2data[key]]
|
||||
if any(self.data_unknownobject):
|
||||
txt += _("\nThe imported file was not self-contained.\n"
|
||||
txt += _("\n The imported file was not self-contained.\n"
|
||||
"To correct for that, %(new)d objects were created and\n"
|
||||
"their typifying attribute was set to 'Unknown'.\n"
|
||||
"The breakdown per category is depicted by the\n"
|
||||
"number in parentheses. Where possible these\n"
|
||||
"'Unknown' objects are referenced by note %(unknown)s.\n"
|
||||
"'Unkown' objects are referenced by note %(unknown)s.\n"
|
||||
) % {'new': sum(self.data_unknownobject), 'unknown': self.expl_note}
|
||||
if self.data_relpath:
|
||||
txt += _("\nMedia objects with relative paths have been\n"
|
||||
@ -318,7 +318,7 @@ class ImportInfo:
|
||||
merge = True
|
||||
break
|
||||
if merge:
|
||||
txt += _("\nObjects that are candidates to be merged:\n")
|
||||
txt += _("\n\nObjects that are candidates to be merged:\n")
|
||||
for key in self.keyorder:
|
||||
datakey = self.key2data[key]
|
||||
for handle in list(self.data_mergecandidate[datakey].keys()):
|
||||
@ -2523,7 +2523,7 @@ class GrampsParser(UpdateCallback):
|
||||
attrs = " ".join(
|
||||
['{}="{}"'.format(k,escape(v, entities={'"' : """}))
|
||||
for k,v in xml_attrs.items()]))
|
||||
# Translators: leave the {date} and {xml} untranslated in the format string,
|
||||
# TRANSLATORS: leave the {date} and {xml} untranslated in the format string,
|
||||
# but you may re-order them if needed.
|
||||
LOG.warning(_("Invalid date {date} in XML {xml}, preserving XML as text"
|
||||
).format(date=date_error.date.__dict__, xml=xml))
|
||||
|
||||
@ -30,6 +30,7 @@ This module exports the Html class
|
||||
#------------------------------------------------------------------------
|
||||
# Python modules
|
||||
#------------------------------------------------------------------------
|
||||
import re
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
@ -113,10 +114,10 @@ class Html(list):
|
||||
"""
|
||||
Build and return an XML declaration statement
|
||||
|
||||
:type version: decimal number
|
||||
:param version: version of XML to be used. Defaults to 1.0
|
||||
:type encoding: string
|
||||
:param encoding: encoding method to be used. Defaults to "UTF-8"
|
||||
:type version: decimal number
|
||||
:param version: version of XML to be used. Defaults to 1.0
|
||||
:type encoding: string
|
||||
:param encoding: encoding method to be used. Defaults to "UTF-8"
|
||||
:type standalone: string
|
||||
:param standalone: "yes" or "no". Defaults to "no"
|
||||
"""
|
||||
@ -131,16 +132,16 @@ class Html(list):
|
||||
"""
|
||||
Build and return a DOCTYPE statement
|
||||
|
||||
:type name: string
|
||||
:param name: name of this DOCTYPE. Defaults to "html"
|
||||
:type public: string
|
||||
:param public: class of this DOCTYPE. Defaults to 'PUBLIC
|
||||
:type name: string
|
||||
:param name: name of this DOCTYPE. Defaults to "html"
|
||||
:type public: string
|
||||
:param public: class of this DOCTYPE. Defaults to 'PUBLIC
|
||||
:type external_id: string
|
||||
:param external_id: external identifier of this DOCTYPE.
|
||||
Defaults to XHTML 1.0 STRICT
|
||||
:type args: object
|
||||
:param args: 0 or more positional parameters to be added to
|
||||
this DOCTYPE.
|
||||
:type args: object
|
||||
:param args: 0 or more positional parameters to be added to this
|
||||
DOCTYPE.
|
||||
"""
|
||||
return (
|
||||
'<!DOCTYPE %s %s %s' % (
|
||||
@ -151,40 +152,38 @@ class Html(list):
|
||||
).rstrip() + '>'
|
||||
#
|
||||
@staticmethod
|
||||
def html(xmlns=_XMLNS, lang='en', php_session=None, *args, **keywargs):
|
||||
def html(xmlns=_XMLNS, lang='en', *args, **keywargs):
|
||||
"""
|
||||
Build and return a properly-formated <html> object
|
||||
|
||||
:type xmlns: string
|
||||
:param xmlns: XML namespace string.
|
||||
Default = 'http://www.w3.org/1999/xhtml'
|
||||
:type lang: string
|
||||
:param lang: language to be used. Defaul = 'en'
|
||||
:rtype: reference to new Html instance
|
||||
:php_session: If we need to have a php session start
|
||||
:returns: reference to the newly-created Html instances
|
||||
for <html> object
|
||||
:param xmlns: XML namespace string. Default = 'http://www.w3.org/1999/xhtml'
|
||||
:type lang: string
|
||||
:param lang: language to be used. Defaul = 'en'
|
||||
:rtype: reference to new Html instance
|
||||
:returns: reference to the newly-created Html instances for <html> object
|
||||
"""
|
||||
return Html('html', indent=False, xmlns=xmlns,
|
||||
attr='xml:lang="%s" lang="%s"' % ((lang,)*2),
|
||||
php=php_session,
|
||||
*args, **keywargs)
|
||||
return Html('html',
|
||||
indent=False,
|
||||
xmlns=xmlns,
|
||||
attr='xml:lang="%s" lang="%s"' % ((lang,)*2),
|
||||
*args, **keywargs
|
||||
)
|
||||
#
|
||||
@staticmethod
|
||||
def head(title=None, encoding='utf-8', html5=True, *args, **keywargs):
|
||||
"""
|
||||
Build and return a properly-formated <head> object
|
||||
|
||||
:type title: string or None
|
||||
:param title: title for HTML page. Default=None. If None no
|
||||
title tag is written
|
||||
:type title: string or None
|
||||
:param title: title for HTML page. Default=None. If None no
|
||||
title tag is written
|
||||
:type encoding: string
|
||||
:param encoding: encoding to be used. Default = 'utf-8'
|
||||
:param html5: generate html5 syntax. Default = True. Set to False
|
||||
if pre-html5 syntax required
|
||||
:rtype: reference to new Html instance
|
||||
:returns: reference to the newly-created Html instances
|
||||
for <head> object
|
||||
:param html5: generate html5 syntax. Default = True. Set to False
|
||||
if pre-html5 syntax required
|
||||
:rtype: reference to new Html instance
|
||||
:returns: reference to the newly-created Html instances for <head> object
|
||||
"""
|
||||
|
||||
head = Html('head', *args, **keywargs)
|
||||
@ -200,38 +199,39 @@ class Html(list):
|
||||
return head
|
||||
#
|
||||
@staticmethod
|
||||
def page(title=None, encoding='utf-8', lang='en', html5=True, cms=False,
|
||||
php_session=None, *args, **keywargs):
|
||||
def page(title=None, encoding='utf-8', lang='en', html5=True, cms=False, *args, **keywargs):
|
||||
"""
|
||||
This function prepares a new Html class based page and returns
|
||||
|
||||
:type title: string
|
||||
:param title: title for HTML page. Default=None
|
||||
:type title: string
|
||||
:param title: title for HTML page. Default=None
|
||||
:type encoding: string
|
||||
:param encoding: encoding to be used. Default = 'utf-8'
|
||||
:type lang: string
|
||||
:param lang: language to be used. Defaul = 'en'
|
||||
:param html5: generate html5 syntax. Default = True. Set to False
|
||||
if pre-html5 syntax required
|
||||
:rtype: three object references
|
||||
:php_session: the note to include before all html code
|
||||
:returns: references to the newly-created Html instances for
|
||||
page, head and body
|
||||
:type lang: string
|
||||
:param lang: language to be used. Defaul = 'en'
|
||||
:param html5: generate html5 syntax. Default = True. Set to False
|
||||
if pre-html5 syntax required
|
||||
:rtype: three object references
|
||||
:returns: references to the newly-created Html instances for
|
||||
page, head and body
|
||||
"""
|
||||
page = Html.html(lang=lang, php_session=php_session,
|
||||
*args, **keywargs)
|
||||
page = Html.html(lang=lang, *args, **keywargs)
|
||||
if html5:
|
||||
page.addDOCTYPE(external_id=_HTML5)
|
||||
else:
|
||||
page.addXML(encoding=encoding)
|
||||
page.addDOCTYPE(external_id=_XHTML10_STRICT)
|
||||
#
|
||||
head = Html.head(title=title, encoding=encoding, lang=lang,
|
||||
html5=html5, indent=False, *args, **keywargs)
|
||||
head = Html.head(title=title,
|
||||
encoding=encoding,
|
||||
lang=lang,
|
||||
html5=html5,
|
||||
indent=False,
|
||||
*args, **keywargs
|
||||
)
|
||||
#
|
||||
if cms:
|
||||
body = Html('div', class_="body", indent=False,
|
||||
*args, **keywargs)
|
||||
body = Html('div', class_ = "body", indent=False, *args, **keywargs)
|
||||
else:
|
||||
body = Html('body', indent=False, *args, **keywargs)
|
||||
page += (head, body)
|
||||
@ -241,37 +241,34 @@ class Html(list):
|
||||
"""
|
||||
Class Constructor: Returns a new instance of the Html class
|
||||
|
||||
:type tag: string
|
||||
:param tag: The HTML tag. Default is 'html'
|
||||
:type args: optional positional parameters
|
||||
:param args: 0 more positional arguments to be inserted between
|
||||
opening and closing HTML tags.
|
||||
:type indent: boolean or None
|
||||
:param indent: True ==> indent this object with respect to its
|
||||
parent
|
||||
False ==> do not indent this object
|
||||
None ==> no indent for this object
|
||||
(use eg for pre tag)
|
||||
Defaults to True
|
||||
:type inline: boolean
|
||||
:param inline: True ==> instructs the write() method to output
|
||||
this object and any child objects as a
|
||||
single string
|
||||
False ==> output this object and its contents one
|
||||
string at a time
|
||||
Defaults to False
|
||||
:type close: boolean or None
|
||||
:param close: True ==> this tag should be closed normally
|
||||
e.g. <tag>...</tag>
|
||||
False ==> this tag should be automatically closed
|
||||
e.g. <tag />
|
||||
None ==> do not provide any closing for this tag
|
||||
:type tag: string
|
||||
:param tag: The HTML tag. Default is 'html'
|
||||
:type args: optional positional parameters
|
||||
:param args: 0 more positional arguments to be inserted between
|
||||
opening and closing HTML tags.
|
||||
:type indent: boolean or None
|
||||
:param indent: True ==> indent this object with respect to its parent
|
||||
False ==> do not indent this object
|
||||
None ==> no indent for this object (use eg for pre tag)
|
||||
Defaults to True
|
||||
:type inline: boolean
|
||||
:param inline: True ==> instructs the write() method to output this
|
||||
object and any child objects as a single string
|
||||
False ==> output this object and its contents one string
|
||||
at a time
|
||||
Defaults to False
|
||||
:type close: boolean or None
|
||||
:param close: True ==> this tag should be closed normally
|
||||
e.g. <tag>...</tag>
|
||||
False ==> this tag should be automatically closed
|
||||
e.g. <tag />
|
||||
None ==> do not provide any closing for this tag
|
||||
:type keywargs: optional keyword parameters
|
||||
:param keywargs: 0 or more keyword=argument pairs that should be
|
||||
copied into the opening tag as keyword="argument"
|
||||
attributes
|
||||
:rtype: object reference
|
||||
:returns: reference to the newly-created Html instance
|
||||
:rtype: object reference
|
||||
:returns: reference to the newly-created Html instance
|
||||
|
||||
For full usage of the Html class with examples, please see the wiki
|
||||
page at: http://www.gramps-project.org/wiki/index.php?title=Libhtml
|
||||
@ -287,19 +284,16 @@ class Html(list):
|
||||
# Keywords we don't recognize are saved for later
|
||||
# addition to the opening tag as attributes.
|
||||
#
|
||||
phpnote = None
|
||||
for keyw, arg in sorted(keywargs.items()):
|
||||
if (keyw in ['indent', 'close', 'inline'] and
|
||||
arg in [True, False, None]):
|
||||
arg in [True, False, None]):
|
||||
setattr(self, keyw, arg)
|
||||
elif keyw == 'attr': # pass attributes along
|
||||
elif keyw == 'attr': # pass attributes along
|
||||
attr += ' ' + arg
|
||||
elif keyw == 'php': # php init session
|
||||
phpnote = arg
|
||||
elif keyw[-1] == '_': # avoid Python conflicts
|
||||
attr += ' %s="%s"' % (keyw[:-1], arg) # pass keyword arg along
|
||||
elif keyw[-1] == '_': # avoid Python conflicts
|
||||
attr += ' %s="%s"' % (keyw[:-1], arg) # pass keyword arg along
|
||||
else:
|
||||
attr += ' %s="%s"' % (keyw, arg) # pass keyword arg along
|
||||
attr += ' %s="%s"' % (keyw, arg) # pass keyword arg along
|
||||
#
|
||||
if tag[0] == '<': # if caller provided preformatted tag?
|
||||
self[0:] = [tag] # add it in
|
||||
@ -307,13 +301,7 @@ class Html(list):
|
||||
else:
|
||||
if tag in _START_CLOSE: # if tag in special list
|
||||
self.close = False # it needs no closing tag
|
||||
if phpnote:
|
||||
# We need to insert php code before the html tag
|
||||
# This is used to initiate a php session.
|
||||
htmlhead = phpnote + '<%s%s%s>'
|
||||
else:
|
||||
htmlhead = '<%s%s%s>'
|
||||
begin = htmlhead % ( # build opening tag with attributes
|
||||
begin = '<%s%s%s>' % ( # build opening tag with attributes
|
||||
tag,
|
||||
attr,
|
||||
('' if self.close is not False else ' /')
|
||||
@ -322,7 +310,7 @@ class Html(list):
|
||||
# Use slice syntax since we don't override slicing
|
||||
self[0:] = [begin] + list(args) # add beginning tag
|
||||
if self.close: # if need closing tab
|
||||
self[len(self):] = ['</%s>' % tag] # add it on the end
|
||||
self[len(self):] = ['</%s>' % tag] # add it on the end
|
||||
#
|
||||
def __add(self, value):
|
||||
"""
|
||||
@ -332,8 +320,8 @@ class Html(list):
|
||||
:type value: object
|
||||
:param value: object to be added
|
||||
|
||||
:rtype: object reference
|
||||
:returns: reference to object with new value added
|
||||
:rtype: object reference
|
||||
:returns: reference to object with new value added
|
||||
"""
|
||||
if (isinstance(value, Html) or not hasattr(value, '__iter__') or
|
||||
isinstance(value, str)):
|
||||
@ -358,11 +346,11 @@ class Html(list):
|
||||
|
||||
:type cur_value: object
|
||||
:param cur_value: value of object to be replaced
|
||||
:type value: object
|
||||
:param value: replacement value
|
||||
:type value: object
|
||||
:param value: replacement value
|
||||
|
||||
:rtype: object reference
|
||||
:returns: reference to object with new value added
|
||||
:rtype: object reference
|
||||
:returns: reference to object with new value added
|
||||
"""
|
||||
self[self.index(cur_value)] = value
|
||||
#
|
||||
@ -372,8 +360,8 @@ class Html(list):
|
||||
:type value: object
|
||||
:param value: object to be removed
|
||||
|
||||
:rtype: object reference
|
||||
:returns: reference to object with value removed
|
||||
:rtype: object reference
|
||||
:returns: reference to object with value removed
|
||||
"""
|
||||
del self[self.index(value)]
|
||||
return self
|
||||
@ -384,7 +372,7 @@ class Html(list):
|
||||
"""
|
||||
Returns string representation
|
||||
|
||||
:rtype: string
|
||||
:rtype: string
|
||||
:returns: string representation of object
|
||||
"""
|
||||
return '%s'*len(self) % tuple(self[:])
|
||||
@ -394,9 +382,9 @@ class Html(list):
|
||||
Iterator function: returns a generator that performs an
|
||||
insertion-order tree traversal and yields each item found.
|
||||
"""
|
||||
for item in self[:]: # loop through all list elements
|
||||
for item in self[:]: # loop through all list elements
|
||||
if isinstance(item, Html): # if nested list found
|
||||
for sub_item in item: # recurse
|
||||
for sub_item in item: # recurse
|
||||
yield sub_item
|
||||
else:
|
||||
yield item
|
||||
@ -405,26 +393,26 @@ class Html(list):
|
||||
#
|
||||
def write(self, method=print, indent='\t', tabs=''):
|
||||
"""
|
||||
Output function: performs an insertion-order tree traversal and
|
||||
calls supplied method for each item found.
|
||||
Output function: performs an insertion-order tree traversal
|
||||
and calls supplied method for each item found.
|
||||
|
||||
:type method: function reference
|
||||
:param method: function to call with each item found
|
||||
:type indent: string
|
||||
:param indenf: string to use for indentation. Default = '\t' (tab)
|
||||
:type tabs: string
|
||||
:param tabs: starting indentation
|
||||
:type method: function reference
|
||||
:param method: function to call with each item found
|
||||
:type indent: string
|
||||
:param indenf: string to use for indentation. Default = '\t' (tab)
|
||||
:type tabs: string
|
||||
:param tabs: starting indentation
|
||||
"""
|
||||
if self.indent is None:
|
||||
tabs = ''
|
||||
elif self.indent:
|
||||
tabs += indent
|
||||
if self.inline: # if inline, write all list and
|
||||
method(str('%s%s' % (tabs, self))) # nested list elements
|
||||
if self.inline: # if inline, write all list and
|
||||
method(str('%s%s' % (tabs, self))) # nested list elements
|
||||
#
|
||||
else:
|
||||
for item in self[:]: # else write one at a time
|
||||
if isinstance(item, Html): # recurse if nested Html class
|
||||
for item in self[:]: # else write one at a time
|
||||
if isinstance(item, Html): # recurse if nested Html class
|
||||
item.write(method=method, indent=indent, tabs=tabs)
|
||||
else:
|
||||
method(str('%s%s' % (tabs, item))) # else write the line
|
||||
@ -433,10 +421,10 @@ class Html(list):
|
||||
"""
|
||||
Add an XML statement to the start of the list for this object
|
||||
|
||||
:type version: decimal number
|
||||
:param version: version of XML to be used. Defaults to 1.0
|
||||
:type encoding: string
|
||||
:param encoding: encoding method to be used. Defaults to "UTF-8"
|
||||
:type version: decimal number
|
||||
:param version: version of XML to be used. Defaults to 1.0
|
||||
:type encoding: string
|
||||
:param encoding: encoding method to be used. Defaults to "UTF-8"
|
||||
:type standalone: string
|
||||
:param standalone: "yes" or "no". Defaults to "no"
|
||||
"""
|
||||
@ -448,30 +436,30 @@ class Html(list):
|
||||
self[0:0] = [xmldecl]
|
||||
#
|
||||
def addDOCTYPE(self, name='html', public='PUBLIC',
|
||||
external_id=_HTML5, *args):
|
||||
external_id=_HTML5, *args):
|
||||
"""
|
||||
Add a DOCTYPE statement to the start of the list
|
||||
|
||||
:type name: string
|
||||
:param name: name of this DOCTYPE. Defaults to "html"
|
||||
:type name: string
|
||||
:param name: name of this DOCTYPE. Defaults to "html"
|
||||
:type external_id: string
|
||||
:param external_id: external identifier of this DOCTYPE.
|
||||
Defaults to XHTML 1.0 STRICT
|
||||
:type args: object
|
||||
:param args: 0 or more positional parameters to be added
|
||||
to this DOCTYPE.
|
||||
:type args: object
|
||||
:param args: 0 or more positional parameters to be added to this
|
||||
DOCTYPE.
|
||||
"""
|
||||
doctype = (
|
||||
'<!DOCTYPE %s %s %s%s' % (name,
|
||||
('' if external_id == _HTML5
|
||||
else public),
|
||||
external_id,
|
||||
' %s'*len(args) % args)
|
||||
'<!DOCTYPE %s %s %s%s' % (
|
||||
name,
|
||||
('' if external_id ==_HTML5 else public),
|
||||
external_id,
|
||||
' %s'*len(args) % args
|
||||
)
|
||||
).rstrip() + '>'
|
||||
# Note: DOCTYPE declaration must follow XML declaration
|
||||
|
||||
#if len(self) and self[0][:6] == '<?xml ':
|
||||
if self[0][:6] == '<?xml ':
|
||||
if len(self) and self[0][:6] == '<?xml ':
|
||||
self[1:1] = [doctype]
|
||||
else:
|
||||
self[0:0] = [doctype]
|
||||
@ -480,7 +468,7 @@ class Html(list):
|
||||
"""
|
||||
Returns HTML tag for this object
|
||||
|
||||
:rtype: string
|
||||
:rtype: string
|
||||
:returns: HTML tag
|
||||
"""
|
||||
return self[0].split()[0].strip('< >')
|
||||
@ -508,7 +496,7 @@ class Html(list):
|
||||
"""
|
||||
Returns HTML attributes for this object
|
||||
|
||||
:rtype: string
|
||||
:rtype: string
|
||||
:returns: HTML attributes
|
||||
"""
|
||||
attr = self[0].strip('<!?/>').split(None, 1)
|
||||
@ -532,16 +520,20 @@ class Html(list):
|
||||
"""
|
||||
Removes HTML attributes for this object
|
||||
"""
|
||||
self[0] = '<' + self.tag + (# Set correct closing delimiter(s)
|
||||
' />' if self.close is False else '>')
|
||||
self[0] = '<' + self.tag + (
|
||||
|
||||
# Set correct closing delimiter(s)
|
||||
|
||||
' />' if self.close is False else '>'
|
||||
)
|
||||
#
|
||||
attr = property(__getattr, __setattr, __delattr)
|
||||
attr = property(__getattr, __setattr, __delattr)
|
||||
#
|
||||
def __getinside(self):
|
||||
"""
|
||||
Returns list of items between opening and closing tags
|
||||
|
||||
:rtype: list
|
||||
:rtype: list
|
||||
:returns: list of items between opening and closing HTML tags
|
||||
"""
|
||||
return self[1:-1]
|
||||
|
||||
@ -513,7 +513,7 @@ def _get_styled(name, callname, placeholder=False,
|
||||
elif callname == CALLNAME_UNDERLINE_ADD:
|
||||
if n.call not in n.first_name:
|
||||
# Add call name to first name.
|
||||
# Translators: used in French+Russian, ignore otherwise
|
||||
# translators: used in French+Russian, ignore otherwise
|
||||
n.first_name = trans_text('"%(callname)s" (%(firstname)s)') % {
|
||||
'callname': n.call,
|
||||
'firstname': n.first_name }
|
||||
|
||||
@ -703,7 +703,7 @@ class PageNumberBox(BoxBase):
|
||||
|
||||
def __calc_position(self, page):
|
||||
""" calculate where I am to print on the page(s) """
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore otherwise
|
||||
self.text = "(%d" + self._(',') + "%d)"
|
||||
|
||||
style_sheet = self.doc.get_style_sheet()
|
||||
|
||||
@ -416,7 +416,7 @@ def run(database, document, filter_name, *args, **kwargs):
|
||||
|
||||
else:
|
||||
raise AttributeError("invalid filter name: '%s'" % filter_name)
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
sdoc.paragraph(ngettext("Filter matched {number_of} record.",
|
||||
"Filter matched {number_of} records.", matches
|
||||
).format(number_of=matches) )
|
||||
|
||||
@ -131,7 +131,7 @@ def run(database, document, person):
|
||||
|
||||
document.has_data = matches > 0
|
||||
sdoc.paragraph(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext("There is {number_of} person "
|
||||
"with a matching name, or alternate name.\n",
|
||||
"There are {number_of} people "
|
||||
@ -176,7 +176,7 @@ def run_given(database, document, person):
|
||||
|
||||
document.has_data = matches > 0
|
||||
sdoc.paragraph(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext("There is {number_of} person "
|
||||
"with a matching name, or alternate name.\n",
|
||||
"There are {number_of} people "
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
# Copyright (C) 2003-2005 Donald N. Allingham
|
||||
# Copyright (C) 2008 Stefan Siegel
|
||||
# Copyright (C) 2008 Brian G. Matherly
|
||||
# Copyright (C) 2021 Mirko Leonhaeuser
|
||||
#
|
||||
# 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
|
||||
@ -157,7 +156,7 @@ class RelationshipCalculator(gramps.gen.relationship.RelationshipCalculator):
|
||||
if removed < len(_removed):
|
||||
return _removed[removed]
|
||||
else:
|
||||
return '(%s) Urgroß' % self._make_roman(removed-1)
|
||||
return '(%s)' % self._make_roman(removed-2)
|
||||
|
||||
def _degree_text(self, degree, removed):
|
||||
if removed == 0:
|
||||
|
||||
@ -366,7 +366,7 @@ reports.addcli(TestDynamic, "tool_verify",
|
||||
"--options", "name=verify")
|
||||
|
||||
txt_list = ["6 media objects were referenced, but not found",
|
||||
"References to 6 missing media objects were kept"]
|
||||
"References to 6 media objects were kept"]
|
||||
reports.addcli(TestDynamic, "tool_check",
|
||||
out_does_contain(txt_list),
|
||||
[None],
|
||||
|
||||
@ -140,7 +140,7 @@ class ToolControl(unittest.TestCase):
|
||||
"4 broken spouse/family links were fixed",
|
||||
"1 place alternate name fixed",
|
||||
"10 media objects were referenced, but not found",
|
||||
"References to 10 missing media objects were kept",
|
||||
"References to 10 media objects were kept",
|
||||
"3 events were referenced, but not found",
|
||||
"1 invalid birth event name was fixed",
|
||||
"1 invalid death event name was fixed",
|
||||
|
||||
@ -334,7 +334,7 @@ class BirthdayReport(Report):
|
||||
'person' : short_name,
|
||||
'relation' : comment}
|
||||
else:
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
text = ngettext('* {year}{person}{dead}, {age}{relation}',
|
||||
'* {year}{person}{dead}, {age}{relation}',
|
||||
nyears).format(year=yeartxt,
|
||||
@ -403,7 +403,7 @@ class BirthdayReport(Report):
|
||||
'spouse' : spouse_name,
|
||||
'person' : short_name}
|
||||
else:
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
text = ngettext("⚭ {year}{spouse}{deadtxt2} and\n {person}{deadtxt1}, {nyears}",
|
||||
"⚭ {year}{spouse}{deadtxt2} and\n {person}{deadtxt1}, {nyears}",
|
||||
nyears).format(year=yeartxt, spouse=spouse_name, deadtxt2=deadtxt2, person=short_name, deadtxt1=deadtxt1, nyears=nyears)
|
||||
|
||||
@ -413,7 +413,7 @@ class DetAncestorReport(Report):
|
||||
date = addr.get_date_object().get_year()
|
||||
|
||||
if date:
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore otherwise
|
||||
self.doc.write_text(self._('%s, ') % date)
|
||||
self.doc.write_text(text)
|
||||
self.doc.write_text_citation(self.endnotes(addr))
|
||||
@ -426,7 +426,7 @@ class DetAncestorReport(Report):
|
||||
for attr in attrs:
|
||||
self.doc.start_paragraph('DAR-MoreDetails')
|
||||
attr_name = attr.get_type().type2base()
|
||||
# Translators: needed for French, ignore otherwise
|
||||
# translators: needed for French, ignore otherwise
|
||||
text = self._("%(type)s: %(value)s%(endnotes)s"
|
||||
) % {'type' : self._(attr_name),
|
||||
'value' : attr.get_value(),
|
||||
@ -450,7 +450,7 @@ class DetAncestorReport(Report):
|
||||
|
||||
self.doc.start_paragraph('DAR-MoreDetails')
|
||||
if date and place:
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore otherwise
|
||||
text += self._('%(str1)s, %(str2)s'
|
||||
) % {'str1' : date, 'str2' : place}
|
||||
elif date:
|
||||
@ -471,7 +471,7 @@ class DetAncestorReport(Report):
|
||||
event_name = self._(self._get_type(event.get_type()))
|
||||
role = event_ref.get_role()
|
||||
if role in (EventRoleType.PRIMARY, EventRoleType.FAMILY):
|
||||
# Translators: needed for French, ignore otherwise
|
||||
# translators: needed for French, ignore otherwise
|
||||
text = self._('%(str1)s: %(str2)s'
|
||||
) % {'str1' : event_name, 'str2' : text}
|
||||
else:
|
||||
@ -491,10 +491,10 @@ class DetAncestorReport(Report):
|
||||
attr_list.extend(event_ref.get_attribute_list())
|
||||
for attr in attr_list:
|
||||
if text:
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore otherwise
|
||||
text += self._("; ")
|
||||
attr_name = attr.get_type().type2base()
|
||||
# Translators: needed for French, ignore otherwise
|
||||
# translators: needed for French, ignore otherwise
|
||||
text += self._("%(type)s: %(value)s%(endnotes)s"
|
||||
) % {'type' : self._(attr_name),
|
||||
'value' : attr.get_value(),
|
||||
|
||||
@ -411,7 +411,7 @@ class DetDescendantReport(Report):
|
||||
if index == 1:
|
||||
self.doc.write_text(name + "-" + str(index) + ") ")
|
||||
else:
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore otherwise
|
||||
self.doc.write_text(name + "-" + str(index) + self._("; "))
|
||||
index -= 1
|
||||
|
||||
@ -483,7 +483,7 @@ class DetDescendantReport(Report):
|
||||
self.doc.start_paragraph('DDR-MoreDetails')
|
||||
event_name = self._get_type(event.get_type())
|
||||
if date and place:
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore otherwise
|
||||
text += self._('%(str1)s, %(str2)s'
|
||||
) % {'str1' : date, 'str2' : place}
|
||||
elif date:
|
||||
@ -501,7 +501,7 @@ class DetDescendantReport(Report):
|
||||
if text:
|
||||
text += ". "
|
||||
|
||||
# Translators: needed for French, ignore otherwise
|
||||
# translators: needed for French, ignore otherwise
|
||||
text = self._('%(str1)s: %(str2)s'
|
||||
) % {'str1' : self._(event_name),
|
||||
'str2' : text}
|
||||
@ -514,10 +514,10 @@ class DetDescendantReport(Report):
|
||||
attr_list.extend(event_ref.get_attribute_list())
|
||||
for attr in attr_list:
|
||||
if text:
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore otherwise
|
||||
text += self._("; ")
|
||||
attr_name = attr.get_type().type2base()
|
||||
# Translators: needed for French, ignore otherwise
|
||||
# translators: needed for French, ignore otherwise
|
||||
text += self._("%(type)s: %(value)s%(endnotes)s"
|
||||
) % {'type' : self._(attr_name),
|
||||
'value' : attr.get_value(),
|
||||
@ -935,7 +935,7 @@ class DetDescendantReport(Report):
|
||||
|
||||
self.doc.write_text(self._('Address: '))
|
||||
if date:
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore otherwise
|
||||
self.doc.write_text(self._('%s, ') % date)
|
||||
self.doc.write_text(text)
|
||||
self.doc.write_text_citation(self.endnotes(addr))
|
||||
@ -954,7 +954,7 @@ class DetDescendantReport(Report):
|
||||
for attr in attrs:
|
||||
self.doc.start_paragraph('DDR-MoreDetails')
|
||||
attr_name = attr.get_type().type2base()
|
||||
# Translators: needed for French, ignore otherwise
|
||||
# translators: needed for French, ignore otherwise
|
||||
text = self._("%(type)s: %(value)s%(endnotes)s"
|
||||
) % {'type' : self._(attr_name),
|
||||
'value' : attr.get_value(),
|
||||
|
||||
@ -133,10 +133,10 @@ class FamilyGroup(Report):
|
||||
if self.include_attrs:
|
||||
for attr in event.get_attribute_list():
|
||||
if descr:
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore otherwise
|
||||
descr += self._("; ")
|
||||
attr_type = self._get_type(attr.get_type())
|
||||
# Translators: needed for French, ignore otherwise
|
||||
# translators: needed for French, ignore otherwise
|
||||
descr += self._("%(str1)s: %(str2)s"
|
||||
) % {'str1' : self._(attr_type),
|
||||
'str2' : attr.get_value()}
|
||||
@ -302,7 +302,7 @@ class FamilyGroup(Report):
|
||||
self.doc.start_cell('FGR-ParentHead', 3)
|
||||
self.doc.start_paragraph('FGR-ParentName')
|
||||
mark = utils.get_person_mark(self.db, person)
|
||||
# Translators: needed for French, ignore otherwise
|
||||
# translators: needed for French, ignore otherwise
|
||||
self.doc.write_text(self._("%(str1)s: %(str2)s"
|
||||
) % {'str1' : title,
|
||||
'str2' : name},
|
||||
@ -406,7 +406,7 @@ class FamilyGroup(Report):
|
||||
header = self._("Marriage")
|
||||
if self.gramps_ids:
|
||||
header += " (%s)" % family.get_gramps_id()
|
||||
# Translators: needed for French, ignore otherwise
|
||||
# translators: needed for French, ignore otherwise
|
||||
self.doc.write_text(self._("%s:") % header)
|
||||
self.doc.end_paragraph()
|
||||
self.doc.end_cell()
|
||||
|
||||
@ -199,7 +199,7 @@ class IndivCompleteReport(Report):
|
||||
column_1 = self._(self._get_type(event.get_type()))
|
||||
if role not in (EventRoleType.PRIMARY, EventRoleType.FAMILY):
|
||||
column_1 = column_1 + ' (' + self._(role.xml_str()) + ')'
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore otherwise
|
||||
# make sure it's translated, so it can be used below, in "combine"
|
||||
ignore = _('%(str1)s, %(str2)s') % {'str1' : '', 'str2' : ''}
|
||||
column_2 = self.combine('%(str1)s, %(str2)s', '%s',
|
||||
@ -207,7 +207,7 @@ class IndivCompleteReport(Report):
|
||||
else:
|
||||
# Groups with a single type (remove event type from first column)
|
||||
column_1 = date
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore otherwise
|
||||
# make sure it's translated, so it can be used below, in "combine"
|
||||
ignore = _('%(str1)s, %(str2)s') % {'str1' : '', 'str2' : ''}
|
||||
column_2 = self.combine('%(str1)s, %(str2)s', '%s',
|
||||
@ -247,7 +247,7 @@ class IndivCompleteReport(Report):
|
||||
self.doc.start_row()
|
||||
self.write_cell(label)
|
||||
if parent_name:
|
||||
# Translators: e.g. (a stepfather): John Smith, relationship: Step
|
||||
# for example (a stepfather): John Smith, relationship: Step
|
||||
text = self._('%(parent-name)s, relationship: %(rel-type)s'
|
||||
) % {'parent-name' : parent_name,
|
||||
'rel-type' : self._(rel_type)}
|
||||
@ -919,7 +919,7 @@ class IndivCompleteReport(Report):
|
||||
p_style = 'IDS-PersonTable' # this is tested for, also
|
||||
else:
|
||||
self._user.warn(_("Could not add photo to page"),
|
||||
# Translators: for French, else ignore
|
||||
# translators: for French, else ignore
|
||||
_("%(str1)s: %(str2)s"
|
||||
) % {'str1' : image_filename,
|
||||
'str2' : _('File does not exist')})
|
||||
@ -927,7 +927,7 @@ class IndivCompleteReport(Report):
|
||||
self.doc.start_table('person', p_style)
|
||||
self.doc.start_row()
|
||||
|
||||
# Translators: needed for French, ignore otherwise
|
||||
# translators: needed for French, ignore otherwise
|
||||
ignore = self._("%s:")
|
||||
self.doc.start_cell('IDS-NormalCell')
|
||||
self.write_paragraph(self._("%s:") % self._("Name"))
|
||||
@ -959,7 +959,7 @@ class IndivCompleteReport(Report):
|
||||
else:
|
||||
for attr in attr_list:
|
||||
attr_type = attr.get_type().type2base()
|
||||
# Translators: needed for French, ignore otherwise
|
||||
# translators: needed for French, ignore otherwise
|
||||
text = self._("%(str1)s: %(str2)s"
|
||||
) % {'str1' : self._(attr_type),
|
||||
'str2' : attr.get_value()}
|
||||
@ -1020,7 +1020,7 @@ class IndivCompleteReport(Report):
|
||||
if not txt:
|
||||
return prior
|
||||
if prior:
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore otherwise
|
||||
txt = self._('%(str1)s, %(str2)s') % {'str1':prior, 'str2':txt}
|
||||
return txt
|
||||
|
||||
@ -1030,7 +1030,7 @@ class IndivCompleteReport(Report):
|
||||
return
|
||||
for attr in attr_list:
|
||||
attr_type = attr.get_type().type2base()
|
||||
# Translators: needed for French, ignore otherwise
|
||||
# translators: needed for French, ignore otherwise
|
||||
text = self._("%(str1)s: %(str2)s"
|
||||
) % {'str1' : self._(attr_type),
|
||||
'str2' : attr.get_value()}
|
||||
|
||||
@ -120,7 +120,7 @@ class NumberOfAncestorsReport(Report):
|
||||
|
||||
# TC # English return something like:
|
||||
# Generation 3 has 2 individuals. (50.00%)
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
text = ngettext(
|
||||
"Generation {number} has {count} individual. {percent}",
|
||||
"Generation {number} has {count} individuals. {percent}",
|
||||
|
||||
@ -181,7 +181,7 @@ class PlaceReport(Report):
|
||||
|
||||
place_details = [self._("Gramps ID: %s ") % place.get_gramps_id()]
|
||||
for level in get_location_list(self._db, place):
|
||||
# Translators: needed for French, ignore otherwise
|
||||
# translators: needed for French, ignore otherwise
|
||||
place_details.append(self._("%(str1)s: %(str2)s"
|
||||
) % {'str1': self._(level[1].xml_str()),
|
||||
'str2': level[0]})
|
||||
@ -191,7 +191,7 @@ class PlaceReport(Report):
|
||||
if len(all_names) > 1 or __debug__:
|
||||
for place_name in all_names:
|
||||
if place_names != '':
|
||||
# Translators: needed for Arabic, ignore otherwise
|
||||
# translators: needed for Arabic, ignore otherwise
|
||||
place_names += self._(", ")
|
||||
place_names += '%s' % place_name.get_value()
|
||||
if place_name.get_language() != '' or __debug__:
|
||||
|
||||
@ -133,7 +133,7 @@ class ChangeTypes(tool.BatchTool, ManagedWindow):
|
||||
if modified == 0:
|
||||
msg = _("No event record was modified.")
|
||||
else:
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
msg = ngettext("{number_of} event record was modified.",
|
||||
"{number_of} event records were modified.", modified
|
||||
).format(number_of=modified)
|
||||
|
||||
@ -2458,7 +2458,7 @@ class CheckIntegrity:
|
||||
|
||||
if blink > 0:
|
||||
self.text.write(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext("{quantity} broken child/family link was fixed\n",
|
||||
"{quantity} broken child/family links were fixed\n",
|
||||
blink).format(quantity=blink)
|
||||
@ -2484,7 +2484,7 @@ class CheckIntegrity:
|
||||
|
||||
if plink > 0:
|
||||
self.text.write(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext("{quantity} broken spouse/family link was fixed\n",
|
||||
"{quantity} broken spouse/family links were fixed\n",
|
||||
plink).format(quantity=plink)
|
||||
@ -2510,7 +2510,7 @@ class CheckIntegrity:
|
||||
|
||||
if slink > 0:
|
||||
self.text.write(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext("{quantity} duplicate "
|
||||
"spouse/family link was found\n",
|
||||
"{quantity} duplicate "
|
||||
@ -2538,7 +2538,7 @@ class CheckIntegrity:
|
||||
|
||||
if efam:
|
||||
self.text.write(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext("{quantity} family "
|
||||
"with no parents or children found, removed.\n",
|
||||
"{quantity} families "
|
||||
@ -2550,7 +2550,7 @@ class CheckIntegrity:
|
||||
|
||||
if rel:
|
||||
self.text.write(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext("{quantity} corrupted family relationship fixed\n",
|
||||
"{quantity} corrupted family relationships fixed\n",
|
||||
rel).format(quantity=rel)
|
||||
@ -2558,7 +2558,7 @@ class CheckIntegrity:
|
||||
|
||||
if self.place_errors:
|
||||
self.text.write(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext("{quantity} place alternate name fixed\n",
|
||||
"{quantity} place alternate names fixed\n",
|
||||
self.place_errors).format(quantity=self.place_errors)
|
||||
@ -2566,7 +2566,7 @@ class CheckIntegrity:
|
||||
|
||||
if person_references:
|
||||
self.text.write(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext(
|
||||
"{quantity} person was referenced but not found\n",
|
||||
"{quantity} persons were referenced, but not found\n",
|
||||
@ -2575,7 +2575,7 @@ class CheckIntegrity:
|
||||
|
||||
if family_references:
|
||||
self.text.write(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext("{quantity} family was "
|
||||
"referenced but not found\n",
|
||||
"{quantity} families were "
|
||||
@ -2585,7 +2585,7 @@ class CheckIntegrity:
|
||||
|
||||
if invalid_dates:
|
||||
self.text.write(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext("{quantity} date was corrected\n",
|
||||
"{quantity} dates were corrected\n",
|
||||
invalid_dates).format(quantity=invalid_dates)
|
||||
@ -2593,7 +2593,7 @@ class CheckIntegrity:
|
||||
|
||||
if repo_references:
|
||||
self.text.write(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext(
|
||||
"{quantity} repository was "
|
||||
"referenced but not found\n",
|
||||
@ -2604,7 +2604,7 @@ class CheckIntegrity:
|
||||
|
||||
if photos:
|
||||
self.text.write(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext("{quantity} media object was "
|
||||
"referenced but not found\n",
|
||||
"{quantity} media objects were "
|
||||
@ -2614,16 +2614,16 @@ class CheckIntegrity:
|
||||
|
||||
if bad_photos:
|
||||
self.text.write(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext(
|
||||
"Reference to {quantity} missing media object was kept\n",
|
||||
"References to {quantity} missing media objects were kept\n",
|
||||
"References to {quantity} media objects were kept\n",
|
||||
bad_photos).format(quantity=bad_photos)
|
||||
)
|
||||
|
||||
if replaced_photos:
|
||||
self.text.write(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext("{quantity} missing media object was replaced\n",
|
||||
"{quantity} missing media objects were replaced\n",
|
||||
replaced_photos).format(quantity=replaced_photos)
|
||||
@ -2631,7 +2631,7 @@ class CheckIntegrity:
|
||||
|
||||
if removed_photos:
|
||||
self.text.write(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext("{quantity} missing media object was removed\n",
|
||||
"{quantity} missing media objects were removed\n",
|
||||
removed_photos).format(quantity=removed_photos)
|
||||
@ -2639,7 +2639,7 @@ class CheckIntegrity:
|
||||
|
||||
if event_invalid:
|
||||
self.text.write(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext("{quantity} event was referenced but not found\n",
|
||||
"{quantity} events were referenced, but not found\n",
|
||||
event_invalid).format(quantity=event_invalid)
|
||||
@ -2647,7 +2647,7 @@ class CheckIntegrity:
|
||||
|
||||
if birth_invalid:
|
||||
self.text.write(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext("{quantity} invalid birth event name was fixed\n",
|
||||
"{quantity} invalid birth event names were fixed\n",
|
||||
birth_invalid).format(quantity=birth_invalid)
|
||||
@ -2655,7 +2655,7 @@ class CheckIntegrity:
|
||||
|
||||
if death_invalid:
|
||||
self.text.write(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext("{quantity} invalid death event name was fixed\n",
|
||||
"{quantity} invalid death event names were fixed\n",
|
||||
death_invalid).format(quantity=death_invalid)
|
||||
@ -2663,7 +2663,7 @@ class CheckIntegrity:
|
||||
|
||||
if place_references:
|
||||
self.text.write(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext("{quantity} place was referenced but not found\n",
|
||||
"{quantity} places were referenced, but not found\n",
|
||||
place_references).format(quantity=place_references)
|
||||
@ -2671,7 +2671,7 @@ class CheckIntegrity:
|
||||
|
||||
if citation_references:
|
||||
self.text.write(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext(
|
||||
"{quantity} citation was referenced but not found\n",
|
||||
"{quantity} citations were referenced, but not found\n",
|
||||
@ -2681,7 +2681,7 @@ class CheckIntegrity:
|
||||
|
||||
if source_references:
|
||||
self.text.write(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext(
|
||||
"{quantity} source was referenced but not found\n",
|
||||
"{quantity} sources were referenced, but not found\n",
|
||||
@ -2690,7 +2690,7 @@ class CheckIntegrity:
|
||||
|
||||
if media_references:
|
||||
self.text.write(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext(
|
||||
"{quantity} media object was referenced but not found\n",
|
||||
"{quantity} media objects were referenced,"
|
||||
@ -2700,7 +2700,7 @@ class CheckIntegrity:
|
||||
|
||||
if note_references:
|
||||
self.text.write(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext("{quantity} note object was "
|
||||
"referenced but not found\n",
|
||||
"{quantity} note objects were "
|
||||
@ -2710,7 +2710,7 @@ class CheckIntegrity:
|
||||
|
||||
if tag_references:
|
||||
self.text.write(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext("{quantity} tag object was "
|
||||
"referenced but not found\n",
|
||||
"{quantity} tag objects were "
|
||||
@ -2720,7 +2720,7 @@ class CheckIntegrity:
|
||||
|
||||
if tag_references:
|
||||
self.text.write(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext("{quantity} tag object was "
|
||||
"referenced but not found\n",
|
||||
"{quantity} tag objects were "
|
||||
@ -2730,7 +2730,7 @@ class CheckIntegrity:
|
||||
|
||||
if name_format:
|
||||
self.text.write(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext("{quantity} invalid name format "
|
||||
"reference was removed\n",
|
||||
"{quantity} invalid name format "
|
||||
@ -2740,7 +2740,7 @@ class CheckIntegrity:
|
||||
|
||||
if replaced_sourcerefs:
|
||||
self.text.write(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext(
|
||||
"{quantity} invalid source citation was fixed\n",
|
||||
"{quantity} invalid source citations were fixed\n",
|
||||
@ -2750,7 +2750,7 @@ class CheckIntegrity:
|
||||
|
||||
if dup_gramps_ids > 0:
|
||||
self.text.write(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext("{quantity} Duplicated Gramps ID fixed\n",
|
||||
"{quantity} Duplicated Gramps IDs fixed\n",
|
||||
dup_gramps_ids).format(quantity=dup_gramps_ids)
|
||||
|
||||
@ -116,7 +116,7 @@ class EventNames(tool.BatchTool):
|
||||
else:
|
||||
parent_window = None
|
||||
if self.change == True:
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
message = ngettext("{quantity} event description has been added",
|
||||
"{quantity} event descriptions have been added",
|
||||
counter).format(quantity=counter)
|
||||
|
||||
@ -231,7 +231,7 @@ class MergeCitations(tool.BatchTool,ManagedWindow):
|
||||
db.request_rebuild()
|
||||
self.progress.close()
|
||||
OkDialog(_("Number of merges done"),
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext("{number_of} citation merged",
|
||||
"{number_of} citations merged", num_merges
|
||||
).format(number_of=num_merges),
|
||||
|
||||
@ -257,7 +257,7 @@ class NotRelated(tool.ActivePersonTool, ManagedWindow):
|
||||
progress = ProgressMeter(self.title, _('Starting'),
|
||||
parent=self.window)
|
||||
progress.set_pass(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
#TRANS: no singular form needed, as rows is always > 1
|
||||
ngettext("Setting tag for {number_of} person",
|
||||
"Setting tag for {number_of} people",
|
||||
@ -300,7 +300,7 @@ class NotRelated(tool.ActivePersonTool, ManagedWindow):
|
||||
def findRelatedPeople(self):
|
||||
|
||||
self.progress.set_pass(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
#TRANS: No singular form is needed.
|
||||
ngettext("Finding relationships between {number_of} person",
|
||||
"Finding relationships between {number_of} people",
|
||||
@ -381,7 +381,7 @@ class NotRelated(tool.ActivePersonTool, ManagedWindow):
|
||||
# we have at least 1 "unrelated" person to find
|
||||
|
||||
self.progress.set_pass(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext("Looking for {number_of} person",
|
||||
"Looking for {number_of} people",
|
||||
self.numberOfUnrelatedPeople
|
||||
@ -409,7 +409,7 @@ class NotRelated(tool.ActivePersonTool, ManagedWindow):
|
||||
def populateModel(self):
|
||||
|
||||
self.progress.set_pass(
|
||||
# Translators: leave all/any {...} untranslated
|
||||
# translators: leave all/any {...} untranslated
|
||||
ngettext("Looking up the name of {number_of} person",
|
||||
"Looking up the names of {number_of} people",
|
||||
self.numberOfUnrelatedPeople
|
||||
|
||||
@ -314,7 +314,7 @@ class Verify(tool.Tool, ManagedWindow, UpdateCallback):
|
||||
severity_str = 'W'
|
||||
elif severity == Rule.ERROR:
|
||||
severity_str = 'E'
|
||||
# Translators: needed for French+Arabic, ignore otherwise
|
||||
# translators: needed for French+Arabic, ignore otherwise
|
||||
print(_("%(severity)s: %(msg)s, %(type)s: %(gid)s, %(name)s"
|
||||
) % {'severity' : severity_str, 'msg' : msg, 'type' : the_type,
|
||||
'gid' : gramps_id, 'name' : name})
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user