[qet] [1329] Implemented a SQLite-based cache to speed up the elements panel loading.

[ Thread Index | Date Index | More lists.tuxfamily.org/qet Archives ]


Revision: 1329
Author:   xavier
Date:     2011-09-13 23:46:10 +0200 (Tue, 13 Sep 2011)
Log Message:
-----------
Implemented a SQLite-based cache to speed up the elements panel loading.

Modified Paths:
--------------
    branches/0.3/qelectrotech.pro
    branches/0.3/sources/elementdefinition.h
    branches/0.3/sources/elementscollection.h
    branches/0.3/sources/elementspanel.cpp
    branches/0.3/sources/elementspanel.h
    branches/0.3/sources/fileelementdefinition.cpp
    branches/0.3/sources/fileelementdefinition.h
    branches/0.3/sources/fileelementscollection.cpp
    branches/0.3/sources/fileelementscollection.h
    branches/0.3/sources/xmlelementdefinition.cpp
    branches/0.3/sources/xmlelementdefinition.h
    branches/0.3/sources/xmlelementscollection.cpp
    branches/0.3/sources/xmlelementscollection.h

Added Paths:
-----------
    branches/0.3/sources/elementscollectioncache.cpp
    branches/0.3/sources/elementscollectioncache.h

Modified: branches/0.3/qelectrotech.pro
===================================================================
--- branches/0.3/qelectrotech.pro	2011-09-13 17:13:10 UTC (rev 1328)
+++ branches/0.3/qelectrotech.pro	2011-09-13 21:46:10 UTC (rev 1329)
@@ -71,7 +71,7 @@
 TRANSLATIONS +=                lang/qt_es.ts  lang/qt_fr.ts  lang/qt_ru.ts  lang/qt_pt.ts  lang/qt_cs.ts  lang/qt_pl.ts  lang/qt_de.ts                 lang/qt_it.ts
 
 # Modules Qt utilises par l'application
-QT += xml svg network
+QT += xml svg network sql
 
 # Configuration de la compilation
 CONFIG += debug_and_release warn_on

Modified: branches/0.3/sources/elementdefinition.h
===================================================================
--- branches/0.3/sources/elementdefinition.h	2011-09-13 17:13:10 UTC (rev 1328)
+++ branches/0.3/sources/elementdefinition.h	2011-09-13 21:46:10 UTC (rev 1329)
@@ -117,6 +117,7 @@
 	virtual ElementDefinition *toElement();
 	virtual bool equals(ElementDefinition &);
 	virtual bool removeContent();
+	virtual QDateTime modificationTime() const = 0;
 	void copy(MoveElementsDescription *);
 	void move(MoveElementsDescription *);
 	

Modified: branches/0.3/sources/elementscollection.h
===================================================================
--- branches/0.3/sources/elementscollection.h	2011-09-13 17:13:10 UTC (rev 1328)
+++ branches/0.3/sources/elementscollection.h	2011-09-13 21:46:10 UTC (rev 1329)
@@ -74,6 +74,7 @@
 	virtual ElementDefinition *createElement(const QString &);
 	virtual bool isEmpty();
 	virtual int count();
+	virtual bool isCacheable() const = 0;
 	
 	// Methodes propres a la classe ElementsCollection
 	public:

Added: branches/0.3/sources/elementscollectioncache.cpp
===================================================================
--- branches/0.3/sources/elementscollectioncache.cpp	                        (rev 0)
+++ branches/0.3/sources/elementscollectioncache.cpp	2011-09-13 21:46:10 UTC (rev 1329)
@@ -0,0 +1,267 @@
+#include "elementscollectioncache.h"
+#include "elementscollection.h"
+#include "elementscategory.h"
+#include "elementdefinition.h"
+#include "customelement.h"
+
+/**
+	Construct a cache for elements collections.
+	@param database_path Path of the SQLite database to open.
+	@param parent Parent QObject
+*/
+ElementsCollectionCache::ElementsCollectionCache(const QString &database_path, QObject *parent) :
+	QObject(parent),
+	locale_("en"),
+	pixmap_storage_format_("PNG")
+{
+	// initialize the cache SQLite database
+	static int cache_instances = 0;
+	QString connection_name = QString("ElementsCollectionCache-%1").arg(cache_instances++);
+	cache_db_ = QSqlDatabase::addDatabase("QSQLITE", connection_name );
+	cache_db_.setDatabaseName(database_path);
+	if (!cache_db_.open()) {
+		qDebug() << "Unable to open the SQLite database " << database_path << " as " << connection_name << ": " << cache_db_.lastError();
+	} else {
+		cache_db_.exec("PRAGMA temp_store=MEMORY");
+		cache_db_.exec("PRAGMA journal_mode = MEMORY");
+		cache_db_.exec("PRAGMA synchronous=OFF");
+		cache_db_.exec("PRAGMA cache_size=10000");
+		/// @todo the tables could already exist, handle that case.
+		cache_db_.exec("CREATE TABLE names (path VARCHAR(512) NOT NULL, locale VARCHAR(2) NOT NULL, mtime DATETIME NOT NULL, name VARCHAR(128), PRIMARY KEY(path, locale));");
+		cache_db_.exec("CREATE TABLE pixmaps (path VARCHAR(512) NOT NULL UNIQUE, mtime DATETIME NOT NULL, pixmap BLOB, PRIMARY KEY(path), FOREIGN KEY(path) REFERENCES names (path) ON DELETE CASCADE);");
+		
+		// prepare queries
+		select_name_   = new QSqlQuery(cache_db_);
+		select_pixmap_ = new QSqlQuery(cache_db_);
+		insert_name_   = new QSqlQuery(cache_db_);
+		insert_pixmap_ = new QSqlQuery(cache_db_);
+		select_name_   -> prepare("SELECT name FROM names WHERE path = :path AND locale = :locale AND mtime > :file_mtime");
+		select_pixmap_ -> prepare("SELECT pixmap FROM pixmaps WHERE path = :path AND mtime > :file_mtime");
+		insert_name_   -> prepare("REPLACE INTO names (path, locale, mtime, name) VALUES (:path, :locale, :mtime, :name)");
+		insert_pixmap_ -> prepare("REPLACE INTO pixmaps (path, mtime, pixmap) VALUES (:path, :mtime, :pixmap)");
+	}
+}
+
+/**
+	Destructor
+*/
+ElementsCollectionCache::~ElementsCollectionCache() {
+	cache_db_.close();
+}
+
+/**
+	Define the locale to be used when dealing with names.
+	@param locale New locale to be used.
+*/
+void ElementsCollectionCache::setLocale(const QString &locale) {
+	locale_ = locale;
+}
+
+/**
+	@return The locale to be used when dealing with names.
+*/
+QString ElementsCollectionCache::locale() const {
+	return(locale_);
+}
+
+/**
+	Define the storage format for the pixmaps within the SQLite database. See
+	Qt's QPixmap documentation for more information.
+	@param format The new pixmap storage format.
+	@return True if the format change was accepted, false otherwise.
+*/
+bool ElementsCollectionCache::setPixmapStorageFormat(const QString &format) {
+	if (QImageWriter::supportedImageFormats().contains(format.toAscii())) { 
+		pixmap_storage_format_= format;
+		return(true);
+	}
+	return(false);
+}
+
+/**
+	@return the pixmap storage format. Default is "PNG"
+	@see setPixmapStorageFormat()
+*/
+QString ElementsCollectionCache::pixmapStorageFormat() const {
+	return(pixmap_storage_format_);
+}
+
+/**
+	Indicate the cache a new collection is about to be browsed. This is mainly
+	used to delimit database transactions.
+	@param collection The elements collection about to be browsed.
+*/
+void ElementsCollectionCache::beginCollection(ElementsCollection *collection) {
+	bool use_cache = cache_db_.isOpen() && collection -> isCacheable();
+	if (use_cache) {
+		bool transaction_started = cache_db_.transaction();
+		qDebug() << (transaction_started ? "transaction began for " : "transaction not started for ") << collection -> protocol();
+	}
+}
+
+/**
+	Indicate the cache the currently browsed collection end has been reached. This
+	is mainly used to delimit database transactions.
+	@param collection The elements collection being browsed.
+*/
+void ElementsCollectionCache::endCollection(ElementsCollection *collection) {
+	bool use_cache = cache_db_.isOpen() && collection -> isCacheable();
+	if (use_cache) {
+		bool transaction_commited = cache_db_.commit();
+		qDebug() << (transaction_commited ? "transaction commited for " : "transaction not commited for") << collection -> protocol();
+	}
+}
+
+/**
+	Retrieve the data for a given element, using the cache if available,
+	filling it otherwise. Data are then available through pixmap() and name()
+	methods.
+	@param element The definition of an element.
+	@see pixmap()
+	@see name()
+	@return True if the retrieval succeeded, false otherwise.
+*/
+bool ElementsCollectionCache::fetchElement(ElementDefinition *element) {
+	// can we use the cache with this element?
+	bool use_cache = cache_db_.isOpen() && element -> parentCollection() -> isCacheable();
+	
+	// attempt to fetch the element name from the cache database
+	if (!use_cache) {
+		return(fetchData(element -> location()));
+	} else {
+		QString element_path = element -> location().toString();
+		bool got_name   = fetchNameFromCache(element_path, element -> modificationTime());
+		bool got_pixmap = fetchPixmapFromCache(element_path, element -> modificationTime());
+		if (got_name && got_pixmap) {
+			return(true);
+		}
+		if (fetchData(element -> location())) {
+			cacheName(element_path);
+			cachePixmap(element_path);
+		}
+		return(true);
+	}
+}
+
+/**
+	@return The last name fetched through fetchElement().
+*/
+QString ElementsCollectionCache::name() const {
+	return(current_name_);
+}
+
+/**
+	@return The last pixmap fetched through fetchElement().
+*/
+QPixmap ElementsCollectionCache::pixmap() const {
+	return(current_pixmap_);
+}
+
+/**
+	Retrieve the data by building the full CustomElement object matching the
+	given location, without using the cache. Data are then available through
+	pixmap() and name() methods.
+	@param Location Location of a given Element.
+	@return True if the retrieval succeeded, false otherwise.
+*/
+bool ElementsCollectionCache::fetchData(const ElementsLocation &location) {
+	int state;
+	CustomElement *custom_elmt = new CustomElement(location, 0, 0, &state);
+	if (state) {
+		qDebug() << "ElementsCollectionCache::fetchData() : Le chargement du composant" << qPrintable(location.toString()) << "a echoue avec le code d'erreur" << state;
+	} else {
+		current_name_   = custom_elmt -> name();
+		current_pixmap_ = custom_elmt -> pixmap();
+	}
+	delete custom_elmt;
+	return(!state);
+}
+
+/**
+	Retrieve the name for an element, given its path and last modification
+	time. The value is then available through the name() method.
+	@param path Element path (as obtained using ElementsLocation::toString())
+	@param file_mtime Date and time of last modification of this element. Any
+	older cached value will be ignored.
+	@return True if the retrieval succeeded, false otherwise.
+*/
+bool ElementsCollectionCache::fetchNameFromCache(const QString &path, const QDateTime &file_mtime) {
+	select_name_ -> bindValue(":path", path);
+	select_name_ -> bindValue(":locale", locale_);
+	select_name_ -> bindValue(":file_mtime", file_mtime);
+	if (select_name_ -> exec()) {
+		if (select_name_ -> first()) {
+			current_name_ = select_name_ -> value(0).toString();
+			return(true);
+		}
+	} else {
+		qDebug() << "select_name_->exec() failed";
+	}
+	return(false);
+}
+
+/**
+	Retrieve the pixmap for an element, given its path and last modification
+	time. It is then available through the pixmap() method.
+	@param path Element path (as obtained using ElementsLocation::toString())
+	@param file_mtime Date and time of last modification of this element. Any
+	older cached pixmap will be ignored.
+	@return True if the retrieval succeeded, false otherwise.
+*/
+bool ElementsCollectionCache::fetchPixmapFromCache(const QString &path, const QDateTime &file_mtime) {
+	select_pixmap_ -> bindValue(":path", path);
+	select_pixmap_ -> bindValue(":file_mtime", file_mtime);
+	if (select_pixmap_ -> exec()) {
+		if (select_pixmap_ -> first()) {
+			QByteArray ba = select_pixmap_ -> value(0).toByteArray();
+			// avoid returning always the same pixmap (i.e. same cacheKey())
+			current_pixmap_.detach();
+			current_pixmap_.loadFromData(ba, qPrintable(pixmap_storage_format_));
+		}
+		return(true);
+	} else {
+		qDebug() << "select_pixmap_->exec() failed";
+	}
+	return(false);
+}
+
+/**
+	Cache the current (i.e. last retrieved) name. The cache entry will use
+	the current date and time and the locale set via setLocale().
+	@param path Element path (as obtained using ElementsLocation::toString())
+	@return True if the caching succeeded, false otherwise.
+	@see name()
+*/
+bool ElementsCollectionCache::cacheName(const QString &path) {
+	insert_name_ -> bindValue(":path",   path);
+	insert_name_ -> bindValue(":locale", locale_);
+	insert_name_ -> bindValue(":mtime",  QVariant(QDateTime::currentDateTime()));
+	insert_name_ -> bindValue(":name",   current_name_);
+	if (!insert_name_ -> exec()) {
+		qDebug() << cache_db_.lastError();
+		return(false);
+	}
+	return(true);
+}
+
+/**
+	Cache the current (i.e. last retrieved) pixmap. The cache entry will use
+	the current date and time.
+	@param path Element path (as obtained using ElementsLocation::toString())
+	@return True if the caching succeeded, false otherwise.
+	@see pixmap()
+*/
+bool ElementsCollectionCache::cachePixmap(const QString &path) {
+	QByteArray ba;
+	QBuffer buffer(&ba);
+	buffer.open(QIODevice::WriteOnly);
+	current_pixmap_.save(&buffer, qPrintable(pixmap_storage_format_));
+	insert_pixmap_ -> bindValue(":path", path);
+	insert_pixmap_ -> bindValue(":mtime", QVariant(QDateTime::currentDateTime()));
+	insert_pixmap_ -> bindValue(":pixmap", QVariant(ba));
+	if (!insert_pixmap_->exec()) {
+		qDebug() << cache_db_.lastError();
+		return(false);
+	}
+	return(true);
+}

Added: branches/0.3/sources/elementscollectioncache.h
===================================================================
--- branches/0.3/sources/elementscollectioncache.h	                        (rev 0)
+++ branches/0.3/sources/elementscollectioncache.h	2011-09-13 21:46:10 UTC (rev 1329)
@@ -0,0 +1,69 @@
+/*
+	Copyright 2006-2011 Xavier Guerrin
+	This file is part of QElectroTech.
+	
+	QElectroTech 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.
+	
+	QElectroTech 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 QElectroTech.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef ELEMENTS_COLLECTION_CACHE_H
+#define ELEMENTS_COLLECTION_CACHE_H
+#include <QtCore>
+#include <QtSql>
+#include "elementslocation.h"
+class ElementsCollection;
+class ElementsCategory;
+class ElementDefinition;
+/**
+	This class implements a SQLite cache for data related to elements
+	collections, mainly names and pixmaps. This avoids the cost of parsing XML
+	definitions of elements and building full CustomElement objects when
+	(re)loading the elements panel.
+*/
+class ElementsCollectionCache : public QObject {
+	public:
+	// constructor, destructor
+	ElementsCollectionCache(const QString &database_path, QObject * = 0);
+	virtual ~ElementsCollectionCache();
+	
+	// methods
+	public:
+	void setLocale(const QString &);
+	QString locale() const;
+	bool setPixmapStorageFormat(const QString &);
+	QString pixmapStorageFormat() const;
+	void beginCollection(ElementsCollection *);
+	void endCollection(ElementsCollection *);
+	bool fetchElement(ElementDefinition *);
+	QString name() const;
+	QPixmap pixmap() const;
+	
+	private:
+	bool fetchData(const ElementsLocation &);
+	bool fetchNameFromCache(const QString &, const QDateTime &);
+	bool fetchPixmapFromCache(const QString &, const QDateTime &);
+	bool cacheName(const QString &);
+	bool cachePixmap(const QString &);
+	
+	// attributes
+	private:
+	QSqlDatabase cache_db_;         ///< Object providing access to the SQLite database this cache relies on
+	QSqlQuery *select_name_;        ///< Prepared statement to fetch names from the cache
+	QSqlQuery *select_pixmap_;      ///< Prepared statement to fetch pixmaps from the cache
+	QSqlQuery *insert_name_;        ///< Prepared statement to insert names into the cache
+	QSqlQuery *insert_pixmap_;      ///< Prepared statement to insert pixmaps into the cache
+	QString locale_;                ///< Locale to be used when dealing with names
+	QString pixmap_storage_format_; ///< Storage format for cached pixmaps
+	QString current_name_;          ///< Last name fetched
+	QPixmap current_pixmap_;        ///< Last pixmap fetched
+};
+#endif

Modified: branches/0.3/sources/elementspanel.cpp
===================================================================
--- branches/0.3/sources/elementspanel.cpp	2011-09-13 17:13:10 UTC (rev 1328)
+++ branches/0.3/sources/elementspanel.cpp	2011-09-13 21:46:10 UTC (rev 1329)
@@ -20,6 +20,7 @@
 #include "qetproject.h"
 #include "diagram.h"
 #include "elementscategory.h"
+#include "elementscollectioncache.h"
 #include "customelement.h"
 #include "fileelementscollection.h"
 #include "fileelementdefinition.h"
@@ -89,7 +90,6 @@
 	first_activation_(true),
 	first_reload_(true)
 {
-	
 	// selection unique
 	setSelectionMode(QAbstractItemView::SingleSelection);
 	setColumnCount(1);
@@ -120,6 +120,10 @@
 	
 	// emet un signal au lieu de gerer son menu contextuel
 	setContextMenuPolicy(Qt::CustomContextMenu);
+	
+	QString cache_path = QETApp::configDir() + "/elements_cache.sqlite";
+	cache_ = new ElementsCollectionCache(cache_path, this);
+	cache_ -> setLocale(QLocale::system().name().left(2)); // @todo we need a unique function to get the good language
 }
 
 /**
@@ -644,7 +648,9 @@
 QTreeWidgetItem *ElementsPanel::addCollection(QTreeWidgetItem *qtwi_parent, ElementsCollection *collection, const QString &coll_name, const QIcon &icon) {
 	if (!collection) return(0);
 	
+	cache_ -> beginCollection(collection);
 	QTreeWidgetItem *qtwi_coll = addCategory(qtwi_parent, collection -> rootCategory(), coll_name, icon);
+	cache_ -> endCollection(collection);
 	return(qtwi_coll);
 }
 
@@ -704,21 +710,21 @@
 QTreeWidgetItem *ElementsPanel::addElement(QTreeWidgetItem *qtwi_parent, ElementDefinition *element, const QString &elmt_name) {
 	if (!element) return(0);
 	
+	if (!cache_ -> fetchElement(element)) {
+		return(0);
+	}
+	QString custom_element_name   = cache_ -> name();
+	QPixmap custom_element_pixmap = cache_ -> pixmap();
+	
 	QString whats_this = tr("Ceci est un \351l\351ment que vous pouvez ins\351rer dans votre sch\351ma par cliquer-d\351placer");
 	QString tool_tip = tr("Cliquer-d\351posez cet \351l\351ment sur le sch\351ma pour ins\351rer un \351l\351ment ");
-	int state;
-	CustomElement custom_elmt(element -> location(), 0, 0, &state);
-	if (state) {
-		qDebug() << "ElementsCategoriesList::addElement() : Le chargement du composant" << qPrintable(element -> location().toString()) << "a echoue avec le code d'erreur" << state;
-		return(0);
-	}
-	QString final_name(elmt_name.isEmpty() ? custom_elmt.name() : elmt_name);
+	QString final_name(elmt_name.isEmpty() ? custom_element_name : elmt_name);
 	QTreeWidgetItem *qtwi = new QTreeWidgetItem(qtwi_parent, QStringList(final_name));
-	qtwi -> setStatusTip(0, tool_tip + "\253 " + custom_elmt.name() + " \273");
+	qtwi -> setStatusTip(0, tool_tip + "\253 " + custom_element_name + " \273");
 	qtwi -> setToolTip(0, element -> location().toString());
 	qtwi -> setWhatsThis(0, whats_this);
 	qtwi -> setFlags(Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled);
-	qtwi -> setIcon(0, QIcon(custom_elmt.pixmap()));
+	qtwi -> setIcon(0, QIcon(custom_element_pixmap));
 	
 	// actions speciales pour les elements appartenant a un projet
 	if (QETProject *element_project = element -> location().project()) {

Modified: branches/0.3/sources/elementspanel.h
===================================================================
--- branches/0.3/sources/elementspanel.h	2011-09-13 17:13:10 UTC (rev 1328)
+++ branches/0.3/sources/elementspanel.h	2011-09-13 21:46:10 UTC (rev 1329)
@@ -25,6 +25,7 @@
 class ElementsCollectionItem;
 class ElementsCategory;
 class ElementDefinition;
+class ElementsCollectionCache;
 /**
 	Cette classe represente le panel d'appareils (en tant qu'element
 	graphique) dans lequel l'utilisateur choisit les composants de
@@ -144,5 +145,6 @@
 	int loading_progress_;
 	bool first_activation_;
 	bool first_reload_;
+	ElementsCollectionCache *cache_;
 };
 #endif

Modified: branches/0.3/sources/fileelementdefinition.cpp
===================================================================
--- branches/0.3/sources/fileelementdefinition.cpp	2011-09-13 17:13:10 UTC (rev 1328)
+++ branches/0.3/sources/fileelementdefinition.cpp	2011-09-13 21:46:10 UTC (rev 1329)
@@ -198,3 +198,14 @@
 	}
 	file_path = file_info.canonicalFilePath();
 }
+
+/**
+	@return the time of the last modification (mtime) for this element file
+*/
+QDateTime FileElementDefinition::modificationTime() const {
+	QFileInfo file_info(file_path);
+	if (!file_info.exists() || !file_info.isReadable()) {
+		return QDateTime();
+	}
+	return(file_info.lastModified());
+}

Modified: branches/0.3/sources/fileelementdefinition.h
===================================================================
--- branches/0.3/sources/fileelementdefinition.h	2011-09-13 17:13:10 UTC (rev 1328)
+++ branches/0.3/sources/fileelementdefinition.h	2011-09-13 21:46:10 UTC (rev 1329)
@@ -49,6 +49,7 @@
 	virtual bool hasFilePath();
 	virtual QString filePath();
 	virtual void setFilePath(const QString &);
+	virtual QDateTime modificationTime() const;
 	
 	// attributs
 	private:

Modified: branches/0.3/sources/fileelementscollection.cpp
===================================================================
--- branches/0.3/sources/fileelementscollection.cpp	2011-09-13 17:13:10 UTC (rev 1328)
+++ branches/0.3/sources/fileelementscollection.cpp	2011-09-13 21:46:10 UTC (rev 1329)
@@ -123,3 +123,11 @@
 bool FileElementsCollection::write() {
 	return(true);
 }
+
+/**
+	@return always true, since a file-based elements collection can always be
+	cached.
+*/
+bool FileElementsCollection::isCacheable() const {
+	return(true);
+}

Modified: branches/0.3/sources/fileelementscollection.h
===================================================================
--- branches/0.3/sources/fileelementscollection.h	2011-09-13 17:13:10 UTC (rev 1328)
+++ branches/0.3/sources/fileelementscollection.h	2011-09-13 21:46:10 UTC (rev 1329)
@@ -48,6 +48,7 @@
 	virtual bool isReadable();
 	virtual bool isWritable();
 	virtual bool write();
+	virtual bool isCacheable() const;
 	
 	private:
 	void deleteContent();

Modified: branches/0.3/sources/xmlelementdefinition.cpp
===================================================================
--- branches/0.3/sources/xmlelementdefinition.cpp	2011-09-13 17:13:10 UTC (rev 1328)
+++ branches/0.3/sources/xmlelementdefinition.cpp	2011-09-13 21:46:10 UTC (rev 1329)
@@ -213,6 +213,17 @@
 	// une categorie XML n'a pas de chemin de type fichier
 }
 
+/**
+	@return a null QDateTime object since an XML element does not have a
+	modification time.
+*/
+/**
+	@return the time of the last modification (mtime) for this element file
+*/
+QDateTime XmlElementDefinition::modificationTime() const {
+	return QDateTime();
+}
+
 QDomElement XmlElementDefinition::writeXml(QDomDocument &xml_doc) const {
 	QDomElement element_elmt = xml_element_.documentElement();
 	QDomNode new_node = xml_doc.importNode(element_elmt, true);

Modified: branches/0.3/sources/xmlelementdefinition.h
===================================================================
--- branches/0.3/sources/xmlelementdefinition.h	2011-09-13 17:13:10 UTC (rev 1328)
+++ branches/0.3/sources/xmlelementdefinition.h	2011-09-13 21:46:10 UTC (rev 1329)
@@ -52,6 +52,7 @@
 	virtual bool hasFilePath();
 	virtual QString filePath();
 	virtual void setFilePath(const QString &);
+	virtual QDateTime modificationTime() const;
 	virtual QDomElement writeXml(QDomDocument &) const;
 	
 	signals:

Modified: branches/0.3/sources/xmlelementscollection.cpp
===================================================================
--- branches/0.3/sources/xmlelementscollection.cpp	2011-09-13 17:13:10 UTC (rev 1328)
+++ branches/0.3/sources/xmlelementscollection.cpp	2011-09-13 21:46:10 UTC (rev 1329)
@@ -115,6 +115,14 @@
 	return(true);
 }
 
+/**
+	@return always false, since an XMl-based elements collection should never
+	be cached.
+*/
+bool XmlElementsCollection::isCacheable() const {
+	return(false);
+}
+
 QDomElement XmlElementsCollection::writeXml(QDomDocument &xml_doc) const {
 	QDomElement collection_elmt = root -> writeXml(xml_doc);
 	collection_elmt.setTagName("collection");

Modified: branches/0.3/sources/xmlelementscollection.h
===================================================================
--- branches/0.3/sources/xmlelementscollection.h	2011-09-13 17:13:10 UTC (rev 1328)
+++ branches/0.3/sources/xmlelementscollection.h	2011-09-13 21:46:10 UTC (rev 1329)
@@ -47,6 +47,7 @@
 	virtual bool isReadable();
 	virtual bool isWritable();
 	virtual bool write();
+	virtual bool isCacheable() const;
 	
 	virtual QDomElement writeXml(QDomDocument &) const;
 	


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/