[kde-doc-english] [skrooge] /: BUG:345719

Stephane Mankowski stephane at mankowski.fr
Thu Apr 2 20:46:48 UTC 2015


Git commit 2aaaafd99d7ddd8a0e0b77db1886b843e79fb2c8 by Stephane Mankowski.
Committed on 02/04/2015 at 20:42.
Pushed by smankowski into branch 'master'.

BUG:345719
Enhance fast search/filter on lists

M  +8    -5    doc/index.docbook
M  +1    -1    skgbasegui/skgfilteredtableview.ui
M  +94   -34   skgbasegui/skgsortfilterproxymodel.cpp
M  +3    -0    skgbasegui/skgsortfilterproxymodel.h

http://commits.kde.org/skrooge/2aaaafd99d7ddd8a0e0b77db1886b843e79fb2c8

diff --git a/doc/index.docbook b/doc/index.docbook
index 20d3c88..96eec8b 100644
--- a/doc/index.docbook
+++ b/doc/index.docbook
@@ -588,16 +588,19 @@
 		<listitem><para>If you want to search only on one column, you must prefix your word by the column name like: col1:word.</para></listitem>
 		<listitem><para>If you want to use the character ":" in value, you must specify the column name like this: col1:value:rest.</para></listitem>
 		<listitem><para>If you want to search for a phrase or something that contains spaces, you must put it in quotes, like: "yes, this is a phrase".</para></listitem>
+		<listitem><para>You can also use operator "<" and ">".</para></listitem>
 	    </itemizedlist>
 	  <para>
 	    Some examples are better to explain:
 	  </para>
 	    <itemizedlist>
-	      <listitem><para>+val1 +val2 => Keep lines containing val1 OR val2</para></listitem>
-	      <listitem><para>+val1 -val2 => Keep lines containing val1 but NOT val2</para></listitem>
-	      <listitem><para>"abc def" => Keep lines containing the sentense "abc def"</para></listitem>
-	      <listitem><para>abc:def => Keep lines having a column name starting by abc and containing def</para></listitem>
-	      <listitem><para>:abc:def => Keep lines containing "abc:def"</para></listitem>
+	      <listitem><para>+val1 +val2 => Keep lines containing val1 OR val2</para></listitem>
+	      <listitem><para>+val1 -val2 => Keep lines containing val1 but NOT val2</para></listitem>
+	      <listitem><para>"abc def" => Keep lines containing the sentense "abc def"</para></listitem>
+	      <listitem><para>abc:def => Keep lines having a column name starting by abc and containing def</para></listitem>
+	      <listitem><para>:abc:def => Keep lines containing "abc:def"</para></listitem>
+	      <listitem><para>Date>2015-03-01 => Keep lines where Date attribute is greater than 2015-03-01</para></listitem>
+	      <listitem><para>Amount<10 =>Keep lines where Amount attribute is less than 10</para></listitem>
 	    </itemizedlist>
 	</tip>
 	</sect3>
diff --git a/skgbasegui/skgfilteredtableview.ui b/skgbasegui/skgfilteredtableview.ui
index c225272..a3670ed 100644
--- a/skgbasegui/skgfilteredtableview.ui
+++ b/skgbasegui/skgfilteredtableview.ui
@@ -101,7 +101,7 @@
         <enum>Qt::WheelFocus</enum>
        </property>
        <property name="toolTip">
-        <string><html><head/><body><p>Searching is case-insensitive. So table, Table, and TABLE are all the same.<br/>If you just put a word or series of words in the search box, the application will filter the table to keep all lines having these words (logical operator AND). <br/>If you want to add (logical operator OR) some line, you must prefix your word by &quot;+&quot;.<br/>If you want to remove (logical operator NOT) some line, you must prefix your word by &quot;-&quot;.<br/>If you want to search only on one column, you must prefix your word by the column name like: col1:word.</p><p>If you want to use the character &quot;:&quot; in value, you must specify the column name like this: col1:value:rest.<br/>If you want to search for a phrase or something that contains spaces, you must put it in quotes, like: &quot;yes, this is a phrase&quot;.</p><p><span style=" font-weight:600; text-decoration: underline;">Examples:</span><br/>+val1 +val2 =&gt; Keep lines containing val1 OR val2<br/>+val1 -val2 =&gt; Keep lines containing val1 but NOT val2<br/>&quot;abc def&quot; =&gt; Keep lines containing the sentense &quot;abc def&quot; <br/>abc:def =&gt; Keep lines having a column name starting by abc and containing def<br/>:abc:def =&gt; Keep lines containing &quot;abc:def&quot;</p></body></html></string>
+        <string><html><head/><body><p>Searching is case-insensitive. So table, Table, and TABLE are all the same.<br/>If you just put a word or series of words in the search box, the application will filter the table to keep all lines having these words (logical operator AND). <br/>If you want to add (logical operator OR) some line, you must prefix your word by &quot;+&quot;.<br/>If you want to remove (logical operator NOT) some line, you must prefix your word by &quot;-&quot;.<br/>If you want to search only on one column, you must prefix your word by the column name like: col1:word.<br/>If you want to use the character &quot;:&quot; in value, you must specify the column name like this: col1:value:rest.<br/>If you want to search for a phrase or something that contains spaces, you must put it in quotes, like: &quot;yes, this is a phrase&quot;.</p><p>You can also use operator &quot;&lt;&quot; and &quot;&gt;&quot;.</p><p><span style=" font-weight:600; text-decoration: underline;">Examples:</span><br/>+val1 +val2 =&gt; Keep lines containing val1 OR val2<br/>+val1 -val2 =&gt; Keep lines containing val1 but NOT val2<br/>&quot;abc def&quot; =&gt; Keep lines containing the sentense &quot;abc def&quot; <br/>abc:def =&gt; Keep lines having a column name starting by abc and containing def<br/>:abc:def =&gt; Keep lines containing &quot;abc:def&quot;<br/>Date&gt;2015-03-01 =&gt; Keep lines where Date attribute is greater than 2015-03-01<br/>Amount&lt;10 =&gt;Keep lines where Amount attribute is less than 10</p></body></html></string>
        </property>
       </widget>
      </item>
diff --git a/skgbasegui/skgsortfilterproxymodel.cpp b/skgbasegui/skgsortfilterproxymodel.cpp
index 9c12558..f00d9e5 100644
--- a/skgbasegui/skgsortfilterproxymodel.cpp
+++ b/skgbasegui/skgsortfilterproxymodel.cpp
@@ -125,42 +125,82 @@ bool SKGSortFilterProxyModel::lessThan(const QModelIndex& left,
         } else {
             // For better performances, and avoid too many calls to QAbstractItemModel::data
             // return QSortFilterProxyModel::lessThan(left, right);
-            switch (leftData.userType()) {
-            case QVariant::Invalid:
-                return (rightData.type() != QVariant::Invalid);
-            case QVariant::Int:
-                return leftData.toInt() < rightData.toInt();
-            case QVariant::UInt:
-                return leftData.toUInt() < rightData.toUInt();
-            case QVariant::LongLong:
-                return leftData.toLongLong() < rightData.toLongLong();
-            case QVariant::ULongLong:
-                return leftData.toULongLong() < rightData.toULongLong();
-            case QMetaType::Float:
-                return leftData.toFloat() < rightData.toFloat();
-            case QVariant::Double:
-                return leftData.toDouble() < rightData.toDouble();
-            case QVariant::Char:
-                return leftData.toChar() < rightData.toChar();
-            case QVariant::Date:
-                return leftData.toDate() < rightData.toDate();
-            case QVariant::Time:
-                return leftData.toTime() < rightData.toTime();
-            case QVariant::DateTime:
-                return leftData.toDateTime() < rightData.toDateTime();
-            case QVariant::String:
-            default:
-                if (this->isSortLocaleAware()) {
-                    return leftData.toString().localeAwareCompare(rightData.toString()) < 0;
-                } else {
-                    return leftData.toString().compare(rightData.toString(), this->sortCaseSensitivity()) < 0;
-                }
-            }
+            return lessThan(leftData, rightData);
         }
     }
     return false;
 }
 
+bool SKGSortFilterProxyModel::lessThan(const QVariant& iLeftData, const QVariant& iRightData) const
+{
+    switch (iLeftData.userType()) {
+    case QVariant::Invalid:
+        return (iRightData.type() != QVariant::Invalid);
+    case QVariant::Int:
+        return iLeftData.toInt() < iRightData.toInt();
+    case QVariant::UInt:
+        return iLeftData.toUInt() < iRightData.toUInt();
+    case QVariant::LongLong:
+        return iLeftData.toLongLong() < iRightData.toLongLong();
+    case QVariant::ULongLong:
+        return iLeftData.toULongLong() < iRightData.toULongLong();
+    case QMetaType::Float:
+        return iLeftData.toFloat() < iRightData.toFloat();
+    case QVariant::Double:
+        return iLeftData.toDouble() < iRightData.toDouble();
+    case QVariant::Char:
+        return iLeftData.toChar() < iRightData.toChar();
+    case QVariant::Date:
+        return iLeftData.toDate() < iRightData.toDate();
+    case QVariant::Time:
+        return iLeftData.toTime() < iRightData.toTime();
+    case QVariant::DateTime:
+        return iLeftData.toDateTime() < iRightData.toDateTime();
+    case QVariant::String:
+    default:
+        if (this->isSortLocaleAware()) {
+            return iLeftData.toString().localeAwareCompare(iRightData.toString()) < 0;
+        } else {
+            return iLeftData.toString().compare(iRightData.toString(), this->sortCaseSensitivity()) < 0;
+        }
+    }
+}
+
+bool SKGSortFilterProxyModel::moreThan(const QVariant& iLeftData, const QVariant& iRightData) const
+{
+    switch (iLeftData.userType()) {
+    case QVariant::Invalid:
+        return (iRightData.type() != QVariant::Invalid);
+    case QVariant::Int:
+        return iLeftData.toInt() > iRightData.toInt();
+    case QVariant::UInt:
+        return iLeftData.toUInt() > iRightData.toUInt();
+    case QVariant::LongLong:
+        return iLeftData.toLongLong() > iRightData.toLongLong();
+    case QVariant::ULongLong:
+        return iLeftData.toULongLong() > iRightData.toULongLong();
+    case QMetaType::Float:
+        return iLeftData.toFloat() > iRightData.toFloat();
+    case QVariant::Double:
+        return iLeftData.toDouble() > iRightData.toDouble();
+    case QVariant::Char:
+        return iLeftData.toChar() > iRightData.toChar();
+    case QVariant::Date:
+        return iLeftData.toDate() > iRightData.toDate();
+    case QVariant::Time:
+        return iLeftData.toTime() > iRightData.toTime();
+    case QVariant::DateTime:
+        return iLeftData.toDateTime() > iRightData.toDateTime();
+    case QVariant::String:
+    default:
+        if (this->isSortLocaleAware()) {
+            return iLeftData.toString().localeAwareCompare(iRightData.toString()) < 0;
+        } else {
+            return iLeftData.toString().compare(iRightData.toString(), this->sortCaseSensitivity()) > 0;
+        }
+    }
+}
+
 bool SKGSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const
 {
     _SKGTRACEINFUNC(10);
@@ -214,11 +254,22 @@ bool SKGSortFilterProxyModel::filterAcceptsRowWords(int source_row, const QModel
         for (int w = 0; output && w < nbwords; ++w) {
             QString word = iWords.at(w);
             QString att;
+            QChar op = ':';
 
             // Check if the word follows the format attribut:value
             int pos = word.indexOf(':');
+            int pos2 = word.indexOf('<');
+            int pos3 = word.indexOf('>');
+            if (pos2 != -1 && (pos2 < pos || pos == -1)) {
+                pos = pos2;
+            }
+            if (pos3 != -1 && (pos3 < pos || pos == -1)) {
+                pos = pos3;
+            }
+
             if (pos != -1) {
                 att = word.left(pos);
+                op = word[pos];
                 word = word.right(word.count() - pos - 1);
             }
 
@@ -230,10 +281,19 @@ bool SKGSortFilterProxyModel::filterAcceptsRowWords(int source_row, const QModel
                 if (index0.isValid()) {
                     // Check if the header validates the attribut
                     if (att.isEmpty() || model->headerData(i, Qt::Horizontal).toString().startsWith(att, Qt::CaseInsensitive)) {
+
                         // Check if the value validate the attribute
-                        output = model->data(index0).toString().contains(word , Qt::CaseInsensitive);
-                        if (!output) {
-                            output = model->data(index0, Qt::UserRole).toString().contains(word , Qt::CaseInsensitive);
+                        if (op == ':') {
+                            output = model->data(index0).toString().contains(word , Qt::CaseInsensitive);
+                            if (!output) {
+                                output = model->data(index0, Qt::UserRole).toString().contains(word , Qt::CaseInsensitive);
+                            }
+                        } else if (op == '<') {
+                            QVariant var = model->data(index0, Qt::UserRole);
+                            output = lessThan(var, QVariant(word));
+                        } else if (op == '>') {
+                            QVariant var = model->data(index0, Qt::UserRole);
+                            output = moreThan(var, QVariant(word));
                         }
                     }
                 }
diff --git a/skgbasegui/skgsortfilterproxymodel.h b/skgbasegui/skgsortfilterproxymodel.h
index 864e754..6a39643 100644
--- a/skgbasegui/skgsortfilterproxymodel.h
+++ b/skgbasegui/skgsortfilterproxymodel.h
@@ -84,6 +84,9 @@ protected:
 private:
     bool filterAcceptsRowWords(int source_row, const QModelIndex& source_parent, const QStringList& iWords) const;
 
+    bool lessThan(const QVariant& iLeftData, const QVariant& iRightData) const;
+    bool moreThan(const QVariant& iLeftData, const QVariant& iRightData) const;
+
     SKGSortFilterProxyModelPrivate* const d;
 };
 



More information about the kde-doc-english mailing list