Solid
predicate.cpp
Go to the documentation of this file.
00001 /* 00002 Copyright 2006 Kevin Ottens <ervin@kde.org> 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Lesser General Public 00006 License as published by the Free Software Foundation; either 00007 version 2.1 of the License, or (at your option) version 3, or any 00008 later version accepted by the membership of KDE e.V. (or its 00009 successor approved by the membership of KDE e.V.), which shall 00010 act as a proxy defined in Section 6 of version 3 of the license. 00011 00012 This library is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Lesser General Public License for more details. 00016 00017 You should have received a copy of the GNU Lesser General Public 00018 License along with this library. If not, see <http://www.gnu.org/licenses/>. 00019 */ 00020 00021 #include "predicate.h" 00022 00023 #include <solid/device.h> 00024 #include <solid/deviceinterface.h> 00025 #include <QtCore/QStringList> 00026 #include <QtCore/QMetaEnum> 00027 00028 namespace Solid 00029 { 00030 class Predicate::Private 00031 { 00032 public: 00033 00034 Private() : isValid(false), type(PropertyCheck), 00035 compOperator(Predicate::Equals), 00036 operand1(0), operand2(0) {} 00037 00038 bool isValid; 00039 Type type; 00040 00041 DeviceInterface::Type ifaceType; 00042 QString property; 00043 QVariant value; 00044 Predicate::ComparisonOperator compOperator; 00045 00046 Predicate *operand1; 00047 Predicate *operand2; 00048 }; 00049 } 00050 00051 00052 Solid::Predicate::Predicate() 00053 : d(new Private()) 00054 { 00055 } 00056 00057 Solid::Predicate::Predicate(const Predicate &other) 00058 : d(new Private()) 00059 { 00060 *this = other; 00061 } 00062 00063 Solid::Predicate::Predicate(const DeviceInterface::Type &ifaceType, 00064 const QString &property, const QVariant &value, 00065 ComparisonOperator compOperator) 00066 : d(new Private()) 00067 { 00068 d->isValid = true; 00069 d->ifaceType = ifaceType; 00070 d->property = property; 00071 d->value = value; 00072 d->compOperator = compOperator; 00073 } 00074 00075 Solid::Predicate::Predicate(const QString &ifaceName, 00076 const QString &property, const QVariant &value, 00077 ComparisonOperator compOperator) 00078 : d(new Private()) 00079 { 00080 DeviceInterface::Type ifaceType = DeviceInterface::stringToType(ifaceName); 00081 00082 if (((int)ifaceType)!=-1) 00083 { 00084 d->isValid = true; 00085 d->ifaceType = ifaceType; 00086 d->property = property; 00087 d->value = value; 00088 d->compOperator = compOperator; 00089 } 00090 } 00091 00092 Solid::Predicate::Predicate(const DeviceInterface::Type &ifaceType) 00093 : d(new Private()) 00094 { 00095 d->isValid = true; 00096 d->type = InterfaceCheck; 00097 d->ifaceType = ifaceType; 00098 } 00099 00100 Solid::Predicate::Predicate(const QString &ifaceName) 00101 : d(new Private()) 00102 { 00103 DeviceInterface::Type ifaceType = DeviceInterface::stringToType(ifaceName); 00104 00105 if (((int)ifaceType)!=-1) 00106 { 00107 d->isValid = true; 00108 d->type = InterfaceCheck; 00109 d->ifaceType = ifaceType; 00110 } 00111 } 00112 00113 Solid::Predicate::~Predicate() 00114 { 00115 if (d->type!=PropertyCheck && d->type!=InterfaceCheck) { 00116 delete d->operand1; 00117 delete d->operand2; 00118 } 00119 00120 delete d; 00121 } 00122 00123 Solid::Predicate &Solid::Predicate::operator=(const Predicate &other) 00124 { 00125 d->isValid = other.d->isValid; 00126 d->type = other.d->type; 00127 00128 if (d->type!=PropertyCheck && d->type!=InterfaceCheck) 00129 { 00130 Predicate* operand1 = new Predicate(*(other.d->operand1)); 00131 delete d->operand1; 00132 d->operand1 = operand1; 00133 Predicate* operand2 = new Predicate(*(other.d->operand2)); 00134 delete d->operand2; 00135 d->operand2 = operand2; 00136 } 00137 else 00138 { 00139 d->ifaceType = other.d->ifaceType; 00140 d->property = other.d->property; 00141 d->value = other.d->value; 00142 d->compOperator = other.d->compOperator; 00143 } 00144 00145 return *this; 00146 } 00147 00148 Solid::Predicate Solid::Predicate::operator &(const Predicate &other) 00149 { 00150 Predicate result; 00151 00152 result.d->isValid = true; 00153 result.d->type = Conjunction; 00154 result.d->operand1 = new Predicate(*this); 00155 result.d->operand2 = new Predicate(other); 00156 00157 return result; 00158 } 00159 00160 Solid::Predicate &Solid::Predicate::operator &=(const Predicate &other) 00161 { 00162 *this = *this & other; 00163 return *this; 00164 } 00165 00166 Solid::Predicate Solid::Predicate::operator|(const Predicate &other) 00167 { 00168 Predicate result; 00169 00170 result.d->isValid = true; 00171 result.d->type = Disjunction; 00172 result.d->operand1 = new Predicate(*this); 00173 result.d->operand2 = new Predicate(other); 00174 00175 return result; 00176 } 00177 00178 Solid::Predicate &Solid::Predicate::operator |=(const Predicate &other) 00179 { 00180 *this = *this | other; 00181 return *this; 00182 } 00183 00184 bool Solid::Predicate::isValid() const 00185 { 00186 return d->isValid; 00187 } 00188 00189 bool Solid::Predicate::matches(const Device &device) const 00190 { 00191 if (!d->isValid) return false; 00192 00193 switch(d->type) 00194 { 00195 case Disjunction: 00196 return d->operand1->matches(device) 00197 || d->operand2->matches(device); 00198 case Conjunction: 00199 return d->operand1->matches(device) 00200 && d->operand2->matches(device); 00201 case PropertyCheck: 00202 { 00203 const DeviceInterface *iface = device.asDeviceInterface(d->ifaceType); 00204 00205 if (iface!=0) 00206 { 00207 const int index = iface->metaObject()->indexOfProperty(d->property.toLatin1()); 00208 QMetaProperty metaProp = iface->metaObject()->property(index); 00209 QVariant value = metaProp.isReadable() ? metaProp.read(iface) : QVariant(); 00210 QVariant expected = d->value; 00211 00212 if (metaProp.isEnumType() && expected.type()==QVariant::String) { 00213 QMetaEnum metaEnum = metaProp.enumerator(); 00214 int value = metaEnum.keysToValue(d->value.toString().toLatin1()); 00215 if (value>=0) { // No value found for these keys, resetting expected to invalid 00216 expected = value; 00217 } else { 00218 expected = QVariant(); 00219 } 00220 } 00221 00222 if (d->compOperator==Mask) { 00223 bool v_ok; 00224 int v = value.toInt(&v_ok); 00225 bool e_ok; 00226 int e = expected.toInt(&e_ok); 00227 00228 return (e_ok && v_ok && (v &e)); 00229 } else { 00230 return (value == expected); 00231 } 00232 } 00233 break; 00234 } 00235 case InterfaceCheck: 00236 return device.isDeviceInterface(d->ifaceType); 00237 } 00238 00239 return false; 00240 } 00241 00242 QSet<Solid::DeviceInterface::Type> Solid::Predicate::usedTypes() const 00243 { 00244 QSet<DeviceInterface::Type> res; 00245 00246 if (d->isValid) { 00247 00248 switch(d->type) 00249 { 00250 case Disjunction: 00251 case Conjunction: 00252 res+= d->operand1->usedTypes(); 00253 res+= d->operand2->usedTypes(); 00254 break; 00255 case PropertyCheck: 00256 case InterfaceCheck: 00257 res << d->ifaceType; 00258 break; 00259 } 00260 00261 } 00262 00263 return res; 00264 } 00265 00266 00267 QString Solid::Predicate::toString() const 00268 { 00269 if (!d->isValid) return "False"; 00270 00271 if (d->type!=PropertyCheck && d->type!=InterfaceCheck) 00272 { 00273 QString op = " AND "; 00274 if (d->type==Disjunction) op = " OR "; 00275 00276 return '['+d->operand1->toString()+op+d->operand2->toString()+']'; 00277 } 00278 else 00279 { 00280 QString ifaceName = DeviceInterface::typeToString(d->ifaceType); 00281 00282 if (ifaceName.isEmpty()) ifaceName = "Unknown"; 00283 00284 if (d->type==InterfaceCheck) { 00285 return "IS "+ifaceName; 00286 } 00287 00288 QString value; 00289 00290 switch (d->value.type()) 00291 { 00292 case QVariant::StringList: 00293 { 00294 value = '{'; 00295 00296 const QStringList list = d->value.toStringList(); 00297 00298 QStringList::ConstIterator it = list.begin(); 00299 QStringList::ConstIterator end = list.end(); 00300 00301 for (; it!=end; ++it) 00302 { 00303 value+= '\''+ *it+'\''; 00304 00305 if (it+1!=end) 00306 { 00307 value+= ", "; 00308 } 00309 } 00310 00311 value+= '}'; 00312 break; 00313 } 00314 case QVariant::Bool: 00315 value = (d->value.toBool()?"true":"false"); 00316 break; 00317 case QVariant::Int: 00318 case QVariant::UInt: 00319 case QVariant::LongLong: 00320 case QVariant::ULongLong: 00321 value = d->value.toString(); 00322 break; 00323 default: 00324 value = '\''+d->value.toString()+'\''; 00325 break; 00326 } 00327 00328 QString str_operator = "=="; 00329 if (d->compOperator!=Equals) str_operator = " &"; 00330 00331 00332 return ifaceName+'.'+d->property+' '+str_operator+' '+value; 00333 } 00334 } 00335 00336 Solid::Predicate::Type Solid::Predicate::type() const 00337 { 00338 return d->type; 00339 } 00340 00341 Solid::DeviceInterface::Type Solid::Predicate::interfaceType() const 00342 { 00343 return d->ifaceType; 00344 } 00345 00346 QString Solid::Predicate::propertyName() const 00347 { 00348 return d->property; 00349 } 00350 00351 QVariant Solid::Predicate::matchingValue() const 00352 { 00353 return d->value; 00354 } 00355 00356 Solid::Predicate::ComparisonOperator Solid::Predicate::comparisonOperator() const 00357 { 00358 return d->compOperator; 00359 } 00360 00361 Solid::Predicate Solid::Predicate::firstOperand() const 00362 { 00363 if( d->operand1 ) { 00364 return *d->operand1; 00365 } 00366 return Predicate(); 00367 } 00368 00369 Solid::Predicate Solid::Predicate::secondOperand() const 00370 { 00371 if( d->operand2 ) { 00372 return *d->operand2; 00373 } 00374 return Predicate(); 00375 } 00376
KDE 4.6 API Reference