[Ktutorial-commits] SF.net SVN: ktutorial:[110] trunk/ktutorial/ktutorial-editor
Status: Alpha
Brought to you by:
danxuliu
From: <dan...@us...> - 2010-03-05 23:35:37
|
Revision: 110 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=110&view=rev Author: danxuliu Date: 2010-03-05 23:35:28 +0000 (Fri, 05 Mar 2010) Log Message: ----------- Add the foundations to show a Tutorial in a QTreeView. Modified Paths: -------------- trunk/ktutorial/ktutorial-editor/CMakeLists.txt trunk/ktutorial/ktutorial-editor/src/CMakeLists.txt Added Paths: ----------- trunk/ktutorial/ktutorial-editor/src/view/ trunk/ktutorial/ktutorial-editor/src/view/CMakeLists.txt trunk/ktutorial/ktutorial-editor/src/view/TreeItem.cpp trunk/ktutorial/ktutorial-editor/src/view/TreeItem.h trunk/ktutorial/ktutorial-editor/src/view/TreeModel.cpp trunk/ktutorial/ktutorial-editor/src/view/TreeModel.h trunk/ktutorial/ktutorial-editor/tests/ trunk/ktutorial/ktutorial-editor/tests/CMakeLists.txt trunk/ktutorial/ktutorial-editor/tests/unit/ trunk/ktutorial/ktutorial-editor/tests/unit/CMakeLists.txt trunk/ktutorial/ktutorial-editor/tests/unit/runMemcheck.py trunk/ktutorial/ktutorial-editor/tests/unit/view/ trunk/ktutorial/ktutorial-editor/tests/unit/view/CMakeLists.txt trunk/ktutorial/ktutorial-editor/tests/unit/view/TreeItemTest.cpp trunk/ktutorial/ktutorial-editor/tests/unit/view/TreeModelTest.cpp Modified: trunk/ktutorial/ktutorial-editor/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/CMakeLists.txt 2010-03-05 23:32:03 UTC (rev 109) +++ trunk/ktutorial/ktutorial-editor/CMakeLists.txt 2010-03-05 23:35:28 UTC (rev 110) @@ -5,3 +5,4 @@ include(KDE4Defaults) add_subdirectory(src) +add_subdirectory(tests) Modified: trunk/ktutorial/ktutorial-editor/src/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/src/CMakeLists.txt 2010-03-05 23:32:03 UTC (rev 109) +++ trunk/ktutorial/ktutorial-editor/src/CMakeLists.txt 2010-03-05 23:35:28 UTC (rev 110) @@ -2,6 +2,8 @@ # In order to work, they must be compiled using -fPIC add_definitions("-fPIC") +add_subdirectory(view) + include_directories(${KDE4_INCLUDES}) set(ktutorial_editor_SRCS @@ -14,6 +16,7 @@ # As everything but a tiny initialization code is in a library, the build system # for the tests can be easily set up. kde4_add_library(ktutorial_editor ${ktutorial_editor_SRCS}) +target_link_libraries(ktutorial_editor ktutorial_editor_view) kde4_add_executable(ktutorial-editor main.cpp) target_link_libraries(ktutorial-editor ktutorial_editor ${KDE4_KDEUI_LIBS} ${KDE4_KIO_LIBS}) Added: trunk/ktutorial/ktutorial-editor/src/view/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/CMakeLists.txt (rev 0) +++ trunk/ktutorial/ktutorial-editor/src/view/CMakeLists.txt 2010-03-05 23:35:28 UTC (rev 110) @@ -0,0 +1,10 @@ +include_directories(${KDE4_INCLUDES}) + +set(ktutorial_editor_view_SRCS + TreeItem.cpp + TreeModel.cpp +) + +kde4_add_library(ktutorial_editor_view ${ktutorial_editor_view_SRCS}) + +target_link_libraries(ktutorial_editor_view ${KDE4_KDEUI_LIBS}) Property changes on: trunk/ktutorial/ktutorial-editor/src/view/CMakeLists.txt ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-editor/src/view/TreeItem.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/TreeItem.cpp (rev 0) +++ trunk/ktutorial/ktutorial-editor/src/view/TreeItem.cpp 2010-03-05 23:35:28 UTC (rev 110) @@ -0,0 +1,70 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * 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 3 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, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include "TreeItem.h" + +TreeItem::TreeItem(TreeItem* parent): + mParent(parent) { +} + +TreeItem::~TreeItem() { + qDeleteAll(mChildren); +} + +TreeItem* TreeItem::child(int index) { + return mChildren.value(index); +} + +int TreeItem::childCount() const { + return mChildren.count(); +} + +void TreeItem::appendChild(TreeItem* child) { + Q_ASSERT(!mChildren.contains(child)); + Q_ASSERT(child->parent() == this); + + mChildren.append(child); +} + +void TreeItem::insertChild(TreeItem* child, int index) { + Q_ASSERT(!mChildren.contains(child)); + Q_ASSERT(child->parent() == this); + + mChildren.insert(index, child); +} + +void TreeItem::removeChild(TreeItem* child) { + Q_ASSERT(mChildren.contains(child)); + Q_ASSERT(child->parent() == this); + + mChildren.removeAt(mChildren.indexOf(child)); +} + +TreeItem* TreeItem::parent() { + return mParent; +} + +int TreeItem::childIndex() const { + for (int i = 0; i < mParent->childCount(); ++i) { + if (mParent->child(i) == this) { + return i; + } + } + + return -1; +} Property changes on: trunk/ktutorial/ktutorial-editor/src/view/TreeItem.cpp ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-editor/src/view/TreeItem.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/TreeItem.h (rev 0) +++ trunk/ktutorial/ktutorial-editor/src/view/TreeItem.h 2010-03-05 23:35:28 UTC (rev 110) @@ -0,0 +1,133 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * 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 3 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, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifndef TREEITEM_H +#define TREEITEM_H + +#include <QString> +#include <QVariant> + +/** + * An item in a TreeModel. + * TreeItems form tree structures that provide the data to TreeModels. The + * TreeItems act as an adapter between the model and the real data: through + * TreeItem custom subclasses a source of data can be represented as several + * nested TreeItem objects that expose the data in some specific structure. + * + * For example, an object of a Person class with name, age and profession + * attributes can be represented as a tree with a parent TreeItem that contains + * the name of the person and two child TreeItems, one that contains the age and + * one that contains the profession. + * + * TreeItem is an abstract class. Subclasses must implement its text() method, + * that provides the data for that item to the TreeModel when DisplayRole is + * used. + * + * @see TreeModel + */ +class TreeItem { +public: + + /** + * Creates a new TreeItem with the given parent. + * + * @param parent The parent TreeItem. + */ + explicit TreeItem(TreeItem* parent = 0); + + /** + * Destroys this TreeItem and all its children. + */ + virtual ~TreeItem(); + + /** + * The text to be shown for this node of the tree, + * This method must be implemented by subclasses. + * + * @return The text for this TreeItem. + */ + virtual QString text() const = 0; + + /** + * Returns the child tree item with the given index. + * + * @param index The index of the child to get. + * @return The child with the given index. + */ + TreeItem* child(int index); + + /** + * Returns the number of child tree items. + * + * @return The number of children. + */ + int childCount() const; + + /** + * Adds a child at the end of the child list. + * + * @param child The child to add. + */ + void appendChild(TreeItem* child); + + /** + * Inserts a child at the given position of the child list. + * + * @param child The child to insert. + * @param index The position to insert the child into. + */ + void insertChild(TreeItem* child, int index); + + /** + * Removes the given child from the child list. + * + * @param child The child to remove. + */ + void removeChild(TreeItem* child); + + /** + * The parent of this TreeItem. + * + * @return The parent of this TreeItem. + */ + TreeItem* parent(); + + /** + * The index of this TreeItem in the child list of its parent. + * If this TreeItem was not added or was removed from its parent, -1 is + * returned. + * + * @return The index of this TreeItem. + */ + int childIndex() const; + +private: + + /** + * The parent of this TreeItem. + */ + TreeItem* mParent; + + /** + * The children of this TreeItem. + */ + QList<TreeItem*> mChildren; + +}; + +#endif Property changes on: trunk/ktutorial/ktutorial-editor/src/view/TreeItem.h ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-editor/src/view/TreeModel.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/TreeModel.cpp (rev 0) +++ trunk/ktutorial/ktutorial-editor/src/view/TreeModel.cpp 2010-03-05 23:35:28 UTC (rev 110) @@ -0,0 +1,116 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * 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 3 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, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include "TreeModel.h" + +#include "TreeItem.h" + +//public: + +TreeModel::TreeModel(TreeItem* rootItem, QObject* parent): + QAbstractItemModel(parent), + mRootItem(rootItem) { + Q_ASSERT(rootItem); +} + +TreeModel::~TreeModel() { + delete mRootItem; +} + +QVariant TreeModel::data(const QModelIndex& index, int role) const { + if (!index.isValid()) { + return QVariant(); + } + + if (role != Qt::DisplayRole) { + return QVariant(); + } + + TreeItem* item = static_cast<TreeItem*>(index.internalPointer()); + + return item->text(); +} + +Qt::ItemFlags TreeModel::flags(const QModelIndex& index) const { + if (!index.isValid()) { + return Qt::NoItemFlags; + } + + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; +} + +QVariant TreeModel::headerData(int section, Qt::Orientation orientation, + int role) const { + if (section == 0 && orientation == Qt::Horizontal && + role == Qt::DisplayRole) { + return mRootItem->text(); + } + + return QVariant(); +} + +QModelIndex TreeModel::index(int row, int column, + const QModelIndex& parent) const { + if (!hasIndex(row, column, parent)) { + return QModelIndex(); + } + + TreeItem* parentItem; + + if (!parent.isValid()) { + parentItem = mRootItem; + } else { + parentItem = static_cast<TreeItem*>(parent.internalPointer()); + } + + TreeItem* childItem = parentItem->child(row); + + return createIndex(row, column, childItem); +} + +QModelIndex TreeModel::parent(const QModelIndex& index) const { + if (!index.isValid()) { + return QModelIndex(); + } + + TreeItem* childItem = static_cast<TreeItem*>(index.internalPointer()); + TreeItem* parentItem = childItem->parent(); + + if (parentItem == mRootItem) { + return QModelIndex(); + } + + return createIndex(parentItem->childIndex(), 0, parentItem); +} + +int TreeModel::rowCount(const QModelIndex& parent) const { + TreeItem* parentItem; + if (!parent.isValid()) { + parentItem = mRootItem; + } else { + parentItem = static_cast<TreeItem*>(parent.internalPointer()); + } + + return parentItem->childCount(); +} + +int TreeModel::columnCount(const QModelIndex& parent) const { + Q_UNUSED(parent); + + return 1; +} Property changes on: trunk/ktutorial/ktutorial-editor/src/view/TreeModel.cpp ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-editor/src/view/TreeModel.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/TreeModel.h (rev 0) +++ trunk/ktutorial/ktutorial-editor/src/view/TreeModel.h 2010-03-05 23:35:28 UTC (rev 110) @@ -0,0 +1,150 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * 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 3 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, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifndef TREEMODEL_H +#define TREEMODEL_H + +#include <QAbstractItemModel> + +class TreeItem; + +/** + * A read only model to represent nested data in a single column tree. + * The model gets its data from a tree structure made of TreeItems. The root + * item provides the data for the header and its children (and the children of + * its children, and the children of the children of...) the data for the + * contents. + * + * TreeItem objects are mapped one to one to items in the model. Each TreeItem + * (but the root item) has its own index in the model. Top level items (direct + * children of root item) have no parent indexes. For child items, their parent + * index is the index of its parent item. The row count for any index is the + * number of children of its TreeItem. There is only one column in any index (as + * it is a single column tree). + * + * Each TreeItem provides the data to be shown by its associated model item. + * Display role shows the text of the TreeItem. + * + * @see TreeItem + */ +class TreeModel: public QAbstractItemModel { +Q_OBJECT +public: + + /** + * Creates a new TreeModel for the given root TreeItem. + * + * @param rootItem The root of the tree. + * @param parent The parent object. + */ + explicit TreeModel(TreeItem* rootItem, QObject* parent = 0); + + /** + * Destroys this TreeModel and its tree of items. + */ + virtual ~TreeModel(); + + /** + * Returns the data for the given index and role. + * Display role with valid index returns the text of the TreeItem referred + * to by the index. An invalid variant is returned otherwise. + * + * @param index The index. + * @param role The role. + * @return The data for the given index and role, or an invalid variant if + * there is no data. + */ + virtual QVariant data(const QModelIndex& index, + int role = Qt::DisplayRole) const; + + /** + * Returns the flags for the given index. + * If the index is valid, the flags enable the item and allow it to be + * selected. + * + * @return The flags for the given index. + */ + virtual Qt::ItemFlags flags(const QModelIndex& index) const; + + /** + * Returns the data for the given role and section in the header with the + * specified orientation. + * Display role in section 0 and horizontal orientation returns the text of + * the root item. An invalid variant is returned otherwise. + * + * @param section The section of the header. + * @param orientation The orientation of the header. + * @param role The role of the header. + * @return The data for the header. + */ + virtual QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const; + + /** + * Returns the index of the item in the model specified by the given row, + * column and parent index. + * If the row or column is out of bounds for the given parent, an invalid + * index is returned. + * + * @param row The row of the index. + * @param column The column of the index. + * @param parent The parent of the index. + * @return The index for the given row, column and parent. + */ + virtual QModelIndex index(int row, int column, + const QModelIndex& parent = QModelIndex()) const; + + /** + * Returns the index for the parent of the model item with the given index. + * If the index has no parent (it is invalid, or a top level index), an + * invalid index is returned. + * + * @param index The index to get its parent. + * @return The parent index of the given index. + */ + virtual QModelIndex parent(const QModelIndex& index) const; + + /** + * Returns the number of rows under the given parent. + * It is the number of children of the TreeItem referred to by the index. If + * the index is invalid, it is the number of top level items. + * + * @param parent The parent index. + * @return The number of child rows. + */ + virtual int rowCount(const QModelIndex& parent = QModelIndex()) const; + + /** + * Returns the number of columns for the children of the given parent. + * As this model is a single column model, it always returns 1. + * + * @param parent The parent index. + * @return The number of columns for the children. + */ + virtual int columnCount(const QModelIndex& parent = QModelIndex()) const; + +private: + + /** + * The root item. + */ + TreeItem* mRootItem; + +}; + +#endif Property changes on: trunk/ktutorial/ktutorial-editor/src/view/TreeModel.h ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-editor/tests/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/CMakeLists.txt (rev 0) +++ trunk/ktutorial/ktutorial-editor/tests/CMakeLists.txt 2010-03-05 23:35:28 UTC (rev 110) @@ -0,0 +1 @@ +add_subdirectory(unit) Property changes on: trunk/ktutorial/ktutorial-editor/tests/CMakeLists.txt ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-editor/tests/unit/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/CMakeLists.txt (rev 0) +++ trunk/ktutorial/ktutorial-editor/tests/unit/CMakeLists.txt 2010-03-05 23:35:28 UTC (rev 110) @@ -0,0 +1 @@ +add_subdirectory(view) Property changes on: trunk/ktutorial/ktutorial-editor/tests/unit/CMakeLists.txt ___________________________________________________________________ Added: svn:executable + * Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-editor/tests/unit/runMemcheck.py =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/runMemcheck.py (rev 0) +++ trunk/ktutorial/ktutorial-editor/tests/unit/runMemcheck.py 2010-03-05 23:35:28 UTC (rev 110) @@ -0,0 +1,173 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# run valgrind's memory error checker on all tests. +# filter uninteresting errors and known false positives +# eg staticly initialized memory from libraries like libfontconfig +# + + +# Modified from Coverage plugin tests for KDevelop 4 +# http://websvn.kde.org/trunk/KDE/kdevelop/tools/coverage/tests/runMemcheck.py?revision=926694&view=markup +# which is licensed under GPL 2 or later +# http://websvn.kde.org/trunk/KDE/kdevelop/tools/coverage/coverageplugin.cpp?revision=926694&view=markup + + +from os import system, remove +from sys import exit, stdout +from subprocess import Popen, PIPE +from xml.dom.minidom import parse, parseString + +def garbage(line): + ''' filter for valgridn output''' + return not line.startswith('<unknown program name>') and \ + not line.startswith('profiling:') and \ + line.find('</valgrindoutput>') # problem is that valgrind erroneously puts multiple of these end-document entries if processes are spawned _inside_ the exe under investigation + +def memcheck(test): + ''' run valgrind-memcheck on test in testdir. return xml output as string ''' + #proc = Popen("valgrind --tool=memcheck --leak-check=full --xml=yes " + test, stdout=PIPE, stderr=PIPE, shell=True, executable="/bin/bash") + #proc.wait() + #out = proc.stderr.readlines() + system("valgrind --tool=memcheck --leak-check=full --xml=yes --xml-file=.memcheck.tmp --num-callers=50 " + test + " 1>/dev/null") + out = open(".memcheck.tmp").readlines() + remove(".memcheck.tmp") + out = filter(garbage, out) + return ''.join(out) + "\n</valgrindoutput>\n" + +def xml_child_data(dom,tag): + ''' extract child data for tag. return None if not found''' + elem = dom.getElementsByTagName(tag) + val = None + if len(elem) != 0: + val = elem[0].firstChild.data + return val + +class Frame: + ''' single entry in a memory error backtrace ''' + def __init__(self, dom_frame): + '''<frame> + <ip>0x62ACDBF</ip> + <obj>/home/nix/KdeDev/kde4/lib/libkdevplatformlanguage.so.1.0.0</obj> + <fn>KDevelop::ParamIterator::ParamIterator(QString, QString, int)</fn> + <dir>/home/nix/KdeDev/kdevplatform/language/duchain</dir> + <file>stringhelpers.cpp</file> + <line>292</line> + </frame>''' + self.obj = xml_child_data(dom_frame, 'obj') + self.func = xml_child_data(dom_frame, 'fn') + self.sfile = xml_child_data(dom_frame, 'file') + self.sline = xml_child_data(dom_frame, 'line') + + def __str__(self): + out = "" + if self.func: + out += "\t" + self.func + if self.sfile and self.sline: + out += " (" + self.sfile + ":" + self.sline + ")" + #if self.obj: + #out += "\t" + self.obj + "\n" + out += "\n" + return out + +class BackTrace: + ''' valgrind memcheck stack trace ''' + def __init__(self, errordom): + self.dom = errordom + self.kind = self.dom.getElementsByTagName('kind')[0].firstChild.data + stack = self.dom.getElementsByTagName('frame') + self.stack = [] + for frame in stack: + if xml_child_data(frame, 'fn'): # filter anonymous frames out + self.stack.append(Frame(frame)) + self.what = xml_child_data(self.dom, 'what') + if self.dom.getElementsByTagName('xwhat').length > 0: + self.what = xml_child_data(self.dom.getElementsByTagName('xwhat')[0], 'text') + + def is_definitely_lost(self): + return self.kind == u'Leak_DefinitelyLost' + + def is_qtest(self): + is_interesting = False + for frame in self.stack: + if frame.func: + if frame.func.find("QTest") != -1 or frame.func.find("Veritas") != -1: + is_interesting = True + if frame.func.find('XcursorXcFileLoadImages') != -1: + return False # something deep in X server, not interested in this + if frame.func.find('XRegisterIMInstantiateCallback') != -1: + return False # X-related static memory allocation, no leak + if frame.func.find('FcDefaultSubstitute') != -1: + return False # something Qt-Font related, not interested in this + if frame.func.find('__nss_database_lookup') != -1: + return False # more crap + if frame.sfile: + if frame.sfile.find("xtest") != -1 or frame.sfile.find("veritas") != -1: + is_interesting = True + return is_interesting + + def __str__(self): + out = self.what + "\n" + for frame in self.stack: + out += str(frame) + return out + +def parse_errors(out): + ''' extract the interesting memcheck errors from the xml-string input 'out'. + return these as a list ''' + xmldoc = parseString(out) + errors = xmldoc.getElementsByTagName('error') + errors_ = [] + for error in errors: + bt = BackTrace(error) + if bt.is_definitely_lost() and bt.is_qtest(): + errors_.append(bt) + return errors_ + +def run_single_test(exe_name): + print ">> running valgrind memcheck on " + exe_name + system("export LD_LIBRARY_PATH="+sys.argv[2]+"/lib/:$LD_LIBRARY_PATH") + count = 0 + import xml + while count < 5: + try: + out = memcheck(exe_name) + errors = parse_errors(out) + if len(errors) == 0: + print "PASS" + exit(0) + else: + for trace in errors: + print trace, + print "---------------------------------------------------" + exit(-1) + except xml.parsers.expat.ExpatError: + print "Valgrind fooked up, retry" + count += 1 + pass + print "5 retries, no luck: aborting :(" + exit(-1) + +################### ENTRY #################################################### + + +def isValgrind3_5OrHigher(): + process = Popen("valgrind --version", stdout=PIPE, shell=True) + process.wait() + valgrindOutput = process.stdout.read().strip() + + import re, string + version = re.search("[0-9]+(.[0-9]+)*", valgrindOutput).group(0) + version = string.split(version, ".") + + if map(int, version) < [3, 5]: + return False + else: + return True + +if __name__ == '__main__': + if not isValgrind3_5OrHigher(): + print "Valgrind 3.5.0 or higher is needed. No mem check will be run." + exit(-1) + + import sys + run_single_test(sys.argv[1]) Property changes on: trunk/ktutorial/ktutorial-editor/tests/unit/runMemcheck.py ___________________________________________________________________ Added: svn:executable + * Added: trunk/ktutorial/ktutorial-editor/tests/unit/view/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/view/CMakeLists.txt (rev 0) +++ trunk/ktutorial/ktutorial-editor/tests/unit/view/CMakeLists.txt 2010-03-05 23:35:28 UTC (rev 110) @@ -0,0 +1,27 @@ +# Used by kde4_add_unit_test to set the full path to test executables +set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) + +include_directories(${CMAKE_CURRENT_BINARY_DIR} ${ktutorial-editor_SOURCE_DIR}/src/view ${ktutorial-editor_BINARY_DIR}/src/view ${KDE4_INCLUDES}) + +# Since Qt 4.6.0, this definition is needed for GUI testing. +# It is backwards compatible with previous Qt versions, unlike the alternative +# which is to add #include <QTestGui> in the test files. +add_definitions(-DQT_GUI_LIB) + +MACRO(UNIT_TESTS) + FOREACH(_className ${ARGN}) + set(_testName ${_className}Test) + kde4_add_unit_test(${_testName} TESTNAME ktutorial-editor-unit-${_testName} ${_testName}.cpp) + target_link_libraries(${_testName} ktutorial_editor_view ${QT_QTTEST_LIBRARY}) + ENDFOREACH(_className) +ENDMACRO(UNIT_TESTS) + +unit_tests(TreeItem TreeModel) + +MACRO(MEM_TESTS) + FOREACH(_testname ${ARGN}) + add_test(ktutorial-editor-unit-mem-${_testname} ${CMAKE_CURRENT_SOURCE_DIR}/../runMemcheck.py ${CMAKE_CURRENT_BINARY_DIR}/${_testname}Test ${CMAKE_CURRENT_BINARY_DIR}) + ENDFOREACH(_testname) +ENDMACRO(MEM_TESTS) + +mem_tests(TreeItem TreeModel) Property changes on: trunk/ktutorial/ktutorial-editor/tests/unit/view/CMakeLists.txt ___________________________________________________________________ Added: svn:executable + * Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-editor/tests/unit/view/TreeItemTest.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/view/TreeItemTest.cpp (rev 0) +++ trunk/ktutorial/ktutorial-editor/tests/unit/view/TreeItemTest.cpp 2010-03-05 23:35:28 UTC (rev 110) @@ -0,0 +1,188 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * 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 3 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, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include <QtTest> + +#include "TreeItem.h" + +class TreeItemTest: public QObject { +Q_OBJECT + +private slots: + + void testConstructor(); + + void testAppendChild(); + void testAppendChildSeveralChildren(); + + void testInsertChild(); + void testInsertChildSeveralChildren(); + + void testRemoveChild(); + void testRemoveChildSeveralChildren(); + +}; + +class StubTreeItem: public TreeItem { +public: + + QString mText; + + StubTreeItem(TreeItem* parent = 0): TreeItem(parent) { + } + + virtual QString text() const { + return mText; + } + +}; + +void TreeItemTest::testConstructor() { + StubTreeItem parent; + StubTreeItem treeItem(&parent); + + QCOMPARE(parent.parent(), (TreeItem*)0); + QCOMPARE(treeItem.parent(), &parent); +} + +void TreeItemTest::testAppendChild() { + StubTreeItem treeItem; + TreeItem* child = new StubTreeItem(&treeItem); + + treeItem.appendChild(child); + + QCOMPARE(treeItem.childCount(), 1); + QCOMPARE(treeItem.child(0), child); + QCOMPARE(child->childIndex(), 0); + QCOMPARE(child->parent(), &treeItem); +} + +void TreeItemTest::testAppendChildSeveralChildren() { + StubTreeItem treeItem; + TreeItem* child1 = new StubTreeItem(&treeItem); + TreeItem* child2 = new StubTreeItem(&treeItem); + TreeItem* child3 = new StubTreeItem(&treeItem); + + treeItem.appendChild(child1); + treeItem.appendChild(child2); + treeItem.appendChild(child3); + + QCOMPARE(treeItem.childCount(), 3); + QCOMPARE(treeItem.child(0), child1); + QCOMPARE(treeItem.child(1), child2); + QCOMPARE(treeItem.child(2), child3); + QCOMPARE(child1->childIndex(), 0); + QCOMPARE(child1->parent(), &treeItem); + QCOMPARE(child2->childIndex(), 1); + QCOMPARE(child2->parent(), &treeItem); + QCOMPARE(child3->childIndex(), 2); + QCOMPARE(child3->parent(), &treeItem); +} + +void TreeItemTest::testInsertChild() { + StubTreeItem treeItem; + TreeItem* child = new StubTreeItem(&treeItem); + + treeItem.insertChild(child, 0); + + QCOMPARE(treeItem.childCount(), 1); + QCOMPARE(treeItem.child(0), child); + QCOMPARE(child->childIndex(), 0); + QCOMPARE(child->parent(), &treeItem); +} + +void TreeItemTest::testInsertChildSeveralChildren() { + StubTreeItem treeItem; + TreeItem* child1 = new StubTreeItem(&treeItem); + TreeItem* child2 = new StubTreeItem(&treeItem); + TreeItem* child3 = new StubTreeItem(&treeItem); + TreeItem* child4 = new StubTreeItem(&treeItem); + + treeItem.insertChild(child2, 0); + treeItem.insertChild(child1, 0); + treeItem.insertChild(child4, 2); + treeItem.insertChild(child3, 2); + + QCOMPARE(treeItem.childCount(), 4); + QCOMPARE(treeItem.child(0), child1); + QCOMPARE(treeItem.child(1), child2); + QCOMPARE(treeItem.child(2), child3); + QCOMPARE(treeItem.child(3), child4); + QCOMPARE(child1->childIndex(), 0); + QCOMPARE(child1->parent(), &treeItem); + QCOMPARE(child2->childIndex(), 1); + QCOMPARE(child2->parent(), &treeItem); + QCOMPARE(child3->childIndex(), 2); + QCOMPARE(child3->parent(), &treeItem); + QCOMPARE(child4->childIndex(), 3); + QCOMPARE(child4->parent(), &treeItem); +} + +void TreeItemTest::testRemoveChild() { + StubTreeItem treeItem; + //It will be removed and not deleted by parent TreeItem, so it is created in + //stack + StubTreeItem child(&treeItem); + + treeItem.appendChild(&child); + treeItem.removeChild(&child); + + QCOMPARE(treeItem.childCount(), 0); + QCOMPARE(child.childIndex(), -1); + QCOMPARE(child.parent(), &treeItem); +} + +void TreeItemTest::testRemoveChildSeveralChildren() { + StubTreeItem treeItem; + //They will be removed and not deleted by parent TreeItem, so they are + //created in stack + StubTreeItem child1(&treeItem); + StubTreeItem child2(&treeItem); + StubTreeItem child3(&treeItem); + + treeItem.appendChild(&child1); + treeItem.appendChild(&child2); + treeItem.appendChild(&child3); + + treeItem.removeChild(&child2); + + QCOMPARE(treeItem.childCount(), 2); + QCOMPARE(treeItem.child(0), &child1); + QCOMPARE(treeItem.child(1), &child3); + QCOMPARE(child1.childIndex(), 0); + QCOMPARE(child1.parent(), &treeItem); + QCOMPARE(child2.childIndex(), -1); + QCOMPARE(child2.parent(), &treeItem); + QCOMPARE(child3.childIndex(), 1); + QCOMPARE(child3.parent(), &treeItem); + + treeItem.removeChild(&child1); + treeItem.removeChild(&child3); + + QCOMPARE(treeItem.childCount(), 0); + QCOMPARE(child1.childIndex(), -1); + QCOMPARE(child1.parent(), &treeItem); + QCOMPARE(child2.childIndex(), -1); + QCOMPARE(child2.parent(), &treeItem); + QCOMPARE(child3.childIndex(), -1); + QCOMPARE(child3.parent(), &treeItem); +} + +QTEST_MAIN(TreeItemTest) + +#include "TreeItemTest.moc" Property changes on: trunk/ktutorial/ktutorial-editor/tests/unit/view/TreeItemTest.cpp ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-editor/tests/unit/view/TreeModelTest.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/view/TreeModelTest.cpp (rev 0) +++ trunk/ktutorial/ktutorial-editor/tests/unit/view/TreeModelTest.cpp 2010-03-05 23:35:28 UTC (rev 110) @@ -0,0 +1,295 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * 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 3 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, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include <QtTest> + +#include "TreeModel.h" + +#include "TreeItem.h" + +class TreeModelTest: public QObject { +Q_OBJECT + +private slots: + + void init(); + void cleanup(); + + void testConstructorEmptyRootItem(); + void testConstructorSingleItem(); + void testConstructorSeveralFlatItems(); + void testConstructorSingleNestedItem(); + void testConstructorSeveralNestedItems(); + + void testDataWithInvalidIndex(); + void testDataWithInvalidRole(); + + void testFlagsWithInvalidIndex(); + + void testHeaderDataWithInvalidSection(); + void testHeaderDataWithInvalidOrientation(); + void testHeaderDataWithInvalidRole(); + + void testIndexOutOfBounds(); + + void testParentWithInvalidIndex(); + +private: + + TreeItem* mEmptyRootItem; + TreeItem* mSingleItem; + TreeItem* mSeveralFlatItems; + TreeItem* mSingleNestedItem; + TreeItem* mSeveralNestedItems; + + void assertItem(const QModelIndex& index, const QString& displayRoleData, + int childrenCount, const QModelIndex& parent) const; + +}; + +class StubTreeItem: public TreeItem { +public: + + QString mText; + + StubTreeItem(QString text, TreeItem* parent = 0): + TreeItem(parent), + mText(text) { + } + + virtual QString text() const { + return mText; + } + +}; + +void TreeModelTest::init() { + mEmptyRootItem = new StubTreeItem("root"); + + mSingleItem = new StubTreeItem("root"); + TreeItem* parent = mSingleItem; + mSingleItem->appendChild(new StubTreeItem("root-1", parent)); + + mSeveralFlatItems = new StubTreeItem("root"); + parent = mSeveralFlatItems; + mSeveralFlatItems->appendChild(new StubTreeItem("root-1", parent)); + mSeveralFlatItems->appendChild(new StubTreeItem("root-2", parent)); + mSeveralFlatItems->appendChild(new StubTreeItem("root-3", parent)); + + mSingleNestedItem = new StubTreeItem("root"); + parent = mSingleNestedItem; + mSingleNestedItem->appendChild(new StubTreeItem("root-1", parent)); + parent = mSingleNestedItem->child(0); + mSingleNestedItem->child(0)->appendChild(new StubTreeItem("root-1-1", parent)); + + mSeveralNestedItems = new StubTreeItem("root"); + parent = mSeveralNestedItems; + mSeveralNestedItems->appendChild(new StubTreeItem("root-1", parent)); + parent = mSeveralNestedItems->child(0); + mSeveralNestedItems->child(0)->appendChild(new StubTreeItem("root-1-1", parent)); + parent = mSeveralNestedItems; + mSeveralNestedItems->appendChild(new StubTreeItem("root-2", parent)); + mSeveralNestedItems->appendChild(new StubTreeItem("root-3", parent)); + parent = mSeveralNestedItems->child(2); + mSeveralNestedItems->child(2)->appendChild(new StubTreeItem("root-3-1", parent)); + mSeveralNestedItems->child(2)->appendChild(new StubTreeItem("root-3-2", parent)); +} + +void TreeModelTest::cleanup() { + delete mEmptyRootItem; + delete mSingleItem; + delete mSeveralFlatItems; + delete mSingleNestedItem; + delete mSeveralNestedItems; +} + +void TreeModelTest::testConstructorEmptyRootItem() { + TreeModel model(mEmptyRootItem); + mEmptyRootItem = 0; + + QCOMPARE(model.rowCount(), 0); + QCOMPARE(model.columnCount(), 1); + QCOMPARE(model.headerData(0, Qt::Horizontal).toString(), QString("root")); +} + +void TreeModelTest::testConstructorSingleItem() { + TreeModel model(mSingleItem); + mSingleItem = 0; + + QCOMPARE(model.rowCount(), 1); + QCOMPARE(model.columnCount(), 1); + QCOMPARE(model.headerData(0, Qt::Horizontal).toString(), QString("root")); + + QModelIndex index = model.index(0, 0); + assertItem(index, "root-1", 0, QModelIndex()); +} + +void TreeModelTest::testConstructorSeveralFlatItems() { + TreeModel model(mSeveralFlatItems); + mSeveralFlatItems = 0; + + QCOMPARE(model.rowCount(), 3); + QCOMPARE(model.columnCount(), 1); + QCOMPARE(model.headerData(0, Qt::Horizontal).toString(), QString("root")); + + QModelIndex index = model.index(0, 0); + assertItem(index, "root-1", 0, QModelIndex()); + + index = model.index(1, 0); + assertItem(index, "root-2", 0, QModelIndex()); + + index = model.index(2, 0); + assertItem(index, "root-3", 0, QModelIndex()); +} + +void TreeModelTest::testConstructorSingleNestedItem() { + TreeModel model(mSingleNestedItem); + mSingleNestedItem = 0; + + QCOMPARE(model.rowCount(), 1); + QCOMPARE(model.columnCount(), 1); + QCOMPARE(model.headerData(0, Qt::Horizontal).toString(), QString("root")); + + QModelIndex index = model.index(0, 0); + assertItem(index, "root-1", 1, QModelIndex()); + + QModelIndex parent = index; + index = model.index(0, 0, parent); + assertItem(index, "root-1-1", 0, parent); +} + +void TreeModelTest::testConstructorSeveralNestedItems() { + TreeModel model(mSeveralNestedItems); + mSeveralNestedItems = 0; + + QCOMPARE(model.rowCount(), 3); + QCOMPARE(model.columnCount(), 1); + QCOMPARE(model.headerData(0, Qt::Horizontal).toString(), QString("root")); + + QModelIndex index = model.index(0, 0); + assertItem(index, "root-1", 1, QModelIndex()); + + QModelIndex parent = index; + index = model.index(0, 0, parent); + assertItem(index, "root-1-1", 0, parent); + + index = model.index(1, 0); + assertItem(index, "root-2", 0, QModelIndex()); + + index = model.index(2, 0); + assertItem(index, "root-3", 2, QModelIndex()); + + parent = index; + index = model.index(0, 0, parent); + assertItem(index, "root-3-1", 0, parent); + + index = model.index(1, 0, parent); + assertItem(index, "root-3-2", 0, parent); +} + +void TreeModelTest::testDataWithInvalidIndex() { + TreeModel model(mSingleItem); + mSingleItem = 0; + + QCOMPARE(model.data(QModelIndex()), QVariant()); +} + +void TreeModelTest::testDataWithInvalidRole() { + TreeModel model(mSingleItem); + mSingleItem = 0; + + QCOMPARE(model.data(model.index(0, 0), Qt::DecorationRole), QVariant()); + QCOMPARE(model.data(model.index(0, 0), Qt::EditRole), QVariant()); + QCOMPARE(model.data(model.index(0, 0), Qt::ToolTipRole), QVariant()); + QCOMPARE(model.data(model.index(0, 0), Qt::StatusTipRole), QVariant()); + QCOMPARE(model.data(model.index(0, 0), Qt::WhatsThisRole), QVariant()); + QCOMPARE(model.data(model.index(0, 0), Qt::SizeHintRole), QVariant()); +} + +void TreeModelTest::testFlagsWithInvalidIndex() { + TreeModel model(mSingleItem); + mSingleItem = 0; + + QCOMPARE(model.flags(QModelIndex()), Qt::NoItemFlags); +} + +void TreeModelTest::testHeaderDataWithInvalidSection() { + TreeModel model(mEmptyRootItem); + mEmptyRootItem = 0; + + QCOMPARE(model.headerData(1, Qt::Horizontal), QVariant()); +} + +void TreeModelTest::testHeaderDataWithInvalidOrientation() { + TreeModel model(mEmptyRootItem); + mEmptyRootItem = 0; + + QCOMPARE(model.headerData(0, Qt::Vertical), QVariant()); +} + +void TreeModelTest::testHeaderDataWithInvalidRole() { + TreeModel model(mEmptyRootItem); + mEmptyRootItem = 0; + + QCOMPARE(model.headerData(0, Qt::Horizontal, Qt::DecorationRole), QVariant()); + QCOMPARE(model.headerData(0, Qt::Horizontal, Qt::EditRole), QVariant()); + QCOMPARE(model.headerData(0, Qt::Horizontal, Qt::ToolTipRole), QVariant()); + QCOMPARE(model.headerData(0, Qt::Horizontal, Qt::StatusTipRole), QVariant()); + QCOMPARE(model.headerData(0, Qt::Horizontal, Qt::WhatsThisRole), QVariant()); + QCOMPARE(model.headerData(0, Qt::Horizontal, Qt::SizeHintRole), QVariant()); +} + +void TreeModelTest::testIndexOutOfBounds() { + TreeModel model(mSingleNestedItem); + mSingleNestedItem = 0; + + QCOMPARE(model.index(0, 1), QModelIndex()); + QCOMPARE(model.index(1, 0), QModelIndex()); + + QModelIndex parent = model.index(0, 0); + QVERIFY(parent.isValid()); + QCOMPARE(model.index(0, 1, parent), QModelIndex()); + QCOMPARE(model.index(1, 0, parent), QModelIndex()); +} + +void TreeModelTest::testParentWithInvalidIndex() { + TreeModel model(mSingleItem); + mSingleItem = 0; + + QCOMPARE(model.parent(QModelIndex()), QModelIndex()); +} + +/////////////////////////////////// Helpers //////////////////////////////////// + +void TreeModelTest::assertItem(const QModelIndex& index, + const QString& displayRoleData, + int childrenCount, + const QModelIndex& parent) const { + const QAbstractItemModel* model = index.model(); + + QVERIFY(index.isValid()); + QCOMPARE(model->data(index).toString(), displayRoleData); + QCOMPARE(model->flags(index), Qt::ItemIsEnabled | Qt::ItemIsSelectable); + QCOMPARE(model->parent(index), parent); + QCOMPARE(model->rowCount(index), childrenCount); + QCOMPARE(model->columnCount(index), 1); +} + +QTEST_MAIN(TreeModelTest) + +#include "TreeModelTest.moc" Property changes on: trunk/ktutorial/ktutorial-editor/tests/unit/view/TreeModelTest.cpp ___________________________________________________________________ Added: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |