[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 "+".<br/>If you want to remove (logical operator NOT) some line, you must prefix your word by "-".<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 ":" 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: "yes, this is a phrase".</p><p><span style=" font-weight:600; text-decoration: underline;">Examples:</span><br/>+val1 +val2 => Keep lines containing val1 OR val2<br/>+val1 -val2 => Keep lines containing val1 but NOT val2<br/>"abc def" => Keep lines containing the sentense "abc def" <br/>abc:def => Keep lines having a column name starting by abc and containing def<br/>:abc:def => Keep lines containing "abc:def"</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 "+".<br/>If you want to remove (logical operator NOT) some line, you must prefix your word by "-".<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 ":" 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: "yes, this is a phrase".</p><p>You can also use operator "<" and ">".</p><p><span style=" font-weight:600; text-decoration: underline;">Examples:</span><br/>+val1 +val2 => Keep lines containing val1 OR val2<br/>+val1 -val2 => Keep lines containing val1 but NOT val2<br/>"abc def" => Keep lines containing the sentense "abc def" <br/>abc:def => Keep lines having a column name starting by abc and containing def<br/>:abc:def => Keep lines containing "abc:def"<br/>Date>2015-03-01 => Keep lines where Date attribute is greater than 2015-03-01<br/>Amount<10 =>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