Make an easy way to start gramps for novices
This is related to: https://gramps.discourse.group/t/novice-user-ux-proposed-solution/1832
This commit is contained in:
@@ -37,6 +37,7 @@ import subprocess
|
|||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
|
import tempfile
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
@@ -53,7 +54,7 @@ from gi.repository import Pango
|
|||||||
#
|
#
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
from .display import display_help
|
from .display import display_help
|
||||||
from gramps.gen.const import URL_WIKISTRING, URL_MANUAL_PAGE
|
from gramps.gen.const import (URL_WIKISTRING, URL_MANUAL_PAGE, USER_HOME)
|
||||||
from .user import User
|
from .user import User
|
||||||
from .dialog import ErrorDialog, QuestionDialog, QuestionDialog2, ICON
|
from .dialog import ErrorDialog, QuestionDialog, QuestionDialog2, ICON
|
||||||
from .pluginmanager import GuiPluginManager
|
from .pluginmanager import GuiPluginManager
|
||||||
@@ -63,8 +64,11 @@ from .ddtargets import DdTargets
|
|||||||
from gramps.gen.recentfiles import rename_filename, remove_filename
|
from gramps.gen.recentfiles import rename_filename, remove_filename
|
||||||
from .glade import Glade
|
from .glade import Glade
|
||||||
from gramps.gen.db.exceptions import DbException
|
from gramps.gen.db.exceptions import DbException
|
||||||
|
from gramps.gen.errors import WindowActiveError
|
||||||
from gramps.gen.db.utils import make_database, open_database
|
from gramps.gen.db.utils import make_database, open_database
|
||||||
from gramps.gen.config import config
|
from gramps.gen.config import config
|
||||||
|
from .dbloader import DbLoader
|
||||||
|
|
||||||
from .listmodel import ListModel
|
from .listmodel import ListModel
|
||||||
from gramps.gen.constfunc import win
|
from gramps.gen.constfunc import win
|
||||||
from gramps.gen.plug import BasePluginManager
|
from gramps.gen.plug import BasePluginManager
|
||||||
@@ -112,6 +116,114 @@ BACKEND_COL = 7
|
|||||||
|
|
||||||
RCS_BUTTON = {True : _('_Extract'), False : _('_Archive')}
|
RCS_BUTTON = {True : _('_Extract'), False : _('_Archive')}
|
||||||
|
|
||||||
|
FIRST_TIME_DEFAULT_FILE = """<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE database PUBLIC "-//Gramps//DTD Gramps XML 1.7.1//EN"
|
||||||
|
"http://gramps-project.org/xml/1.7.1/grampsxml.dtd">
|
||||||
|
<database xmlns="http://gramps-project.org/xml/1.7.1/">
|
||||||
|
<header>
|
||||||
|
<created date="2021-09-06" version="5.1.3"/>
|
||||||
|
<researcher>
|
||||||
|
<resname></resname>
|
||||||
|
<rescity></rescity>
|
||||||
|
<resstate></resstate>
|
||||||
|
<rescountry></rescountry>
|
||||||
|
<respostal></respostal>
|
||||||
|
<resemail></resemail>
|
||||||
|
</researcher>
|
||||||
|
</header>
|
||||||
|
<events>
|
||||||
|
<event handle="_ed548c041fa32c988d5d657b24b" change="1630921138" id="E00000">
|
||||||
|
<type>Birth</type>
|
||||||
|
<place hlink="_ed548be51c757169db87d47eb17"/>
|
||||||
|
<description>My birth date</description>
|
||||||
|
</event>
|
||||||
|
<event handle="_ed548c75b6e4ead70b407e929e2" change="1630921184" id="E00001">
|
||||||
|
<type>Death</type>
|
||||||
|
<place hlink="_ed548be51c757169db87d47eb17"/>
|
||||||
|
<description>My death date</description>
|
||||||
|
</event>
|
||||||
|
<event handle="_ed548d06d5015bf1a3f45d8156f" change="1630921244" id="E00002">
|
||||||
|
<type>Birth</type>
|
||||||
|
<place hlink="_ed548be51c757169db87d47eb17"/>
|
||||||
|
</event>
|
||||||
|
<event handle="_ed548d262ac57c779d40741f72b" change="1630921257" id="E00003">
|
||||||
|
<type>Death</type>
|
||||||
|
<place hlink="_ed548be51c757169db87d47eb17"/>
|
||||||
|
</event>
|
||||||
|
<event handle="_ed548dd823a29ee79af6c958406" change="1630921329" id="E00004">
|
||||||
|
<type>Birth</type>
|
||||||
|
<place hlink="_ed548dce1b23bc140e754d077a8"/>
|
||||||
|
</event>
|
||||||
|
<event handle="_ed548e0361f1ae2cbc05454d012" change="1630921347" id="E00005">
|
||||||
|
<type>Death</type>
|
||||||
|
<place hlink="_ed548be51c757169db87d47eb17"/>
|
||||||
|
</event>
|
||||||
|
<event handle="_ed548e400156e491fe92ae01bed" change="1630921372" id="E00006">
|
||||||
|
<type>Marriage</type>
|
||||||
|
<place hlink="_ed548be51c757169db87d47eb17"/>
|
||||||
|
</event>
|
||||||
|
</events>
|
||||||
|
<people>
|
||||||
|
<person handle="_ed548ab269d640ea256206b4610" change="1630921381" id="I00000">
|
||||||
|
<gender>U</gender>
|
||||||
|
<name type="Birth Name">
|
||||||
|
<first>{me}</first>
|
||||||
|
<surname></surname>
|
||||||
|
</name>
|
||||||
|
<eventref hlink="_ed548c041fa32c988d5d657b24b" role="Primary"/>
|
||||||
|
<eventref hlink="_ed548c75b6e4ead70b407e929e2" role="Primary"/>
|
||||||
|
<childof hlink="_ed548cb8f4cc81352fdb41f3c1"/>
|
||||||
|
</person>
|
||||||
|
<person handle="_ed548cbf0d6f280dc7e4ac78f" change="1630921381" id="I00001">
|
||||||
|
<gender>M</gender>
|
||||||
|
<name type="Birth Name">
|
||||||
|
<first>{partner1}</first>
|
||||||
|
<surname></surname>
|
||||||
|
</name>
|
||||||
|
<eventref hlink="_ed548d06d5015bf1a3f45d8156f" role="Primary"/>
|
||||||
|
<eventref hlink="_ed548d262ac57c779d40741f72b" role="Primary"/>
|
||||||
|
<parentin hlink="_ed548cb8f4cc81352fdb41f3c1"/>
|
||||||
|
</person>
|
||||||
|
<person handle="_ed548d3e42d4102be30eb9ed5f8" change="1630921381" id="I00002">
|
||||||
|
<gender>F</gender>
|
||||||
|
<name type="Birth Name">
|
||||||
|
<first>{partner2}</first>
|
||||||
|
<surname></surname>
|
||||||
|
</name>
|
||||||
|
<eventref hlink="_ed548dd823a29ee79af6c958406" role="Primary"/>
|
||||||
|
<eventref hlink="_ed548e0361f1ae2cbc05454d012" role="Primary"/>
|
||||||
|
<parentin hlink="_ed548cb8f4cc81352fdb41f3c1"/>
|
||||||
|
</person>
|
||||||
|
</people>
|
||||||
|
<families>
|
||||||
|
<family handle="_ed548cb8f4cc81352fdb41f3c1" change="1630921381" id="F00000">
|
||||||
|
<rel type="Civil Union"/>
|
||||||
|
<father hlink="_ed548cbf0d6f280dc7e4ac78f"/>
|
||||||
|
<mother hlink="_ed548d3e42d4102be30eb9ed5f8"/>
|
||||||
|
<eventref hlink="_ed548e400156e491fe92ae01bed" role="Family"/>
|
||||||
|
<childref hlink="_ed548ab269d640ea256206b4610"/>
|
||||||
|
</family>
|
||||||
|
</families>
|
||||||
|
<places>
|
||||||
|
<placeobj handle="_ed548bd0f7877dce591a7d7b5a" change="1630921117" id="P00000" type="Country">
|
||||||
|
<pname value="{place1}"/>
|
||||||
|
</placeobj>
|
||||||
|
<placeobj handle="_ed548bd3b4335a76ccf085b246a" change="1630921320" id="P00001" type="County">
|
||||||
|
<pname value="{place2}"/>
|
||||||
|
<placeref hlink="_ed548bd0f7877dce591a7d7b5a"/>
|
||||||
|
</placeobj>
|
||||||
|
<placeobj handle="_ed548be51c757169db87d47eb17" change="1630921125" id="P00002" type="Village">
|
||||||
|
<pname value="{place3}"/>
|
||||||
|
<placeref hlink="_ed548bd3b4335a76ccf085b246a"/>
|
||||||
|
</placeobj>
|
||||||
|
<placeobj handle="_ed548dce1b23bc140e754d077a8" change="1630921325" id="P00003" type="Town">
|
||||||
|
<pname value="{place4}"/>
|
||||||
|
<placeref hlink="_ed548bd3b4335a76ccf085b246a"/>
|
||||||
|
</placeobj>
|
||||||
|
</places>
|
||||||
|
</database>
|
||||||
|
"""
|
||||||
|
|
||||||
class Information(ManagedWindow):
|
class Information(ManagedWindow):
|
||||||
|
|
||||||
def __init__(self, uistate, data, track):
|
def __init__(self, uistate, data, track):
|
||||||
@@ -172,7 +284,7 @@ class DbManager(CLIDbManager, ManagedWindow):
|
|||||||
|
|
||||||
for attr in ['connect_btn', 'cancel_btn', 'new_btn', 'remove_btn',
|
for attr in ['connect_btn', 'cancel_btn', 'new_btn', 'remove_btn',
|
||||||
'info_btn', 'rename_btn', 'convert_btn',
|
'info_btn', 'rename_btn', 'convert_btn',
|
||||||
'repair_btn', 'rcs_btn', 'msg', 'close_btn']:
|
'repair_btn', 'rcs_btn', 'msg', 'close_btn', 'firsttime']:
|
||||||
setattr(self, attr, self.glade.get_object(attr))
|
setattr(self, attr, self.glade.get_object(attr))
|
||||||
|
|
||||||
self.model = None
|
self.model = None
|
||||||
@@ -233,6 +345,7 @@ class DbManager(CLIDbManager, ManagedWindow):
|
|||||||
self.info_btn.connect('clicked', self.__info_db)
|
self.info_btn.connect('clicked', self.__info_db)
|
||||||
self.close_btn.connect('clicked', self.__close_db)
|
self.close_btn.connect('clicked', self.__close_db)
|
||||||
self.repair_btn.connect('clicked', self.__repair_db)
|
self.repair_btn.connect('clicked', self.__repair_db)
|
||||||
|
self.firsttime.connect('clicked', self.__firsttime_db)
|
||||||
self.selection.connect('changed', self.__selection_changed)
|
self.selection.connect('changed', self.__selection_changed)
|
||||||
self.dblist.connect('button-press-event', self.__button_press)
|
self.dblist.connect('button-press-event', self.__button_press)
|
||||||
self.dblist.connect('key-press-event', self.__key_press)
|
self.dblist.connect('key-press-event', self.__key_press)
|
||||||
@@ -293,6 +406,24 @@ class DbManager(CLIDbManager, ManagedWindow):
|
|||||||
if not _RCS_FOUND: # it's not in Windows
|
if not _RCS_FOUND: # it's not in Windows
|
||||||
self.rcs_btn.set_visible(False)
|
self.rcs_btn.set_visible(False)
|
||||||
|
|
||||||
|
if len(self.current_names) > 1:
|
||||||
|
# We have several databases.
|
||||||
|
# No need to have the "first time" button
|
||||||
|
self.firsttime.set_sensitive(False)
|
||||||
|
elif len(self.current_names) == 1:
|
||||||
|
# We have one database. Is it empty ?
|
||||||
|
name = self.current_names[0][0]
|
||||||
|
bdir = self.current_names[0][1]
|
||||||
|
summary = self.get_dbdir_summary(bdir, name)
|
||||||
|
nbpeople = 0
|
||||||
|
for item in sorted(summary):
|
||||||
|
if item == "Number of people":
|
||||||
|
nbpeople = summary[item]
|
||||||
|
if nbpeople:
|
||||||
|
# We have one database with people.
|
||||||
|
# No need to have the "first time" button.
|
||||||
|
self.firsttime.set_sensitive(False)
|
||||||
|
|
||||||
# if nothing is selected
|
# if nothing is selected
|
||||||
if not node:
|
if not node:
|
||||||
self.connect_btn.set_sensitive(False)
|
self.connect_btn.set_sensitive(False)
|
||||||
@@ -1034,6 +1165,220 @@ class DbManager(CLIDbManager, ManagedWindow):
|
|||||||
title.append(t)
|
title.append(t)
|
||||||
return fname, title
|
return fname, title
|
||||||
|
|
||||||
|
def __firsttime_db(self, obj):
|
||||||
|
"""
|
||||||
|
This is the first time we use gramps
|
||||||
|
|
||||||
|
1 - Verify this is the first time we use gramps.
|
||||||
|
Show the database dir for databases and explain how to change it.
|
||||||
|
2 - If no database in this database directory create a database.
|
||||||
|
If we have only one database and we have no people in it continue.
|
||||||
|
In all other cases we have nothing to do.
|
||||||
|
3 - Do we want to import a gedcom/gramps file.
|
||||||
|
4 - If no file given, create a default database with three people.
|
||||||
|
|
||||||
|
"""
|
||||||
|
message = ""
|
||||||
|
nbb = len(self.current_names)
|
||||||
|
nbpeople = 0
|
||||||
|
if nbb > 1:
|
||||||
|
message += _("You have already created multiple databases.")
|
||||||
|
if nbb == 1:
|
||||||
|
name = self.current_names[0][0]
|
||||||
|
bdir = self.current_names[0][1]
|
||||||
|
summary = self.get_dbdir_summary(bdir, name)
|
||||||
|
nbpeople = 0
|
||||||
|
for item in sorted(summary):
|
||||||
|
if item == "Number of people":
|
||||||
|
nbpeople = summary[item]
|
||||||
|
if nbpeople == 0:
|
||||||
|
message += _("You have nobody in your database '%s'" % name)
|
||||||
|
if nbb == 0:
|
||||||
|
message += _("You have no database.")
|
||||||
|
NoviceSelection(self, message, nbpeople, self.current_names)
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# NoviceSelection (First time)
|
||||||
|
#
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
class NoviceSelection(ManagedWindow, DbLoader):
|
||||||
|
"""
|
||||||
|
We select ....
|
||||||
|
"""
|
||||||
|
def __init__(self, dbmanager, message, nb_people, current_names):
|
||||||
|
"""
|
||||||
|
Novice Selection initialization
|
||||||
|
"""
|
||||||
|
self.dbmanager = dbmanager
|
||||||
|
self.uistate = dbmanager.uistate
|
||||||
|
self.dbstate = dbmanager.dbstate
|
||||||
|
self.nbb = nb_people
|
||||||
|
try:
|
||||||
|
ManagedWindow.__init__(self, self.uistate, [], NoviceSelection)
|
||||||
|
DbLoader.__init__(self, self.dbstate, self.uistate)
|
||||||
|
except WindowActiveError:
|
||||||
|
print("Novice error")
|
||||||
|
return
|
||||||
|
self.current_names = current_names
|
||||||
|
self.warning = False
|
||||||
|
dlg = Gtk.Dialog(title=_('Novice Selection'),
|
||||||
|
transient_for=self.uistate.window)
|
||||||
|
dlg.add_buttons(
|
||||||
|
Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.set_window(dlg, None, _('Novice Selection'), None)
|
||||||
|
mylabel = message
|
||||||
|
label = Gtk.Label(label=mylabel)
|
||||||
|
label.set_halign(Gtk.Align.START)
|
||||||
|
self.window.vbox.pack_start(label, False, True, 0)
|
||||||
|
label = Gtk.Label(label="")
|
||||||
|
self.window.vbox.pack_start(label, False, True, 0)
|
||||||
|
label1 = Gtk.Label(label=_("Your databases will be stored in"
|
||||||
|
" the following databases directory."))
|
||||||
|
label1.set_halign(Gtk.Align.START)
|
||||||
|
self.window.vbox.pack_start(label1, False, True, 0)
|
||||||
|
label2 = Gtk.Label(label="")
|
||||||
|
self.window.vbox.pack_start(label2, False, True, 0)
|
||||||
|
target = Gtk.Label(label=config.get('database.path'))
|
||||||
|
target.set_tooltip_text(_("The directory for the databases"))
|
||||||
|
target.set_halign(Gtk.Align.START)
|
||||||
|
self.window.vbox.pack_start(target, False, True, 0)
|
||||||
|
label3 = Gtk.Label(label="")
|
||||||
|
self.window.vbox.pack_start(label3, False, True, 0)
|
||||||
|
label4 = Gtk.Label()
|
||||||
|
label4.set_text(_("You can change the database directory above"
|
||||||
|
" using:\nEdit -> Preferences -> Family Tree"
|
||||||
|
"\nwith the 'Family Tree Database path' field."))
|
||||||
|
label4.set_halign(Gtk.Align.START)
|
||||||
|
self.window.vbox.pack_start(label4, False, True, 0)
|
||||||
|
label5 = Gtk.Label(label="")
|
||||||
|
self.window.vbox.pack_start(label5, False, True, 0)
|
||||||
|
label6 = Gtk.Label(label=_("Your database name. You can change it."))
|
||||||
|
label6.set_halign(Gtk.Align.START)
|
||||||
|
self.window.vbox.pack_start(label6, False, True, 0)
|
||||||
|
self.__targetname = Gtk.Entry()
|
||||||
|
self.nbb = len(self.current_names)
|
||||||
|
if self.nbb == 1:
|
||||||
|
name = self.current_names[0][0]
|
||||||
|
self.__targetname.set_text(name)
|
||||||
|
label6.set_text(_("You can't change the database name here."))
|
||||||
|
self.__targetname.set_sensitive(False)
|
||||||
|
if nb_people == 0:
|
||||||
|
label8 = Gtk.Label()
|
||||||
|
label8.set_text(_("Remove the database '%s' and retry."
|
||||||
|
% name))
|
||||||
|
label8.set_halign(Gtk.Align.START)
|
||||||
|
self.window.vbox.pack_start(label8, False, True, 0)
|
||||||
|
self.window.set_default_size(600, 300)
|
||||||
|
self.window.connect('response', self.start)
|
||||||
|
self.window.show_all()
|
||||||
|
self.show()
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
self.__targetname.set_text('My database')
|
||||||
|
dlg.add_buttons(
|
||||||
|
Gtk.STOCK_OK, Gtk.ResponseType.OK
|
||||||
|
)
|
||||||
|
self.__targetname.set_tooltip_text(_("The name of your database"))
|
||||||
|
self.window.vbox.pack_start(self.__targetname, False, True, 0)
|
||||||
|
label7 = Gtk.Label(label="")
|
||||||
|
self.window.vbox.pack_start(label7, False, True, 0)
|
||||||
|
load_db = Gtk.Button(label=_("Load a gedcom/gramps file?"))
|
||||||
|
load_db.set_tooltip_text(_("Click here if you want to load a gedcom/"
|
||||||
|
"gramps file."))
|
||||||
|
load_db.connect("clicked", self.load_database_selection)
|
||||||
|
load_db.set_halign(Gtk.Align.START)
|
||||||
|
self.window.vbox.pack_start(load_db, False, True, 0)
|
||||||
|
self.__target1 = Gtk.Entry()
|
||||||
|
self.__target1.set_text('')
|
||||||
|
self.__target1.set_tooltip_text(_("If you want to load a gedcom/"
|
||||||
|
"gramps file, select it here."))
|
||||||
|
self.window.vbox.pack_start(self.__target1, False, True, 0)
|
||||||
|
self.window.set_default_size(600, 300)
|
||||||
|
self.window.connect('response', self.start)
|
||||||
|
self.window.show_all()
|
||||||
|
self.show()
|
||||||
|
|
||||||
|
def start(self, obj, resp):
|
||||||
|
"""
|
||||||
|
Do we start the first gramps session ?
|
||||||
|
"""
|
||||||
|
if resp == Gtk.ResponseType.OK:
|
||||||
|
name = self.__targetname.get_text()
|
||||||
|
file_to_load = self.__target1.get_text()
|
||||||
|
if file_to_load == "":
|
||||||
|
try:
|
||||||
|
file_to_load = tempfile.mktemp(suffix=".gramps")
|
||||||
|
ftl = open(file_to_load, "wb")
|
||||||
|
except IOError as msg:
|
||||||
|
ErrorDialog(_("Default gedcom/gramps file for novice"),
|
||||||
|
_("Could not create %s: %s") % (file_to_load,
|
||||||
|
msg),
|
||||||
|
parent=self.uistate.window)
|
||||||
|
except:
|
||||||
|
ErrorDialog(_("Default gedcom/gramps file for novice"),
|
||||||
|
_("Could not create %s") % file_to_load,
|
||||||
|
parent=self.uistate.window)
|
||||||
|
|
||||||
|
ftl = open(file_to_load, "w", encoding='utf-8')
|
||||||
|
xml = FIRST_TIME_DEFAULT_FILE.format(
|
||||||
|
me=_("Me"),
|
||||||
|
partner1=_("Father/partner1"),
|
||||||
|
partner2=_("Mother/partner2"),
|
||||||
|
place1=_("Country"),
|
||||||
|
place2=_("County"),
|
||||||
|
place3=_("Place"),
|
||||||
|
place4=_("Second place")
|
||||||
|
)
|
||||||
|
ftl.write(xml)
|
||||||
|
ftl.close()
|
||||||
|
dbid = config.get('database.backend')
|
||||||
|
if self.nbb == 0:
|
||||||
|
self.dbmanager._create_new_db(dbid=dbid, title=name,
|
||||||
|
edit_entry=True)
|
||||||
|
db = open_database(name)
|
||||||
|
if db:
|
||||||
|
pmgr = GuiPluginManager.get_instance()
|
||||||
|
filen, extension = os.path.splitext(file_to_load)
|
||||||
|
extension = extension[1:] # remove the leading dot
|
||||||
|
for plugin in pmgr.get_import_plugins():
|
||||||
|
if extension == plugin.get_extension():
|
||||||
|
self.close()
|
||||||
|
importer = plugin.get_import_function()
|
||||||
|
importer(db, file_to_load,
|
||||||
|
User(callback=self._pulse_progress,
|
||||||
|
uistate=self.uistate,
|
||||||
|
dbstate=self.dbstate))
|
||||||
|
break
|
||||||
|
self.dbmanager.firsttime.set_sensitive(False)
|
||||||
|
os.unlink(file_to_load)
|
||||||
|
|
||||||
|
ManagedWindow.close(self, obj)
|
||||||
|
|
||||||
|
def load_database_selection(self, *arg):
|
||||||
|
"""
|
||||||
|
Select the gedcom/gramps file to load
|
||||||
|
"""
|
||||||
|
filtering = Gtk.FileFilter()
|
||||||
|
filtering.add_pattern("*.ged")
|
||||||
|
filtering.add_pattern("*.GED")
|
||||||
|
filtering.add_pattern("*.gramps")
|
||||||
|
fcd = Gtk.FileChooserDialog(transient_for=self.uistate.window)
|
||||||
|
fcd.set_title(_("Select your database gedcom/gramps file"))
|
||||||
|
fcd.add_buttons(_('_Cancel'), Gtk.ResponseType.CANCEL,
|
||||||
|
_('_Load'), Gtk.ResponseType.OK)
|
||||||
|
fcd.set_filter(filtering)
|
||||||
|
fcd.set_current_folder(USER_HOME)
|
||||||
|
|
||||||
|
status = fcd.run()
|
||||||
|
if status == Gtk.ResponseType.OK:
|
||||||
|
path = fcd.get_filename()
|
||||||
|
if path:
|
||||||
|
self.__target1.set_text(path)
|
||||||
|
fcd.destroy()
|
||||||
|
|
||||||
def drag_motion(wid, context, xpos, ypos, time_stamp):
|
def drag_motion(wid, context, xpos, ypos, time_stamp):
|
||||||
"""
|
"""
|
||||||
DND callback that is called on a DND drag motion begin
|
DND callback that is called on a DND drag motion begin
|
||||||
@@ -1095,8 +1440,6 @@ def find_revisions(name):
|
|||||||
del proc
|
del proc
|
||||||
return revlist
|
return revlist
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def check_out(dbase, rev, path, user):
|
def check_out(dbase, rev, path, user):
|
||||||
"""
|
"""
|
||||||
Checks out the revision from rcs, and loads the resulting XML file
|
Checks out the revision from rcs, and loads the resulting XML file
|
||||||
|
@@ -357,6 +357,22 @@
|
|||||||
<property name="position">7</property>
|
<property name="position">7</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="firsttime">
|
||||||
|
<property name="label" translatable="yes">_First Time</property>
|
||||||
|
<property name="use_action_appearance">False</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="can_default">True</property>
|
||||||
|
<property name="receives_default">False</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
<property name="position">7</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
|
Reference in New Issue
Block a user