KTutorial
0.5.1
|
00001 /*************************************************************************** 00002 * Copyright (C) 2012 by Daniel Calviño Sánchez <danxuliu@gmail.com> * 00003 * * 00004 * This program is free software; you can redistribute it and/or modify * 00005 * it under the terms of the GNU General Public License as published by * 00006 * the Free Software Foundation; either version 2 of the License, or * 00007 * (at your option) any later version. * 00008 * * 00009 * This program is distributed in the hope that it will be useful, * 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00012 * GNU General Public License for more details. * 00013 * * 00014 * You should have received a copy of the GNU General Public License * 00015 * along with this program; If not, see <http://www.gnu.org/licenses/>. * 00016 ***************************************************************************/ 00017 00018 #ifndef KTUTORIAL_OBJECTFINDER_H 00019 #define KTUTORIAL_OBJECTFINDER_H 00020 00021 #include <QtCore/QObject> 00022 #include <QtCore/QRegExp> 00023 00024 #include "ktutorial_export.h" 00025 00026 namespace ktutorial { 00027 00033 class KTUTORIAL_EXPORT ObjectFinder: public QObject { 00034 Q_OBJECT 00035 public: 00036 00042 explicit ObjectFinder(QObject* parent = 0); 00043 00047 virtual ~ObjectFinder(); 00048 00061 template <typename T> 00062 T findObject(const QString& name, const QObject* baseObject) const { 00063 QList<T> candidateObjects; 00064 findObjects<T>(name, baseObject, candidateObjects); 00065 00066 if (candidateObjects.isEmpty()) { 00067 return 0; 00068 } 00069 00070 if (candidateObjects.count() == 1) { 00071 return candidateObjects.first(); 00072 } 00073 00074 return getBestMatch(name, candidateObjects); 00075 } 00076 00077 private: 00078 00079 class ObjectFinderPrivate* d; 00080 00092 template <typename T> 00093 void findObjects(const QString& name, const QObject* ancestor, 00094 QList<T>& foundObjects) const { 00095 if (name.isEmpty() || ancestor == 0) { 00096 return; 00097 } 00098 00099 if (name.indexOf('/') == -1) { 00100 foundObjects.append(ancestor->findChildren<T>(name)); 00101 return; 00102 } 00103 00104 QRegExp slashPattern("/+"); 00105 QString ancestorName = name.left(name.indexOf(slashPattern)); 00106 QString descendantName = name.mid(ancestorName.length() + 00107 slashPattern.matchedLength()); 00108 00109 QList<QObject*> namedAncestors = 00110 ancestor->findChildren<QObject*>(ancestorName); 00111 foreach (QObject* namedAncestor, namedAncestors) { 00112 findObjects<T>(descendantName, namedAncestor, foundObjects); 00113 } 00114 } 00115 00125 template <typename T> 00126 T getBestMatch(const QString& name, QList<T> candidateObjects) const { 00127 QList< QList<QObject*> > objectPaths = getObjectPaths(candidateObjects); 00128 00129 QList<QObject*> bestMatches = getBestMatches(name, objectPaths); 00130 00131 //Should not happen, but just in case 00132 if (bestMatches.isEmpty()) { 00133 return 0; 00134 } 00135 00136 return static_cast<T>(bestMatches[0]); 00137 } 00138 00148 template <typename T> 00149 QList< QList<QObject*> > getObjectPaths(const QList<T> objects) const { 00150 QList< QList<QObject*> > objectPaths; 00151 00152 foreach (T candidateObject, objects) { 00153 QList<QObject*> objectPath; 00154 00155 QObject* ancestor = candidateObject; 00156 while (ancestor) { 00157 objectPath.prepend(ancestor); 00158 ancestor = ancestor->parent(); 00159 } 00160 00161 objectPaths.append(objectPath); 00162 } 00163 00164 return objectPaths; 00165 } 00166 00179 QList<QObject*> getBestMatches(const QString& name, 00180 QList< QList<QObject*> > objectPaths) const; 00181 00196 QList< QList<QObject*> > filterObjectPaths(const QString& name, 00197 const QList< QList<QObject*> >& objectPaths) const; 00198 00210 QList< QList<QObject*> > filterDirectChildren(const QString& name, 00211 const QList< QList<QObject*> >& objectPaths) const; 00212 00228 QList< QList<QObject*> > filterNestedChildrenWithUnnamedAncestors( 00229 const QString& name, const QList< QList<QObject*> >& objectPaths) const; 00230 00244 QList< QList<QObject*> > filterNestedChildren(const QString& name, 00245 const QList< QList<QObject*> >& objectPaths) const; 00246 00247 }; 00248 00249 } 00250 00251 #endif