Commit experimental QML interface, python gramps.py --qml to run
This is not part of Makefile system at the moment. Just proof of concept to see what can be done svn: r16505
This commit is contained in:
parent
9a2fd50642
commit
79d03159f3
29
src/guiQML/__init__.py
Normal file
29
src/guiQML/__init__.py
Normal file
@ -0,0 +1,29 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2010 Benny Malengier
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
"""
|
||||
Package init for the guiQML package.
|
||||
"""
|
||||
|
||||
# DO NOT IMPORT METHODS/CLASSES FROM src/guiQML HERE ! Only __all__
|
||||
|
||||
__all__ = [ ]
|
171
src/guiQML/grampsqml.py
Normal file
171
src/guiQML/grampsqml.py
Normal file
@ -0,0 +1,171 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2010 Benny Malengier
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
"""
|
||||
main file to start the QML application
|
||||
"""
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Standard python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import sys, os
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# set up logging
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import logging
|
||||
LOG = logging.getLogger(".grampsqml")
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GRAMPS modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import constfunc
|
||||
import config
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Main Gramps class
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class GrampsQML(object):
|
||||
"""
|
||||
Main class corresponding to a running gramps process.
|
||||
|
||||
There can be only one instance of this class per gramps application
|
||||
process. It may spawn several windows and control several databases.
|
||||
"""
|
||||
|
||||
def __init__(self, argparser):
|
||||
import DbState
|
||||
from guiQML.viewmanager import ViewManager
|
||||
from cli.arghandler import ArgHandler
|
||||
|
||||
from PySide import QtGui
|
||||
self.app = QtGui.QApplication(sys.argv)
|
||||
dbstate = DbState.DbState()
|
||||
self.vm = ViewManager(dbstate)
|
||||
|
||||
#act based on the given arguments
|
||||
ah = ArgHandler(dbstate, argparser, self.vm, self.argerrorfunc,
|
||||
gui=True)
|
||||
ah.handle_args_gui()
|
||||
if ah.open or ah.imp_db_path:
|
||||
# if we opened or imported something, only show the interface
|
||||
self.vm.post_init_interface()
|
||||
elif config.get('paths.recent-file') and config.get('behavior.autoload'):
|
||||
# if we need to autoload last seen file, do so
|
||||
filename = config.get('paths.recent-file')
|
||||
if os.path.isdir(filename) and \
|
||||
os.path.isfile(os.path.join(filename, "name.txt")) and \
|
||||
ah.check_db(filename):
|
||||
self.vm.open_activate(filename)
|
||||
self.vm.post_init_interface()
|
||||
else:
|
||||
self.vm.post_init_interface()
|
||||
else:
|
||||
# open without fam tree loaded
|
||||
self.vm.post_init_interface()
|
||||
|
||||
#start the QT loop
|
||||
self.app.exec_()
|
||||
|
||||
def argerrorfunc(self, string):
|
||||
from guiQML.questiondialog import ErrorDialog
|
||||
""" Show basic errors in argument handling in GUI fashion"""
|
||||
ErrorDialog(_("Error parsing arguments"), string)
|
||||
|
||||
def startqml(errors, argparser):
|
||||
"""
|
||||
Main startup function started via gobject.timeout_add
|
||||
First action inside the gtk loop
|
||||
"""
|
||||
from guiQML.questiondialog import ErrorDialog, run_dialog_standalone
|
||||
|
||||
#handle first existing errors in GUI fashion
|
||||
if errors:
|
||||
run_dialog_standalone(ErrorDialog,errors[0], errors[1])
|
||||
sys.exit()
|
||||
|
||||
if argparser.errors:
|
||||
run_dialog_standalone(ErrorDialog, argparser.errors[0],
|
||||
argparser.errors[1])
|
||||
sys.exit()
|
||||
|
||||
# add gui logger
|
||||
from GrampsLogger import RotateHandler
|
||||
form = logging.Formatter(fmt="%(relativeCreated)d: %(levelname)s: "
|
||||
"%(filename)s: line %(lineno)d: %(message)s")
|
||||
# Create the log handlers
|
||||
rh = RotateHandler(capacity=20)
|
||||
rh.setFormatter(form)
|
||||
# Only error and critical log records should
|
||||
# trigger the GUI handler.
|
||||
#qmlh = QMLHandler(rotate_handler=rh)
|
||||
#qmlh.setFormatter(form)
|
||||
#qmlh.setLevel(logging.ERROR)
|
||||
l = logging.getLogger()
|
||||
l.addHandler(rh)
|
||||
#l.addHandler(gmlh)
|
||||
|
||||
# start GRAMPS, errors stop the gtk loop
|
||||
try:
|
||||
quit_now = False
|
||||
openGL = True
|
||||
exit_code = 0
|
||||
if constfunc.has_display():
|
||||
GrampsQML(argparser)
|
||||
else:
|
||||
print("Gramps terminated because of no DISPLAY")
|
||||
sys.exit(exit_code)
|
||||
|
||||
except SystemExit, e:
|
||||
quit_now = True
|
||||
if e.code:
|
||||
exit_code = e.code
|
||||
LOG.error("Gramps terminated with exit code: %d." \
|
||||
% e.code, exc_info=True)
|
||||
except OSError, e:
|
||||
quit_now = True
|
||||
exit_code = e[0] or 1
|
||||
try:
|
||||
fn = e.filename
|
||||
except AttributeError:
|
||||
fn = ""
|
||||
LOG.error("Gramps terminated because of OS Error\n" +
|
||||
"Error details: %s %s" % (repr(e), fn), exc_info=True)
|
||||
|
||||
except:
|
||||
quit_now = True
|
||||
exit_code = 1
|
||||
LOG.error("Gramps failed to start.", exc_info=True)
|
||||
|
||||
if quit_now:
|
||||
#quit
|
||||
sys.exit(exit_code)
|
||||
|
||||
#function finished, return False to stop the timeout_add function calls
|
||||
return False
|
77
src/guiQML/qmlwidgets/TextButton.qml
Normal file
77
src/guiQML/qmlwidgets/TextButton.qml
Normal file
@ -0,0 +1,77 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the examples of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:BSD$
|
||||
** You may use this file under the terms of the BSD license as follows:
|
||||
**
|
||||
** "Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
|
||||
** the names of its contributors may be used to endorse or promote
|
||||
** products derived from this software without specific prior written
|
||||
** permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import Qt 4.7
|
||||
|
||||
Rectangle {
|
||||
id: container
|
||||
|
||||
property alias text: label.text
|
||||
|
||||
signal clicked
|
||||
|
||||
width: label.width + 20; height: label.height + 6
|
||||
smooth: true
|
||||
radius: 10
|
||||
|
||||
gradient: Gradient {
|
||||
GradientStop { id: gradientStop; position: 0.0; color: palette.light }
|
||||
GradientStop { position: 1.0; color: palette.button }
|
||||
}
|
||||
|
||||
SystemPalette { id: palette }
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
onClicked: { container.clicked() }
|
||||
}
|
||||
|
||||
Text {
|
||||
id: label
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
states: State {
|
||||
name: "pressed"
|
||||
when: mouseArea.pressed
|
||||
PropertyChanges { target: gradientStop; color: palette.dark }
|
||||
}
|
||||
}
|
44
src/guiQML/qmlwidgets/TopBar.qml
Normal file
44
src/guiQML/qmlwidgets/TopBar.qml
Normal file
@ -0,0 +1,44 @@
|
||||
/*#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2010 Benny Malengier
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id: __init__.py 13807 2009-12-15 05:56:12Z pez4brian $
|
||||
*/
|
||||
|
||||
import Qt 4.7
|
||||
|
||||
Item {
|
||||
id: titlebar
|
||||
|
||||
property alias text: titletext.text
|
||||
width: parent.width
|
||||
height: 20
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "#343434"
|
||||
}
|
||||
Text {
|
||||
id: titletext
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: text
|
||||
font.pixelSize: 15
|
||||
color: "white"
|
||||
font.bold: true
|
||||
}
|
||||
}
|
66
src/guiQML/questiondialog.py
Normal file
66
src/guiQML/questiondialog.py
Normal file
@ -0,0 +1,66 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2010 Benny Malengier
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id: __init__.py 13807 2009-12-15 05:56:12Z pez4brian
|
||||
|
||||
"""
|
||||
Some often needed dialogs
|
||||
"""
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Standard python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import sys
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# QT modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from PySide.QtCore import *
|
||||
from PySide.QtGui import *
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Classes for the Dialogs
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class ErrorDialog(QDialog):
|
||||
def __init__(self, msg1, msg2="", parent=None):
|
||||
super(ErrorDialog, self).__init__(parent)
|
||||
self.setWindowTitle("%s - Gramps" % msg1)
|
||||
lbl1 = QLabel(msg1)
|
||||
lbl2 = QLabel(msg2)
|
||||
layout = QVBoxLayout()
|
||||
layout.addWidget(lbl1)
|
||||
layout.addWidget(lbl2)
|
||||
# Set dialog layout
|
||||
self.setLayout(layout)
|
||||
self.setMinimumSize(350,300)
|
||||
self.show()
|
||||
|
||||
def run_dialog_standalone(dlgclass, *args, **keywords):
|
||||
app = QApplication(sys.argv)
|
||||
QObject.connect(app, SIGNAL('lastWindowClosed()'), app, SLOT('quit()'))
|
||||
|
||||
win = dlgclass(*args, **keywords)
|
||||
app.exec_()
|
156
src/guiQML/viewmanager.py
Normal file
156
src/guiQML/viewmanager.py
Normal file
@ -0,0 +1,156 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2010 Benny Malengier
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
"""
|
||||
The main view
|
||||
"""
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Constants
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
OPENGL = True
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Standard python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import sys, os
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# set up logging
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import logging
|
||||
LOG = logging.getLogger(".")
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# QT modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from PySide import QtCore
|
||||
from PySide import QtGui
|
||||
from PySide import QtDeclarative
|
||||
from PySide import QtOpenGL
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GRAMPS modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import const
|
||||
from cli.grampscli import CLIManager, CLIDbLoader
|
||||
from gen.ggettext import gettext as _
|
||||
from guiQML.views.dbman import DbManager
|
||||
from guiQML.questiondialog import ErrorDialog
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# ViewManager
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
class ViewManager(CLIManager):
|
||||
"""
|
||||
Manages main widget by holding what state it is in.
|
||||
"""
|
||||
def __init__(self, dbstate):
|
||||
"""
|
||||
The viewmanager is initialised with a dbstate on which GRAMPS is
|
||||
working.
|
||||
"""
|
||||
self.__centralview = None
|
||||
CLIManager.__init__(self, dbstate, False)
|
||||
self.db_loader = CLIDbLoader(self.dbstate)
|
||||
#there is one DeclarativeEngine for global settings
|
||||
self.__build_main_window()
|
||||
|
||||
def __build_main_window(self):
|
||||
"""
|
||||
Builds the QML interface
|
||||
"""
|
||||
self.mainwindow = QtGui.QMainWindow()
|
||||
self.mainview = QtDeclarative.QDeclarativeView()
|
||||
if OPENGL:
|
||||
glw = QtOpenGL.QGLWidget()
|
||||
self.mainview.setViewport(glw)
|
||||
self.mainview.setResizeMode(QtDeclarative.QDeclarativeView.SizeRootObjectToView)
|
||||
self.engine = self.mainview.engine()
|
||||
self.engine.rootContext().setBaseUrl(QtCore.QUrl.fromLocalFile(
|
||||
os.path.join(const.ROOT_DIR, "guiQML")))
|
||||
|
||||
#set up the family tree list to select from
|
||||
self.dbman = DbManager(self.dbstate, self.engine, self.load_db)
|
||||
|
||||
def post_init_interface(self):
|
||||
"""
|
||||
Showing the main window is deferred so that
|
||||
ArgHandler can work without it always shown
|
||||
"""
|
||||
if not self.dbstate.db.is_open():
|
||||
self.__open_dbman(None)
|
||||
else:
|
||||
self.__open_centralview(None)
|
||||
|
||||
def __open_dbman(self, obj):
|
||||
"""
|
||||
Called when the Open button is clicked, opens the DbManager
|
||||
"""
|
||||
self.dbman.show(self.mainview, self.mainwindow)
|
||||
|
||||
def _errordialog(self, title, errormessage):
|
||||
"""
|
||||
Show the error.
|
||||
In the GUI, the error is shown, and a return happens
|
||||
"""
|
||||
ErrorDialog(title, errormessage, parent=self.mainwindow)
|
||||
return 1
|
||||
|
||||
def load_db(self, path):
|
||||
"""
|
||||
Load the db and set the interface to the central widget
|
||||
"""
|
||||
self.db_loader.read_file(path)
|
||||
self.__open_centralview(None)
|
||||
|
||||
def __open_centralview(self, obj):
|
||||
"""
|
||||
set interface to the central widget
|
||||
"""
|
||||
if not self.__centralview:
|
||||
from guiQML.views.centralview import CentralView
|
||||
self.__centralview = CentralView(self.dbstate, self.engine,
|
||||
self.open_view)
|
||||
self.__centralview.show(self.mainview, self.mainwindow)
|
||||
|
||||
def open_view(self, viewclass, *args):
|
||||
"""
|
||||
set interface to the given view:
|
||||
"""
|
||||
##we should destroy views that are double
|
||||
##we should do some caching of views so as to move quickly?
|
||||
newview = viewclass(self.dbstate, self.engine, *args)
|
||||
newview.show(self.mainview, self.mainwindow)
|
29
src/guiQML/views/__init__.py
Normal file
29
src/guiQML/views/__init__.py
Normal file
@ -0,0 +1,29 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2010 Benny Malengier
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
"""
|
||||
Package init for different views in guiQML.
|
||||
"""
|
||||
|
||||
# DO NOT IMPORT METHODS/CLASSES FROM src/guiQML HERE ! Only __all__
|
||||
|
||||
__all__ = [ ]
|
174
src/guiQML/views/centralview.py
Normal file
174
src/guiQML/views/centralview.py
Normal file
@ -0,0 +1,174 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2010 Benny Malengier
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
"""
|
||||
The main view from where other views are started
|
||||
"""
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Constants
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Standard python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import sys, os
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# set up logging
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import logging
|
||||
LOG = logging.getLogger(".")
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# QT modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from PySide import QtCore
|
||||
from PySide import QtGui
|
||||
from PySide import QtDeclarative
|
||||
from PySide import QtOpenGL
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GRAMPS modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import const
|
||||
from gen.ggettext import gettext as _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Classes
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
class DetailView(QtCore.QObject):
|
||||
"""
|
||||
Data known about a detail view that can be launched
|
||||
"""
|
||||
def __init__(self, name):
|
||||
QtCore.QObject.__init__(self)
|
||||
self.__name = name
|
||||
|
||||
def _name(self):
|
||||
return self.__name
|
||||
|
||||
changed = QtCore.Signal()
|
||||
|
||||
#make Model.Column.property available in QML
|
||||
name = QtCore.Property(unicode, _name, notify=changed)
|
||||
|
||||
class DetViewSumModel(QtCore.QAbstractListModel):
|
||||
"""
|
||||
A simple ListModel for the different detailed views
|
||||
"""
|
||||
COLUMNS = ('name', )
|
||||
|
||||
def __init__(self, detviews):
|
||||
QtCore.QAbstractListModel.__init__(self)
|
||||
self._detviews = detviews
|
||||
self.setRoleNames(dict(enumerate(DetViewSumModel.COLUMNS)))
|
||||
|
||||
def rowCount(self, parent=QtCore.QModelIndex()):
|
||||
return len(self._detviews)
|
||||
|
||||
def data(self, index, role):
|
||||
print 'role', role, DetViewSumModel.COLUMNS.index('name')
|
||||
if index.isValid() and role == DetViewSumModel.COLUMNS.index('name'):
|
||||
return self._detviews[index.row()]
|
||||
return None
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# CentralView
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
class CentralView(QtCore.QObject):
|
||||
"""
|
||||
Manages family tree list widget
|
||||
"""
|
||||
def __init__(self, dbstate, engine, viewshow):
|
||||
"""
|
||||
The manager is initialised with a dbstate on which GRAMPS is
|
||||
working, and the engine to use context from.
|
||||
"""
|
||||
self.dbstate = dbstate
|
||||
self.__viewshow = viewshow
|
||||
QtCore.QObject.__init__(self)
|
||||
self.const = {
|
||||
'titlelabel': unicode("%s" % self.dbstate.db.get_dbname()),
|
||||
}
|
||||
print self.const['titlelabel']
|
||||
#there is one DeclarativeEngine for global settings
|
||||
self.__build_main_window(engine)
|
||||
|
||||
def __build_main_window(self, engine):
|
||||
"""
|
||||
Builds the QML interface
|
||||
"""
|
||||
parentcontext = engine.rootContext()
|
||||
#Create a context for the family tree list
|
||||
self.centralviewcontext = QtDeclarative.QDeclarativeContext(parentcontext)
|
||||
#Create ListModel to use
|
||||
detviews = DetViewSumModel([DetailView('People')])
|
||||
|
||||
#register them in the context
|
||||
self.centralviewcontext.setContextProperty('Const', self.const)
|
||||
self.centralviewcontext.setContextProperty('CentralView', self)
|
||||
self.centralviewcontext.setContextProperty('DetViewSumModel', detviews)
|
||||
|
||||
#create a Component to show
|
||||
self.centralview = QtDeclarative.QDeclarativeComponent(engine)
|
||||
self.centralview.loadUrl(QtCore.QUrl.fromLocalFile(
|
||||
os.path.join(const.ROOT_DIR, "guiQML", 'views', 'centralview.qml')))
|
||||
#and obtain the QObject of it
|
||||
self.Qcentralview = self.centralview.create(self.centralviewcontext)
|
||||
|
||||
def show(self, graphicsview, mainwindow):
|
||||
"""
|
||||
Paint the Component on the View and put it in the given mainwindow.
|
||||
"""
|
||||
#scene.addItem(self.Qfamtreeview)
|
||||
graphicsview.setRootObject(self.Qcentralview)
|
||||
graphicsview.show();
|
||||
mainwindow.setCentralWidget(graphicsview)
|
||||
mainwindow.show()
|
||||
|
||||
@QtCore.Slot(QtCore.QObject)
|
||||
def detviewSelected(self, detview):
|
||||
"""
|
||||
We load the selected family tree
|
||||
"""
|
||||
print 'User clicked on:', detview.name
|
||||
#now only Person piece to click on, so start that
|
||||
from guiQML.views.personview import QMLPersonList
|
||||
self.__viewshow(QMLPersonList)
|
65
src/guiQML/views/centralview.qml
Normal file
65
src/guiQML/views/centralview.qml
Normal file
@ -0,0 +1,65 @@
|
||||
/*#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2010 Benny Malengier
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id: __init__.py 13807 2009-12-15 05:56:12Z pez4brian $
|
||||
*/
|
||||
|
||||
import Qt 4.7
|
||||
|
||||
import "../qmlwidgets" as Widgets
|
||||
|
||||
Rectangle{
|
||||
id: container
|
||||
color: "#343434"
|
||||
ListView {
|
||||
id: detviewSumList
|
||||
y: 25
|
||||
width: parent.width
|
||||
height: parent.height-25
|
||||
model: DetViewSumModel
|
||||
delegate: Component {
|
||||
Rectangle {
|
||||
width: detviewSumList.width
|
||||
height: 40
|
||||
color: ((index % 2 == 0)?'#222':'#111')
|
||||
Text {
|
||||
id: detviewname
|
||||
elide: Text.ElideRight
|
||||
text: model.name.name
|
||||
color: 'white'
|
||||
font.bold: true
|
||||
anchors.leftMargin: 10
|
||||
anchors.fill: parent
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
CentralView.detviewSelected(model.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// TOP BAR
|
||||
Widgets.TopBar {
|
||||
text: Const.titlelabel
|
||||
}
|
||||
}
|
225
src/guiQML/views/dbman.py
Normal file
225
src/guiQML/views/dbman.py
Normal file
@ -0,0 +1,225 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2010 Benny Malengier
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
"""
|
||||
The main view
|
||||
"""
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Constants
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
OPENGL = True
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Standard python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import sys, os
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# set up logging
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import logging
|
||||
LOG = logging.getLogger(".")
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# QT modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from PySide import QtCore
|
||||
from PySide import QtGui
|
||||
from PySide import QtDeclarative
|
||||
from PySide import QtOpenGL
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GRAMPS modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import const
|
||||
from cli.clidbman import CLIDbManager, NAME_FILE, time_val
|
||||
from gen.ggettext import gettext as _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Classes
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
#open_icon = QtGui.QIcon.fromTheme('open')
|
||||
FAMTREE_ICONPATH = os.path.join(const.IMAGE_DIR, '22x22', 'gramps.png')
|
||||
|
||||
class FamTreeWrapper(QtCore.QObject):
|
||||
"""
|
||||
A QObject wrapper
|
||||
"""
|
||||
def __init__(self, thing, dbman):
|
||||
QtCore.QObject.__init__(self)
|
||||
self.__dbman = dbman
|
||||
self.__name = thing[CLIDbManager.IND_NAME]
|
||||
self.__path = thing[CLIDbManager.IND_PATH]
|
||||
self.__path_namefile = thing[CLIDbManager.IND_PATH_NAMEFILE]
|
||||
self.__last_access = thing[CLIDbManager.IND_TVAL_STR]
|
||||
self.__use_icon = thing[CLIDbManager.IND_USE_ICON_BOOL]
|
||||
self.__icon = thing[CLIDbManager.IND_STOCK_ID]
|
||||
|
||||
changed = QtCore.Signal()
|
||||
changed_name = QtCore.Signal()
|
||||
|
||||
def _name(self): return self.__name
|
||||
def _path(self): return self.__path
|
||||
def _last_access(self): return self.__last_access
|
||||
def _use_icon(self): return self.__use_icon
|
||||
def _icon(self): return self.__icon
|
||||
|
||||
def _set_name(self, name):
|
||||
self.__name = name
|
||||
self.__dbman.rename_database(self.__path_namefile, name)
|
||||
self.changed_name.emit()
|
||||
|
||||
name = QtCore.Property(unicode, _name, _set_name, notify=changed_name)
|
||||
path = QtCore.Property(unicode, _path, notify=changed)
|
||||
last_access = QtCore.Property(unicode, _last_access, notify=changed)
|
||||
use_icon = QtCore.Property(bool, _use_icon, notify=changed)
|
||||
icon = QtCore.Property(unicode, _icon, notify=changed)
|
||||
|
||||
class FamTreeListModel(QtCore.QAbstractListModel):
|
||||
"""
|
||||
A simple ListModel
|
||||
"""
|
||||
COLUMNS = ('name', 'path', 'last_access', 'use_icon', 'icon')
|
||||
|
||||
def __init__(self, famtrees):
|
||||
QtCore.QAbstractListModel.__init__(self)
|
||||
self._famtrees = famtrees
|
||||
self.setRoleNames(dict(enumerate(FamTreeListModel.COLUMNS)))
|
||||
|
||||
def rowCount(self, parent=QtCore.QModelIndex()):
|
||||
return len(self._famtrees)
|
||||
|
||||
def data(self, index, role):
|
||||
if index.isValid() and role == FamTreeListModel.COLUMNS.index('name'):
|
||||
return self._famtrees[index.row()]
|
||||
return None
|
||||
|
||||
def append_famtree(self, famtree):
|
||||
"""
|
||||
Append a FamTreeWrapper to the family tree litsmodel
|
||||
"""
|
||||
self.beginInsertRows(QtCore.QModelIndex(), self.rowCount(), self.rowCount())
|
||||
self._famtrees.append(famtree)
|
||||
self.endInsertRows()
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# DbManager
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
class DbManager(CLIDbManager, QtCore.QObject):
|
||||
"""
|
||||
Manages family tree list widget
|
||||
"""
|
||||
def __init__(self, dbstate, engine, onselectcallback):
|
||||
"""
|
||||
The manager is initialised with a dbstate on which GRAMPS is
|
||||
working, and the engine to use context from.
|
||||
"""
|
||||
self.__busy = False
|
||||
self.__onselect = onselectcallback
|
||||
QtCore.QObject.__init__(self)
|
||||
CLIDbManager.__init__(self, dbstate)
|
||||
#constants needed in the QML
|
||||
self.const = {
|
||||
'titlelabel': "Gramps - %s" % _("Family Trees"),
|
||||
'addbtnlbl': _("Add a Family Tree"),
|
||||
'famtreeicon': FAMTREE_ICONPATH
|
||||
}
|
||||
#there is one DeclarativeEngine for global settings
|
||||
self.__build_main_window(engine)
|
||||
|
||||
def __build_main_window(self, engine):
|
||||
"""
|
||||
Builds the QML interface
|
||||
"""
|
||||
parentcontext = engine.rootContext()
|
||||
#Create a context for the family tree list
|
||||
self.famtreecontext = QtDeclarative.QDeclarativeContext(parentcontext)
|
||||
#Create ListModel to use
|
||||
famtreesQT = [FamTreeWrapper(obj, self) for obj in self.current_names]
|
||||
self.famtrees = FamTreeListModel(famtreesQT)
|
||||
|
||||
#register them in the context
|
||||
self.famtreecontext.setContextProperty('Const', self.const)
|
||||
self.famtreecontext.setContextProperty('DbManager', self)
|
||||
self.famtreecontext.setContextProperty('FamTreeListModel', self.famtrees)
|
||||
|
||||
#create a Component to show
|
||||
self.famtreeview = QtDeclarative.QDeclarativeComponent(engine)
|
||||
self.famtreeview.loadUrl(QtCore.QUrl.fromLocalFile(
|
||||
os.path.join(const.ROOT_DIR, "guiQML", 'views', 'dbman.qml')))
|
||||
#and obtain the QObject of it
|
||||
self.Qfamtreeview = self.famtreeview.create(self.famtreecontext)
|
||||
|
||||
def show(self, graphicsview, mainwindow):
|
||||
"""
|
||||
Paint the Component on the View and put it in the given mainwindow.
|
||||
"""
|
||||
#scene.addItem(self.Qfamtreeview)
|
||||
graphicsview.setRootObject(self.Qfamtreeview)
|
||||
graphicsview.show();
|
||||
mainwindow.setCentralWidget(graphicsview)
|
||||
mainwindow.show()
|
||||
|
||||
@QtCore.Slot(QtCore.QObject)
|
||||
def famtreeSelected(self, wrapper):
|
||||
"""
|
||||
We load the selected family tree
|
||||
"""
|
||||
if self.__busy:
|
||||
return
|
||||
self.__busy = True
|
||||
self.__onselect(wrapper._path())
|
||||
self.__busy = False
|
||||
|
||||
@QtCore.Slot(QtCore.QObject)
|
||||
def addfamtree(self, _):
|
||||
"""
|
||||
We add a family tree
|
||||
"""
|
||||
if self.__busy:
|
||||
return
|
||||
self.__busy = True
|
||||
print 'User clicked on:', 'add fam tree'
|
||||
new_path, title = self.create_new_db_cli(None)
|
||||
path_name = os.path.join(new_path, NAME_FILE)
|
||||
(tval, last) = time_val(new_path)
|
||||
self.famtrees.append_famtree(FamTreeWrapper([title, new_path, path_name,
|
||||
last, tval, False, '']))
|
||||
self.__busy = False
|
||||
|
200
src/guiQML/views/dbman.qml
Normal file
200
src/guiQML/views/dbman.qml
Normal file
@ -0,0 +1,200 @@
|
||||
/*#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2010 Benny Malengier
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id: __init__.py 13807 2009-12-15 05:56:12Z pez4brian $
|
||||
*/
|
||||
|
||||
import Qt 4.7
|
||||
|
||||
import "../qmlwidgets" as Widgets
|
||||
|
||||
Rectangle{
|
||||
id: container
|
||||
color: "#343434"
|
||||
width: 400
|
||||
height: 600
|
||||
|
||||
//Delegate for a famtree entry. Two modes:
|
||||
// 1. List mode (default): shows just the name and allows selection
|
||||
// 2. Details mode: show extra information
|
||||
Component {
|
||||
id: famtreeDelegate
|
||||
Item {
|
||||
id: famtree
|
||||
// Create a property to contain the visibility of the details.
|
||||
// We bind multiple element's opacity to this one property,
|
||||
property real detailsOpacity : 0
|
||||
|
||||
width: pythonList.width
|
||||
height: 30
|
||||
|
||||
Rectangle {
|
||||
id: background
|
||||
anchors.fill: parent
|
||||
color: ((index % 2 == 0)?'#222':'#111')
|
||||
radius: 5 //rounded corners
|
||||
}
|
||||
//click shows details, close button must be clicked to go back to normal
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
famtree.state = 'Details'
|
||||
}
|
||||
}
|
||||
//Now the data on the background, detailsOpacity for what to see
|
||||
Row{
|
||||
id: topfamtreelayout
|
||||
width: parent.width
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
x:10
|
||||
spacing:10
|
||||
Column {
|
||||
id: innerfamtreecol
|
||||
width: parent.width - 70;
|
||||
spacing: 5
|
||||
Text {
|
||||
id: title
|
||||
text: model.name.name
|
||||
color: 'white'
|
||||
font.bold: true
|
||||
opacity: (famtree.detailsOpacity ? 0 : 1 )
|
||||
}
|
||||
Item {
|
||||
id: titleEdit
|
||||
height: 20
|
||||
width: parent.width
|
||||
opacity: famtree.detailsOpacity
|
||||
|
||||
TextInput {
|
||||
id: titleinput
|
||||
text: model.name.name
|
||||
anchors.fill: parent.fill
|
||||
color: 'white'
|
||||
cursorVisible: true; font.bold: true
|
||||
}
|
||||
Keys.forwardTo: [(returnKey), (titleinput)]
|
||||
Item {
|
||||
id: returnKey
|
||||
Keys.onReturnPressed: model.name.name = titleinput.text
|
||||
Keys.onEnterPressed: model.name.name = titleinput.text
|
||||
Keys.onEscapePressed: titleinput.text = model.name.name
|
||||
}
|
||||
}
|
||||
Text {
|
||||
id: lastaccess
|
||||
elide: Text.ElideRight
|
||||
text: model.name.last_access
|
||||
color: 'white'
|
||||
font.bold: true
|
||||
opacity: famtree.detailsOpacity
|
||||
}
|
||||
}
|
||||
Image {
|
||||
id:famtreeimage
|
||||
anchors.verticalCenter: topfamtreelayout.verticalCenter
|
||||
width: 22; height: 22
|
||||
anchors.rightMargin: 20
|
||||
source: Const.famtreeicon
|
||||
opacity: famtree.detailsOpacity
|
||||
}
|
||||
}
|
||||
Row{
|
||||
id: buttonfamtreelayout
|
||||
anchors.top: topfamtreelayout.bottom
|
||||
anchors.rightMargin: 20
|
||||
spacing: 20
|
||||
// A button to select the famtree
|
||||
Widgets.TextButton {
|
||||
y: 10
|
||||
opacity: famtree.detailsOpacity
|
||||
text: "Open"
|
||||
onClicked: {
|
||||
DbManager.famtreeSelected(model.name)
|
||||
}
|
||||
}// A button to close the detailed view, i.e. set the state back to default ('').
|
||||
Widgets.TextButton {
|
||||
y: 10
|
||||
opacity: famtree.detailsOpacity
|
||||
text: "Close"
|
||||
onClicked: famtree.state = '';
|
||||
}
|
||||
}
|
||||
|
||||
states: State {
|
||||
name: "Details"
|
||||
PropertyChanges { target: famtree; detailsOpacity: 1; x: 0 } // Make details visible
|
||||
PropertyChanges { target: famtree; height: 120 } // Fill the entire list area with the detailed view
|
||||
|
||||
// Move the list so that this item is at the top.
|
||||
PropertyChanges { target: famtree.ListView.view; explicit: true; contentY: famtree.y }
|
||||
|
||||
// Disallow flicking while in in detailed view
|
||||
PropertyChanges { target: famtree.ListView.view; interactive: false }
|
||||
}
|
||||
|
||||
transitions: Transition {
|
||||
// Make the state changes smooth
|
||||
ParallelAnimation {
|
||||
ColorAnimation { property: "color"; duration: 500 }
|
||||
NumberAnimation { duration: 300; properties: "detailsOpacity,x,contentY,height,width" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ListView {
|
||||
id: pythonList
|
||||
y: 25
|
||||
width: parent.width
|
||||
height: parent.height-20-40
|
||||
//anchors.top: container.top
|
||||
//anchors.bottom: container.bottom
|
||||
//anchors.fill: parent
|
||||
//anchors.leftMargin: 5
|
||||
//anchors.rightMargin: 5
|
||||
model: FamTreeListModel
|
||||
delegate: famtreeDelegate
|
||||
}
|
||||
// TOP BAR
|
||||
Widgets.TopBar {
|
||||
text: Const.titlelabel
|
||||
}
|
||||
// BOTTOM BAR
|
||||
Item {
|
||||
id: bottombar
|
||||
y: parent.height-40
|
||||
width: parent.width
|
||||
height: 40
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "#343434"
|
||||
}
|
||||
Row {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 10
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: 10
|
||||
Widgets.TextButton {
|
||||
text: Const.addbtnlbl
|
||||
onClicked: {DbManager.addfamtree("")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
66
src/guiQML/views/peopleview.qml
Normal file
66
src/guiQML/views/peopleview.qml
Normal file
@ -0,0 +1,66 @@
|
||||
/*#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2010 Benny Malengier
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id: __init__.py 13807 2009-12-15 05:56:12Z pez4brian $
|
||||
*/
|
||||
|
||||
import Qt 4.7
|
||||
|
||||
import "../qmlwidgets" as Widgets
|
||||
|
||||
Rectangle{
|
||||
id: container
|
||||
color: "#343434"
|
||||
ListView {
|
||||
id: personlist
|
||||
y: 25
|
||||
width: parent.width
|
||||
height: parent.height-25
|
||||
model: QMLPersonListModel
|
||||
delegate: Component {
|
||||
Rectangle {
|
||||
width: personlist.width
|
||||
height: 40
|
||||
radius: 10
|
||||
color: ((index % 2 == 0)?'#222':'#111')
|
||||
Text {
|
||||
id: personname
|
||||
elide: Text.ElideRight
|
||||
text: model.name.name
|
||||
color: 'white'
|
||||
font.bold: true
|
||||
anchors.leftMargin: 15
|
||||
anchors.fill: parent
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
QMLPersonList.detailsSelected(model.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// TOP BAR
|
||||
Widgets.TopBar {
|
||||
text: Const.titlelabel
|
||||
}
|
||||
}
|
214
src/guiQML/views/personview.py
Normal file
214
src/guiQML/views/personview.py
Normal file
@ -0,0 +1,214 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2010 Benny Malengier
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
"""
|
||||
The listview with all people in the database
|
||||
"""
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Standard python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import sys, os
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# set up logging
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import logging
|
||||
LOG = logging.getLogger(".")
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# QT modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from PySide import QtCore
|
||||
from PySide import QtGui
|
||||
from PySide import QtDeclarative
|
||||
from PySide import QtOpenGL
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GRAMPS modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import const
|
||||
from Utils import conv_unicode_tosrtkey_ongtk
|
||||
from gen.ggettext import gettext as _
|
||||
from gen.display.name import displayer as name_displayer
|
||||
from gen.lib import Name
|
||||
##TODO: follow must be refractored so as not to require GTK
|
||||
from gui.views.treemodels.flatbasemodel import FlatNodeMap
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Classes
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
## Copied from gui/views/models/peoplemodel, we need a GTK independent base!
|
||||
COLUMN_NAME = 3
|
||||
|
||||
class QMLPerson(QtCore.QObject):
|
||||
"""
|
||||
Person object encapsulated for QML
|
||||
We only store handle and ref to database, obtain data from db as needed
|
||||
"""
|
||||
def __init__(self, db, personhandle):
|
||||
QtCore.QObject.__init__(self)
|
||||
self.__handle = personhandle
|
||||
self.__db = db
|
||||
|
||||
def _name(self):
|
||||
return name_displayer.display(self.__db.get_person_from_handle(self.__handle))
|
||||
|
||||
#dummy signal for things that change must not be tracked
|
||||
dummychanged = QtCore.Signal()
|
||||
|
||||
#make Model.Column.property available in QML
|
||||
name = QtCore.Property(unicode, _name, notify=dummychanged)
|
||||
|
||||
class QMLPersonListModel(QtCore.QAbstractListModel):
|
||||
"""
|
||||
A simple ListModel for the People in the database
|
||||
"""
|
||||
ROLE_NAME_COL = 0
|
||||
COLUMNS = ((ROLE_NAME_COL, 'name'), )
|
||||
|
||||
def __init__(self, db):
|
||||
QtCore.QAbstractListModel.__init__(self)
|
||||
self.__db = db
|
||||
self.gen_cursor = db.get_person_cursor
|
||||
self.sort_func = self.sort_name
|
||||
self.node_map = FlatNodeMap()
|
||||
self._reverse = False
|
||||
#build node map with all peopls
|
||||
allkeys = self.sort_keys()
|
||||
ident = True
|
||||
dlist = allkeys
|
||||
self.node_map.set_path_map(dlist, allkeys, identical=ident,
|
||||
reverse=self._reverse)
|
||||
|
||||
#every column has a role from 0 to nrcol-1, and name as in COLUMNS
|
||||
self.setRoleNames(dict(QMLPersonListModel.COLUMNS))
|
||||
#we create an array with all the QMLPerson that we need so
|
||||
#that we can match a rowindex with correct QMLPerson
|
||||
self._qmlpersons = []
|
||||
for _, handle in self.node_map.full_srtkey_hndl_map():
|
||||
self._qmlpersons.append(QMLPerson(self.__db, handle))
|
||||
|
||||
def sort_keys(self):
|
||||
"""
|
||||
Return the (sort_key, handle) list of all data that can maximally
|
||||
be shown.
|
||||
This list is sorted ascending, via localized string sort.
|
||||
conv_unicode_tosrtkey_ongtk which uses strxfrm, which is apparently
|
||||
broken in Win ?? --> they should fix base lib, we need strxfrm, fix it
|
||||
in the Utils module.
|
||||
"""
|
||||
# use cursor as a context manager
|
||||
with self.gen_cursor() as cursor:
|
||||
#loop over database and store the sort field, and the handle
|
||||
return sorted((map(conv_unicode_tosrtkey_ongtk,
|
||||
self.sort_func(data)), key) for key, data in cursor)
|
||||
|
||||
def sort_name(self, data):
|
||||
n = Name()
|
||||
n.unserialize(data[COLUMN_NAME])
|
||||
return (n.get_primary_surname().get_surname(), n.get_first_name())
|
||||
|
||||
def rowCount(self, parent=QtCore.QModelIndex()):
|
||||
return self.__db.get_number_of_people()
|
||||
|
||||
def data(self, index, role):
|
||||
"""
|
||||
Obtain QMLPerson to show. Role is a number that corresponds to a column,
|
||||
different columns can obtain data from different objects
|
||||
"""
|
||||
if index.isValid() and role <= QMLPersonListModel.ROLE_NAME_COL:
|
||||
return self._qmlpersons[index.row()]
|
||||
return None
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# CentralView
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
class QMLPersonList(QtCore.QObject):
|
||||
"""
|
||||
Manages family tree list widget
|
||||
"""
|
||||
def __init__(self, dbstate, engine):
|
||||
"""
|
||||
The manager is initialised with a dbstate on which GRAMPS is
|
||||
working, and the engine to use context from.
|
||||
"""
|
||||
self.dbstate = dbstate
|
||||
QtCore.QObject.__init__(self)
|
||||
self.const = {
|
||||
'titlelabel': "%s" % self.dbstate.db.get_dbname(),
|
||||
}
|
||||
#there is one DeclarativeEngine for global settings
|
||||
self.__build_main_window(engine)
|
||||
|
||||
def __build_main_window(self, engine):
|
||||
"""
|
||||
Builds the QML interface
|
||||
"""
|
||||
parentcontext = engine.rootContext()
|
||||
#Create a context for the family tree list
|
||||
self.qmlpersonlistcontext = QtDeclarative.QDeclarativeContext(parentcontext)
|
||||
#Create ListModel to use
|
||||
personlistmodel = QMLPersonListModel(self.dbstate.db)
|
||||
|
||||
#register them in the context
|
||||
self.qmlpersonlistcontext.setContextProperty('Const', self.const)
|
||||
self.qmlpersonlistcontext.setContextProperty('QMLPersonList', self)
|
||||
self.qmlpersonlistcontext.setContextProperty('QMLPersonListModel', personlistmodel)
|
||||
|
||||
#create a Component to show
|
||||
self.qmlpersonlist = QtDeclarative.QDeclarativeComponent(engine)
|
||||
self.qmlpersonlist.loadUrl(QtCore.QUrl.fromLocalFile(
|
||||
os.path.join(const.ROOT_DIR, "guiQML", 'views', 'peopleview.qml')))
|
||||
#and obtain the QObject of it
|
||||
self.Qpersonlist = self.qmlpersonlist.create(self.qmlpersonlistcontext)
|
||||
|
||||
def show(self, graphicsview, mainwindow):
|
||||
"""
|
||||
Paint the Component on the View and put it in the given mainwindow.
|
||||
"""
|
||||
#scene.addItem(self.Qfamtreeview)
|
||||
graphicsview.setRootObject(self.Qpersonlist)
|
||||
graphicsview.show();
|
||||
mainwindow.setCentralWidget(graphicsview)
|
||||
mainwindow.show()
|
||||
|
||||
@QtCore.Slot(QtCore.QObject)
|
||||
def detailsSelected(self, qmlperson):
|
||||
"""
|
||||
We load the selected family tree
|
||||
"""
|
||||
print 'User clicked on:', qmlperson.name
|
Loading…
Reference in New Issue
Block a user