tests/auto/qcompleter/tst_qcompleter.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the test suite of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 #include <QtGui>
       
    42 #include "qcompleter.h"
       
    43 
       
    44 #include <QtTest/QtTest>
       
    45 #include <QtGui>
       
    46 #include <QtDebug>
       
    47 #include <QPair>
       
    48 #include <QList>
       
    49 #include <QPointer>
       
    50 
       
    51 #include "../../shared/util.h"
       
    52 
       
    53 //TESTED_CLASS=
       
    54 //TESTED_FILES=
       
    55 
       
    56 class CsvCompleter : public QCompleter
       
    57 {
       
    58     Q_OBJECT
       
    59 public:
       
    60     CsvCompleter(QObject *parent = 0) : QCompleter(parent), csv(true) { }
       
    61 
       
    62     QString pathFromIndex(const QModelIndex& sourceIndex) const;
       
    63 
       
    64     void setCsvCompletion(bool set) { csv = set; }
       
    65 
       
    66 protected:
       
    67     QStringList splitPath(const QString &path) const {
       
    68         return csv ? path.split(",") : QCompleter::splitPath(path);
       
    69     }
       
    70 
       
    71 private:
       
    72     bool csv;
       
    73 };
       
    74 
       
    75 QString CsvCompleter::pathFromIndex(const QModelIndex& si) const
       
    76 {
       
    77     if (!csv)
       
    78         return QCompleter::pathFromIndex(si);
       
    79 
       
    80     if (!si.isValid())
       
    81         return QString();
       
    82 
       
    83     QModelIndex idx = si;
       
    84     QStringList list;
       
    85     do {
       
    86         QString t = model()->data(idx, completionRole()).toString();
       
    87         list.prepend(t);
       
    88         QModelIndex parent = idx.parent();
       
    89         idx = parent.sibling(parent.row(), si.column());
       
    90     } while (idx.isValid());
       
    91 
       
    92     if (list.count() == 1)
       
    93         return list[0];
       
    94     return list.join(",");
       
    95 }
       
    96 
       
    97 class tst_QCompleter : public QObject
       
    98 {
       
    99     Q_OBJECT
       
   100 public:
       
   101     tst_QCompleter();
       
   102     ~tst_QCompleter();
       
   103 
       
   104 private slots:
       
   105     void getSetCheck();
       
   106 
       
   107     void multipleWidgets();
       
   108     void focusIn();
       
   109 
       
   110     void csMatchingOnCsSortedModel_data();
       
   111     void csMatchingOnCsSortedModel();
       
   112     void ciMatchingOnCiSortedModel_data();
       
   113     void ciMatchingOnCiSortedModel();
       
   114 
       
   115     void ciMatchingOnCsSortedModel_data();
       
   116     void ciMatchingOnCsSortedModel();
       
   117     void csMatchingOnCiSortedModel_data();
       
   118     void csMatchingOnCiSortedModel();
       
   119 
       
   120     void directoryModel_data();
       
   121     void directoryModel();
       
   122 
       
   123     void changingModel_data();
       
   124     void changingModel();
       
   125 
       
   126     void sortedEngineRowCount_data();
       
   127     void sortedEngineRowCount();
       
   128     void unsortedEngineRowCount_data();
       
   129     void unsortedEngineRowCount();
       
   130 
       
   131     void currentRow();
       
   132     void sortedEngineMapFromSource();
       
   133     void unsortedEngineMapFromSource();
       
   134 
       
   135     void historySearch();
       
   136 
       
   137     void modelDeletion();
       
   138     void setters();
       
   139 
       
   140     void dynamicSortOrder();
       
   141     void disabledItems();
       
   142 
       
   143     // task-specific tests below me
       
   144     void task178797_activatedOnReturn();
       
   145     void task189564_omitNonSelectableItems();
       
   146     void task246056_setCompletionPrefix();
       
   147     void task250064_lostFocus();
       
   148 
       
   149     void task253125_lineEditCompletion_data();
       
   150     void task253125_lineEditCompletion();
       
   151     void task247560_keyboardNavigation();
       
   152 
       
   153 private:
       
   154     void filter();
       
   155     void testRowCount();
       
   156     enum ModelType {
       
   157         CASE_SENSITIVELY_SORTED_MODEL,
       
   158         CASE_INSENSITIVELY_SORTED_MODEL,
       
   159         DIRECTORY_MODEL,
       
   160         HISTORY_MODEL
       
   161     };
       
   162     void setSourceModel(ModelType);
       
   163 
       
   164     CsvCompleter *completer;
       
   165     QTreeWidget *treeWidget;
       
   166     const int completionColumn;
       
   167     const int columnCount;
       
   168 };
       
   169 
       
   170 tst_QCompleter::tst_QCompleter() : completer(0), completionColumn(0), columnCount(3)
       
   171 {
       
   172     treeWidget = new QTreeWidget;
       
   173     treeWidget->setColumnCount(columnCount);
       
   174 }
       
   175 
       
   176 tst_QCompleter::~tst_QCompleter()
       
   177 {
       
   178     delete treeWidget;
       
   179     delete completer;
       
   180 }
       
   181 
       
   182 void tst_QCompleter::setSourceModel(ModelType type)
       
   183 {
       
   184     QString text;
       
   185     QTreeWidgetItem *parent, *child;
       
   186     treeWidget->clear();
       
   187     switch(type) {
       
   188     case CASE_SENSITIVELY_SORTED_MODEL:
       
   189         // Creates a tree model with top level items P0, P1, .., p0, p1,..
       
   190         // Each of these items parents have children (for P0 - c0P0, c1P0,...)
       
   191         for (int i = 0; i < 2; i++) {
       
   192             for (int j = 0; j < 5; j++) {
       
   193                 parent = new QTreeWidgetItem(treeWidget);
       
   194                 text.sprintf("%c%i", i == 0 ? 'P' : 'p', j);
       
   195                 parent->setText(completionColumn, text);
       
   196                 for (int k = 0; k < 5; k++) {
       
   197                     child = new QTreeWidgetItem(parent);
       
   198                     QString t = QString().sprintf("c%i", k) + text;
       
   199                     child->setText(completionColumn, t);
       
   200                 }
       
   201             }
       
   202         }
       
   203         completer->setModel(treeWidget->model());
       
   204         completer->setCompletionColumn(completionColumn);
       
   205         break;
       
   206     case CASE_INSENSITIVELY_SORTED_MODEL:
       
   207     case HISTORY_MODEL:
       
   208         // Creates a tree model with top level items P0, p0, P1, p1,...
       
   209         // Each of these items have children c0p0, c1p0,..
       
   210         for (int i = 0; i < 5; i++) {
       
   211             for (int j = 0; j < 2; j++) {
       
   212                 parent = new QTreeWidgetItem(treeWidget);
       
   213                 text.sprintf("%c%i", j == 0 ? 'P' : 'p', i);
       
   214                 parent->setText(completionColumn, text);
       
   215                 for (int k = 0; k < 5; k++) {
       
   216                     child = new QTreeWidgetItem(parent);
       
   217                     QString t = QString().sprintf("c%i", k) + text;
       
   218                     child->setText(completionColumn, t);
       
   219                 }
       
   220             }
       
   221         }
       
   222         completer->setModel(treeWidget->model());
       
   223         completer->setCompletionColumn(completionColumn);
       
   224         if (type == CASE_INSENSITIVELY_SORTED_MODEL)
       
   225             break;
       
   226         parent = new QTreeWidgetItem(treeWidget);
       
   227         parent->setText(completionColumn, QLatin1String("p3,c3p3"));
       
   228         parent = new QTreeWidgetItem(treeWidget);
       
   229         parent->setText(completionColumn, QLatin1String("p2,c4p2"));
       
   230         break;
       
   231     case DIRECTORY_MODEL:
       
   232         completer->setCsvCompletion(false);
       
   233         completer->setModel(new QDirModel(completer));
       
   234         completer->setCompletionColumn(0);
       
   235         break;
       
   236     default:
       
   237         qDebug() << "Invalid type";
       
   238     }
       
   239 }
       
   240 
       
   241 void tst_QCompleter::filter()
       
   242 {
       
   243     QFETCH(QString, filterText);
       
   244     QFETCH(QString, step);
       
   245     QFETCH(QString, completion);
       
   246     QFETCH(QString, completionText);
       
   247 
       
   248     if (filterText.compare("FILTERING_OFF", Qt::CaseInsensitive) == 0) {
       
   249         completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
       
   250         return;
       
   251     }
       
   252 
       
   253     completer->setCompletionPrefix(filterText);
       
   254 
       
   255     for (int i = 0; i < step.length(); i++) {
       
   256         int row = completer->currentRow();
       
   257         switch (step[i].toUpper().toAscii()) {
       
   258         case 'P': --row; break;
       
   259         case 'N': ++row; break;
       
   260         case 'L': row = completer->completionCount() - 1; break;
       
   261         case 'F': row = 0; break;
       
   262         default:
       
   263             Q_ASSERT(false);
       
   264         }
       
   265         completer->setCurrentRow(row);
       
   266     }
       
   267 
       
   268     //QModelIndex si = completer->currentIndex();
       
   269     //QCOMPARE(completer->model()->data(si).toString(), completion);
       
   270     QCOMPARE(completer->currentCompletion(), completionText);
       
   271 }
       
   272 
       
   273 // Testing get/set functions
       
   274 void tst_QCompleter::getSetCheck()
       
   275 {
       
   276     QStandardItemModel model(3,3);
       
   277     QCompleter completer(&model);
       
   278 
       
   279     // QString QCompleter::completionPrefix()
       
   280     // void QCompleter::setCompletionPrefix(QString)
       
   281     completer.setCompletionPrefix(QString("te"));
       
   282     QCOMPARE(completer.completionPrefix(), QString("te"));
       
   283     completer.setCompletionPrefix(QString());
       
   284     QCOMPARE(completer.completionPrefix(), QString());
       
   285 
       
   286     // ModelSorting QCompleter::modelSorting()
       
   287     // void QCompleter::setModelSorting(ModelSorting)
       
   288     completer.setModelSorting(QCompleter::CaseSensitivelySortedModel);
       
   289     QCOMPARE(completer.modelSorting(), QCompleter::CaseSensitivelySortedModel);
       
   290     completer.setModelSorting(QCompleter::CaseInsensitivelySortedModel);
       
   291     QCOMPARE(completer.modelSorting(), QCompleter::CaseInsensitivelySortedModel);
       
   292     completer.setModelSorting(QCompleter::UnsortedModel);
       
   293     QCOMPARE(completer.modelSorting(), QCompleter::UnsortedModel);
       
   294 
       
   295     // CompletionMode QCompleter::completionMode()
       
   296     // void QCompleter::setCompletionMode(CompletionMode)
       
   297     QCOMPARE(completer.completionMode(), QCompleter::PopupCompletion); // default value
       
   298     completer.setCompletionMode(QCompleter::UnfilteredPopupCompletion);
       
   299     QCOMPARE(completer.completionMode(), QCompleter::UnfilteredPopupCompletion);
       
   300     completer.setCompletionMode(QCompleter::InlineCompletion);
       
   301     QCOMPARE(completer.completionMode(), QCompleter::InlineCompletion);
       
   302 
       
   303     // int QCompleter::completionColumn()
       
   304     // void QCompleter::setCompletionColumn(int)
       
   305     completer.setCompletionColumn(2);
       
   306     QCOMPARE(completer.completionColumn(), 2);
       
   307     completer.setCompletionColumn(1);
       
   308     QCOMPARE(completer.completionColumn(), 1);
       
   309 
       
   310     // int QCompleter::completionRole()
       
   311     // void QCompleter::setCompletionRole(int)
       
   312     QCOMPARE(completer.completionRole(), static_cast<int>(Qt::EditRole)); // default value
       
   313     completer.setCompletionRole(Qt::DisplayRole);
       
   314     QCOMPARE(completer.completionRole(), static_cast<int>(Qt::DisplayRole));
       
   315 
       
   316     // int QCompleter::maxVisibleItems()
       
   317     // void QCompleter::setMaxVisibleItems(int)
       
   318     QCOMPARE(completer.maxVisibleItems(), 7); // default value
       
   319     completer.setMaxVisibleItems(10);
       
   320     QCOMPARE(completer.maxVisibleItems(), 10);
       
   321     QTest::ignoreMessage(QtWarningMsg, "QCompleter::setMaxVisibleItems: "
       
   322                          "Invalid max visible items (-2147483648) must be >= 0");
       
   323     completer.setMaxVisibleItems(INT_MIN);
       
   324     QCOMPARE(completer.maxVisibleItems(), 10); // Cannot be set to something negative => old value
       
   325 
       
   326     // Qt::CaseSensitivity QCompleter::caseSensitivity()
       
   327     // void QCompleter::setCaseSensitivity(Qt::CaseSensitivity)
       
   328     QCOMPARE(completer.caseSensitivity(), Qt::CaseSensitive); // default value
       
   329     completer.setCaseSensitivity(Qt::CaseInsensitive);
       
   330     QCOMPARE(completer.caseSensitivity(), Qt::CaseInsensitive);
       
   331 
       
   332     // bool QCompleter::wrapAround()
       
   333     // void QCompleter::setWrapAround(bool)
       
   334     QCOMPARE(completer.wrapAround(), true); // default value
       
   335     completer.setWrapAround(false);
       
   336     QCOMPARE(completer.wrapAround(), false);
       
   337 }
       
   338 
       
   339 void tst_QCompleter::csMatchingOnCsSortedModel_data()
       
   340 {
       
   341     delete completer;
       
   342     completer = new CsvCompleter;
       
   343     completer->setModelSorting(QCompleter::CaseSensitivelySortedModel);
       
   344     completer->setCaseSensitivity(Qt::CaseSensitive);
       
   345     setSourceModel(CASE_SENSITIVELY_SORTED_MODEL);
       
   346 
       
   347     QTest::addColumn<QString>("filterText");
       
   348     QTest::addColumn<QString>("step");
       
   349     QTest::addColumn<QString>("completion");
       
   350     QTest::addColumn<QString>("completionText");
       
   351 
       
   352     for (int i = 0; i < 2; i++) {
       
   353          if (i == 1)
       
   354              QTest::newRow("FILTERING_OFF") << "FILTERING_OFF" << "" << "" << "";
       
   355 
       
   356          // Plain text filter
       
   357          QTest::newRow("()") << "" << "" << "P0" << "P0";
       
   358          QTest::newRow("()F") << "" << "F" << "P0" << "P0";
       
   359          QTest::newRow("()L") << "" << "L" << "p4" << "p4";
       
   360          QTest::newRow("()L") << "" << "L" << "p4" << "p4";
       
   361          QTest::newRow("()N") << "" << "N" << "P1" << "P1";
       
   362          QTest::newRow("(P)") << "P" << "" << "P0" << "P0";
       
   363          QTest::newRow("(P)F") << "P" << "" << "P0" << "P0";
       
   364          QTest::newRow("(P)L") << "P" << "L" << "P4" << "P4";
       
   365          QTest::newRow("(p)") << "p" << "" << "p0" << "p0";
       
   366          QTest::newRow("(p)N") << "p" << "N" << "p1" << "p1";
       
   367          QTest::newRow("(p)NN") << "p" << "NN" << "p2" << "p2";
       
   368          QTest::newRow("(p)NNN") << "p" << "NNN" << "p3" << "p3";
       
   369          QTest::newRow("(p)NNNN") << "p" << "NNNN" << "p4" << "p4";
       
   370          QTest::newRow("(p1)") << "p1" << "" << "p1" << "p1";
       
   371          QTest::newRow("(p11)") << "p11" << "" << "" << "";
       
   372 
       
   373          // Tree filter
       
   374          QTest::newRow("(P0,)") << "P0," << "" << "c0P0" << "P0,c0P0";
       
   375          QTest::newRow("(P0,c)") << "P0,c" << "" << "c0P0" << "P0,c0P0";
       
   376          QTest::newRow("(P0,c1)") << "P0,c1" << "" << "c1P0" << "P0,c1P0";
       
   377          QTest::newRow("(P0,c3P0)") << "P0,c3P0" << "" << "c3P0" << "P0,c3P0";
       
   378          QTest::newRow("(P3,c)F") << "P3,c" << "F" << "c0P3" << "P3,c0P3";
       
   379          QTest::newRow("(P3,c)L") << "P3,c" << "L" << "c4P3" << "P3,c4P3";
       
   380          QTest::newRow("(P3,c)N") << "P3,c" << "N" << "c1P3" << "P3,c1P3";
       
   381          QTest::newRow("(P3,c)NN") << "P3,c" << "NN" << "c2P3" << "P3,c2P3";
       
   382          QTest::newRow("(P3,,c)") << "P3,,c" << "" << "" << "";
       
   383          QTest::newRow("(P3,c0P3,)") << "P3,c0P3," << "" << "" << "";
       
   384          QTest::newRow("(P,)") << "P," << "" << "" << "";
       
   385      }
       
   386 }
       
   387 
       
   388 void tst_QCompleter::csMatchingOnCsSortedModel()
       
   389 {
       
   390     filter();
       
   391 }
       
   392 
       
   393 void tst_QCompleter::ciMatchingOnCiSortedModel_data()
       
   394 {
       
   395     delete completer;
       
   396     completer = new CsvCompleter;
       
   397     completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
       
   398     completer->setCaseSensitivity(Qt::CaseInsensitive);
       
   399     setSourceModel(CASE_INSENSITIVELY_SORTED_MODEL);
       
   400 
       
   401     QTest::addColumn<QString>("filterText");
       
   402     QTest::addColumn<QString>("step");
       
   403     QTest::addColumn<QString>("completion");
       
   404     QTest::addColumn<QString>("completionText");
       
   405 
       
   406     for (int i = 0; i < 2; i++) {
       
   407         if (i == 1)
       
   408             QTest::newRow("FILTERING_OFF") << "FILTERING_OFF" << "" << "" << "";
       
   409 
       
   410         // Plain text filter
       
   411         QTest::newRow("()") << "" << "" << "P0" << "P0";
       
   412         QTest::newRow("()F") << "" << "F" << "P0" << "P0";
       
   413         QTest::newRow("()L") << "" << "L" << "p4" << "p4";
       
   414         QTest::newRow("()N") << "" << "N" << "p0" << "p0";
       
   415         QTest::newRow("(P)") << "P" << "" << "P0" << "P0";
       
   416         QTest::newRow("(P)F") << "P" << "" << "P0" << "P0";
       
   417         QTest::newRow("(P)L") << "P" << "L" << "p4" << "p4";
       
   418         QTest::newRow("(p)") << "p" << "" << "P0" << "P0";
       
   419         QTest::newRow("(p)N") << "p" << "N" << "p0" << "p0";
       
   420         QTest::newRow("(p)NN") << "p" << "NN" << "P1" << "P1";
       
   421         QTest::newRow("(p)NNN") << "p" << "NNN" << "p1" << "p1";
       
   422         QTest::newRow("(p1)") << "p1" << "" << "P1" << "P1";
       
   423         QTest::newRow("(p1)N") << "p1" << "N" << "p1" << "p1";
       
   424         QTest::newRow("(p11)") << "p11" << "" << "" << "";
       
   425 
       
   426         //// Tree filter
       
   427         QTest::newRow("(p0,)") << "p0," << "" << "c0P0" << "P0,c0P0";
       
   428         QTest::newRow("(p0,c)") << "p0,c" << "" << "c0P0" << "P0,c0P0";
       
   429         QTest::newRow("(p0,c1)") << "p0,c1" << "" << "c1P0" << "P0,c1P0";
       
   430         QTest::newRow("(p0,c3P0)") << "p0,c3P0" << "" << "c3P0" << "P0,c3P0";
       
   431         QTest::newRow("(p3,c)F") << "p3,c" << "F" << "c0P3" << "P3,c0P3";
       
   432         QTest::newRow("(p3,c)L") << "p3,c" << "L" << "c4P3" << "P3,c4P3";
       
   433         QTest::newRow("(p3,c)N") << "p3,c" << "N" << "c1P3" << "P3,c1P3";
       
   434         QTest::newRow("(p3,c)NN") << "p3,c" << "NN" << "c2P3" << "P3,c2P3";
       
   435         QTest::newRow("(p3,,c)") << "p3,,c" << "" << "" << "";
       
   436         QTest::newRow("(p3,c0P3,)") << "p3,c0P3," << "" << "" << "";
       
   437         QTest::newRow("(p,)") << "p," << "" << "" << "";
       
   438     }
       
   439 }
       
   440 
       
   441 void tst_QCompleter::ciMatchingOnCiSortedModel()
       
   442 {
       
   443     filter();
       
   444 }
       
   445 
       
   446 void tst_QCompleter::ciMatchingOnCsSortedModel_data()
       
   447 {
       
   448     delete completer;
       
   449     completer = new CsvCompleter;
       
   450     completer->setModelSorting(QCompleter::CaseSensitivelySortedModel);
       
   451     setSourceModel(CASE_SENSITIVELY_SORTED_MODEL);
       
   452     completer->setCaseSensitivity(Qt::CaseInsensitive);
       
   453 
       
   454     QTest::addColumn<QString>("filterText");
       
   455     QTest::addColumn<QString>("step");
       
   456     QTest::addColumn<QString>("completion");
       
   457     QTest::addColumn<QString>("completionText");
       
   458 
       
   459     for (int i = 0; i < 2; i++) {
       
   460         if (i == 1)
       
   461             QTest::newRow("FILTERING_OFF") << "FILTERING_OFF" << "" << "" << "";
       
   462 
       
   463         // Plain text filter
       
   464         QTest::newRow("()") << "" << "" << "P0" << "P0";
       
   465         QTest::newRow("()F") << "" << "F" << "P0" << "P0";
       
   466         QTest::newRow("()L") << "" << "L" << "p4" << "p4";
       
   467         QTest::newRow("(P)") << "P" << "" << "P0" << "P0";
       
   468         QTest::newRow("(P)F") << "P" << "" << "P0" << "P0";
       
   469         QTest::newRow("(P)L") << "P" << "L" << "p4" << "p4";
       
   470         QTest::newRow("(p)") << "p" << "" << "P0" << "P0";
       
   471         QTest::newRow("(p)N") << "p" << "N" << "P1" << "P1";
       
   472         QTest::newRow("(p)NN") << "p" << "NN" << "P2" << "P2";
       
   473         QTest::newRow("(p)NNN") << "p" << "NNN" << "P3" << "P3";
       
   474         QTest::newRow("(p1)") << "p1" << "" << "P1" << "P1";
       
   475         QTest::newRow("(p1)N") << "p1" << "N" << "p1" << "p1";
       
   476         QTest::newRow("(p11)") << "p11" << "" << "" << "";
       
   477 
       
   478         // Tree filter
       
   479         QTest::newRow("(p0,)") << "p0," << "" << "c0P0" << "P0,c0P0";
       
   480         QTest::newRow("(p0,c)") << "p0,c" << "" << "c0P0" << "P0,c0P0";
       
   481         QTest::newRow("(p0,c1)") << "p0,c1" << "" << "c1P0" << "P0,c1P0";
       
   482         QTest::newRow("(p0,c3P0)") << "p0,c3P0" << "" << "c3P0" << "P0,c3P0";
       
   483         QTest::newRow("(p3,c)F") << "p3,c" << "F" << "c0P3" << "P3,c0P3";
       
   484         QTest::newRow("(p3,c)L") << "p3,c" << "L" << "c4P3" << "P3,c4P3";
       
   485         QTest::newRow("(p3,c)N") << "p3,c" << "N" << "c1P3" << "P3,c1P3";
       
   486         QTest::newRow("(p3,c)NN") << "p3,c" << "NN" << "c2P3" << "P3,c2P3";
       
   487         QTest::newRow("(p3,,c)") << "p3,,c" << "" << "" << "";
       
   488         QTest::newRow("(p3,c0P3,)") << "p3,c0P3," << "" << "" << "";
       
   489         QTest::newRow("(p,)") << "p," << "" << "" << "";
       
   490     }
       
   491 }
       
   492 
       
   493 void tst_QCompleter::ciMatchingOnCsSortedModel()
       
   494 {
       
   495     filter();
       
   496 }
       
   497 
       
   498 void tst_QCompleter::csMatchingOnCiSortedModel_data()
       
   499 {
       
   500     delete completer;
       
   501     completer = new CsvCompleter;
       
   502     completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
       
   503     setSourceModel(CASE_INSENSITIVELY_SORTED_MODEL);
       
   504     completer->setCaseSensitivity(Qt::CaseSensitive);
       
   505 
       
   506     QTest::addColumn<QString>("filterText");
       
   507     QTest::addColumn<QString>("step");
       
   508     QTest::addColumn<QString>("completion");
       
   509     QTest::addColumn<QString>("completionText");
       
   510 
       
   511     for (int i = 0; i < 2; i++) {
       
   512         if (i == 1)
       
   513             QTest::newRow("FILTERING_OFF") << "FILTERING_OFF" << "" << "" << "";
       
   514 
       
   515         // Plain text filter
       
   516         QTest::newRow("()") << "" << "" << "P0" << "P0";
       
   517         QTest::newRow("()F") << "" << "F" << "P0" << "P0";
       
   518         QTest::newRow("()L") << "" << "L" << "p4" << "p4";
       
   519         QTest::newRow("()N") << "" << "N" << "p0" << "p0";
       
   520         QTest::newRow("(P)") << "P" << "" << "P0" << "P0";
       
   521         QTest::newRow("(P)F") << "P" << "" << "P0" << "P0";
       
   522         QTest::newRow("(P)L") << "P" << "L" << "P4" << "P4";
       
   523         QTest::newRow("(p)") << "p" << "" << "p0" << "p0";
       
   524         QTest::newRow("(p)N") << "p" << "N" << "p1" << "p1";
       
   525         QTest::newRow("(p)NN") << "p" << "NN" << "p2" << "p2";
       
   526         QTest::newRow("(p)NNN") << "p" << "NNN" << "p3" << "p3";
       
   527         QTest::newRow("(p1)") << "p1" << "" << "p1" << "p1";
       
   528         QTest::newRow("(p11)") << "p11" << "" << "" << "";
       
   529 
       
   530         //// Tree filter
       
   531         QTest::newRow("(p0,)") << "p0," << "" << "c0p0" << "p0,c0p0";
       
   532         QTest::newRow("(p0,c)") << "p0,c" << "" << "c0p0" << "p0,c0p0";
       
   533         QTest::newRow("(p0,c1)") << "p0,c1" << "" << "c1p0" << "p0,c1p0";
       
   534         QTest::newRow("(p0,c3P0)") << "p0,c3p0" << "" << "c3p0" << "p0,c3p0";
       
   535         QTest::newRow("(p3,c)F") << "p3,c" << "F" << "c0p3" << "p3,c0p3";
       
   536         QTest::newRow("(p3,c)L") << "p3,c" << "L" << "c4p3" << "p3,c4p3";
       
   537         QTest::newRow("(p3,c)N") << "p3,c" << "N" << "c1p3" << "p3,c1p3";
       
   538         QTest::newRow("(p3,c)NN") << "p3,c" << "NN" << "c2p3" << "p3,c2p3";
       
   539         QTest::newRow("(p3,,c)") << "p3,,c" << "" << "" << "";
       
   540         QTest::newRow("(p3,c0P3,)") << "p3,c0P3," << "" << "" << "";
       
   541         QTest::newRow("(p,)") << "p," << "" << "" << "";
       
   542 
       
   543         QTest::newRow("FILTERING_OFF") << "FILTERING_OFF" << "" << "" << "";
       
   544     }
       
   545 }
       
   546 
       
   547 void tst_QCompleter::csMatchingOnCiSortedModel()
       
   548 {
       
   549     filter();
       
   550 }
       
   551 
       
   552 void tst_QCompleter::directoryModel_data()
       
   553 {
       
   554     delete completer;
       
   555     completer = new CsvCompleter;
       
   556     completer->setModelSorting(QCompleter::CaseSensitivelySortedModel);
       
   557     setSourceModel(DIRECTORY_MODEL);
       
   558     completer->setCaseSensitivity(Qt::CaseInsensitive);
       
   559 
       
   560     QTest::addColumn<QString>("filterText");
       
   561     QTest::addColumn<QString>("step");
       
   562     QTest::addColumn<QString>("completion");
       
   563     QTest::addColumn<QString>("completionText");
       
   564 
       
   565     // NOTE: Add tests carefully, ensurely the paths exist on all systems
       
   566     // Output is the sourceText; currentCompletionText()
       
   567 
       
   568     for (int i = 0; i < 2; i++) {
       
   569         if (i == 1)
       
   570             QTest::newRow("FILTERING_OFF") << "FILTERING_OFF" << "" << "" << "";
       
   571 
       
   572 #if defined(Q_OS_WINCE)
       
   573         QTest::newRow("()") << "" << "" << "/" << "/";
       
   574         QTest::newRow("()") << "\\Program" << "" << "Program Files" << "\\Program Files";
       
   575 #elif defined(Q_OS_WIN)
       
   576         QTest::newRow("()") << "C" << "" << "C:" << "C:";
       
   577         QTest::newRow("()") << "C:\\Program" << "" << "Program Files" << "C:\\Program Files";
       
   578 #elif defined(Q_OS_SYMBIAN)
       
   579         QTest::newRow("()") << "C" << "" << "C:" << "C:";
       
   580         QTest::newRow("()") << "C:\\re" << "" << "resource" << "C:\\resource";
       
   581 #elif defined (Q_OS_MAC)
       
   582         QTest::newRow("()") << "" << "" << "/" << "/";
       
   583         QTest::newRow("(/a)") << "/a" << "" << "Applications" << "/Applications";
       
   584         QTest::newRow("(/d)") << "/d" << "" << "Developer" << "/Developer";
       
   585 #else
       
   586         QTest::newRow("()") << "" << "" << "/" << "/";
       
   587 #if !defined(Q_OS_IRIX) && !defined(Q_OS_AIX) && !defined(Q_OS_HPUX)
       
   588         QTest::newRow("(/h)") << "/h" << "" << "home" << "/home";
       
   589 #endif
       
   590         QTest::newRow("(/et)") << "/et" << "" << "etc" << "/etc";
       
   591         QTest::newRow("(/etc/passw)") << "/etc/passw" << "" << "passwd" << "/etc/passwd";
       
   592 #endif
       
   593     }
       
   594 }
       
   595 
       
   596 void tst_QCompleter::directoryModel()
       
   597 {
       
   598     filter();
       
   599 }
       
   600 
       
   601 void tst_QCompleter::changingModel_data()
       
   602 {
       
   603 }
       
   604 
       
   605 void tst_QCompleter::changingModel()
       
   606 {
       
   607     for (int i = 0; i < 2; i++) {
       
   608         delete completer;
       
   609         completer = new CsvCompleter;
       
   610         completer->setModelSorting(QCompleter::CaseSensitivelySortedModel);
       
   611         completer->setCaseSensitivity(Qt::CaseSensitive);
       
   612         setSourceModel(CASE_SENSITIVELY_SORTED_MODEL);
       
   613 
       
   614         if (i == 1) {
       
   615             completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
       
   616         }
       
   617 
       
   618         completer->setCompletionPrefix("p");
       
   619         completer->setCurrentRow(completer->completionCount() - 1);
       
   620         QCOMPARE(completer->currentCompletion(), QString("p4"));
       
   621 
       
   622         // Test addition of data
       
   623         QTreeWidgetItem p5item;
       
   624         p5item.setText(completionColumn, "p5");
       
   625         treeWidget->addTopLevelItem(&p5item);
       
   626         completer->setCompletionPrefix("p5");
       
   627         QCOMPARE(completer->currentCompletion(), QString("p5"));
       
   628 
       
   629         // Test removal of data
       
   630         int p5index = treeWidget->indexOfTopLevelItem(&p5item);
       
   631         treeWidget->takeTopLevelItem(p5index);
       
   632         QCOMPARE(completer->currentCompletion(), QString(""));
       
   633 
       
   634         // Test clear
       
   635         treeWidget->clear();
       
   636         QCOMPARE(completer->currentIndex(), QModelIndex());
       
   637     }
       
   638 }
       
   639 
       
   640 void tst_QCompleter::testRowCount()
       
   641 {
       
   642     QFETCH(QString, filterText);
       
   643     QFETCH(bool, hasChildren);
       
   644     QFETCH(int, rowCount);
       
   645     QFETCH(int, completionCount);
       
   646 
       
   647     if (filterText.compare("FILTERING_OFF", Qt::CaseInsensitive) == 0) {
       
   648         completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
       
   649         return;
       
   650     }
       
   651 
       
   652     completer->setCompletionPrefix(filterText);
       
   653     const QAbstractItemModel *completionModel = completer->completionModel();
       
   654     QCOMPARE(completionModel->rowCount(), rowCount);
       
   655     QCOMPARE(completionCount, completionCount);
       
   656     QCOMPARE(completionModel->hasChildren(), hasChildren);
       
   657     QCOMPARE(completionModel->columnCount(), columnCount);
       
   658 }
       
   659 
       
   660 void tst_QCompleter::sortedEngineRowCount_data()
       
   661 {
       
   662     delete completer;
       
   663     completer = new CsvCompleter;
       
   664     completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
       
   665     completer->setCaseSensitivity(Qt::CaseInsensitive);
       
   666     setSourceModel(CASE_INSENSITIVELY_SORTED_MODEL);
       
   667 
       
   668     QTest::addColumn<QString>("filterText");
       
   669     QTest::addColumn<bool>("hasChildren");
       
   670     QTest::addColumn<int>("rowCount");
       
   671     QTest::addColumn<int>("completionCount");
       
   672 
       
   673     QTest::newRow("whatever") << "whatever" << false << 0 << 0;
       
   674     QTest::newRow("p") << "p" << true << 10 << 10;
       
   675     QTest::newRow("p1") << "p1" << true << 2 << 2;
       
   676     QTest::newRow("P1,") << "P1," << true << 5 << 5;
       
   677     QTest::newRow("P1,c") << "P1,c" << true << 5 << 5;
       
   678     QTest::newRow("P1,cc") << "P1,cc" << false << 0 << 0;
       
   679 
       
   680     QTest::newRow("FILTERING_OFF") << "FILTERING_OFF" << false << 0 << 0;
       
   681 
       
   682     QTest::newRow("whatever(filter off)") << "whatever" << true << 10 << 0;
       
   683     QTest::newRow("p1(filter off)") << "p1" << true << 10 << 2;
       
   684     QTest::newRow("p1,(filter off)") << "p1," << true << 5 << 5;
       
   685     QTest::newRow("p1,c(filter off)") << "p1,c" << true << 5 << 5;
       
   686     QTest::newRow("P1,cc(filter off)") << "P1,cc" << true << 5 << 0;
       
   687 }
       
   688 
       
   689 void tst_QCompleter::sortedEngineRowCount()
       
   690 {
       
   691     testRowCount();
       
   692 }
       
   693 
       
   694 void tst_QCompleter::unsortedEngineRowCount_data()
       
   695 {
       
   696     delete completer;
       
   697     completer = new CsvCompleter;
       
   698     completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
       
   699     completer->setCaseSensitivity(Qt::CaseSensitive);
       
   700     setSourceModel(CASE_INSENSITIVELY_SORTED_MODEL);
       
   701 
       
   702     QTest::addColumn<QString>("filterText");
       
   703     QTest::addColumn<bool>("hasChildren");
       
   704     QTest::addColumn<int>("rowCount");
       
   705     QTest::addColumn<int>("completionCount");
       
   706 
       
   707     QTest::newRow("whatever") << "whatever" << false << 0 << 0;
       
   708     QTest::newRow("p") << "p" << true << 5 << 5;
       
   709     QTest::newRow("p1") << "p1" << true << 1 << 1;
       
   710     QTest::newRow("P1,") << "P1," << true << 5 << 5;
       
   711     QTest::newRow("P1,c") << "P1,c" << true << 5 << 5;
       
   712     QTest::newRow("P1,cc") << "P1,cc" << false << 0 << 0;
       
   713 
       
   714     QTest::newRow("FILTERING_OFF") << "FILTERING_OFF" << false << 0 << 0;
       
   715 
       
   716     QTest::newRow("whatever(filter off)") << "whatever" << true << 10 << 0;
       
   717     QTest::newRow("p1(filter off)") << "p1" << true << 10 << 1;
       
   718     QTest::newRow("p1,(filter off)") << "p1," << true << 5 << 5;
       
   719     QTest::newRow("p1,c(filter off)") << "p1,c" << true << 5 << 5;
       
   720     QTest::newRow("P1,cc(filter off)") << "P1,cc" << true << 5 << 0;
       
   721 }
       
   722 
       
   723 void tst_QCompleter::unsortedEngineRowCount()
       
   724 {
       
   725     testRowCount();
       
   726 }
       
   727 
       
   728 void tst_QCompleter::currentRow()
       
   729 {
       
   730     delete completer;
       
   731     completer = new CsvCompleter;
       
   732     completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
       
   733     completer->setCaseSensitivity(Qt::CaseInsensitive);
       
   734     setSourceModel(CASE_INSENSITIVELY_SORTED_MODEL);
       
   735 
       
   736     // blank text
       
   737     completer->setCompletionPrefix("");
       
   738     QCOMPARE(completer->currentRow(), 0);
       
   739     QVERIFY(completer->setCurrentRow(4));
       
   740     QCOMPARE(completer->currentRow(), 4);
       
   741     QVERIFY(!completer->setCurrentRow(13));
       
   742     QVERIFY(completer->setCurrentRow(4));
       
   743 
       
   744     // some text
       
   745      completer->setCompletionPrefix("p1");
       
   746     QCOMPARE(completer->currentRow(), 0);
       
   747     QVERIFY(completer->setCurrentRow(1));
       
   748     QCOMPARE(completer->currentRow(), 1);
       
   749     QVERIFY(!completer->setCurrentRow(2));
       
   750     QCOMPARE(completer->currentRow(), 1);
       
   751 
       
   752     // invalid text
       
   753     completer->setCompletionPrefix("well");
       
   754     QCOMPARE(completer->currentRow(), -1);
       
   755 }
       
   756 
       
   757 void tst_QCompleter::sortedEngineMapFromSource()
       
   758 {
       
   759     delete completer;
       
   760     completer = new CsvCompleter;
       
   761     completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
       
   762     completer->setCaseSensitivity(Qt::CaseInsensitive);
       
   763     setSourceModel(CASE_INSENSITIVELY_SORTED_MODEL);
       
   764 
       
   765     QModelIndex si1, si2, pi;
       
   766     QAbstractItemModel *sourceModel = completer->model();
       
   767     const QAbstractProxyModel *completionModel =
       
   768         qobject_cast<const QAbstractProxyModel *>(completer->completionModel());
       
   769 
       
   770     // Fitering ON
       
   771     // empty
       
   772     si1 = sourceModel->index(4, completionColumn); // "P2"
       
   773     si2 = sourceModel->index(2, 0, si1); // "P2,c0P2"
       
   774     pi = completionModel->mapFromSource(si1);
       
   775     QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P2"));
       
   776     pi = completionModel->mapFromSource(si2);
       
   777     QCOMPARE(pi.isValid(), false);
       
   778 
       
   779     // some text
       
   780     completer->setCompletionPrefix("p");
       
   781     pi = completionModel->mapFromSource(si1);
       
   782     QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P2"));
       
   783     pi = completionModel->mapFromSource(si2);
       
   784     QCOMPARE(pi.isValid(), false);
       
   785 
       
   786     // more text
       
   787     completer->setCompletionPrefix("p2");
       
   788     pi = completionModel->mapFromSource(si1);
       
   789     QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P2"));
       
   790     pi = completionModel->mapFromSource(si2);
       
   791     QCOMPARE(pi.isValid(), false);
       
   792 
       
   793     // invalid text
       
   794     completer->setCompletionPrefix("whatever");
       
   795     pi = completionModel->mapFromSource(si1);
       
   796     QVERIFY(!pi.isValid());
       
   797 
       
   798     // Fitering OFF
       
   799     completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
       
   800     // empty
       
   801     si1 = sourceModel->index(4, completionColumn); // "P2"
       
   802     si2 = sourceModel->index(2, 0, si1); // "P2,c0P2"
       
   803     pi = completionModel->mapFromSource(si1);
       
   804     QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P2"));
       
   805     pi = completionModel->mapFromSource(si2);
       
   806     QCOMPARE(pi.isValid(), false);
       
   807 
       
   808     // some text
       
   809     completer->setCompletionPrefix("p");
       
   810     pi = completionModel->mapFromSource(si1);
       
   811     QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P2"));
       
   812     pi = completionModel->mapFromSource(si2);
       
   813     QCOMPARE(pi.isValid(), false);
       
   814 
       
   815     // more text
       
   816     completer->setCompletionPrefix("p2");
       
   817     pi = completionModel->mapFromSource(si1);
       
   818     QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P2"));
       
   819     pi = completionModel->mapFromSource(si2);
       
   820     QCOMPARE(pi.isValid(), false);
       
   821 
       
   822     // invalid text
       
   823     completer->setCompletionPrefix("whatever");
       
   824     pi = completionModel->mapFromSource(si1);
       
   825     QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P2"));
       
   826 }
       
   827 
       
   828 void tst_QCompleter::unsortedEngineMapFromSource()
       
   829 {
       
   830     delete completer;
       
   831     completer = new CsvCompleter;
       
   832     completer->setCaseSensitivity(Qt::CaseInsensitive);
       
   833     setSourceModel(HISTORY_MODEL); // case insensitively sorted model
       
   834     completer->setModelSorting(QCompleter::UnsortedModel);
       
   835 
       
   836     QModelIndex si, si2, si3, pi;
       
   837     QAbstractItemModel *sourceModel = completer->model();
       
   838     const QAbstractProxyModel *completionModel =
       
   839         qobject_cast<const QAbstractProxyModel *>(completer->completionModel());
       
   840 
       
   841     si = sourceModel->index(6, completionColumn); // "P3"
       
   842     QCOMPARE(si.data().toString(), QLatin1String("P3"));
       
   843     si2 = sourceModel->index(3, completionColumn, sourceModel->index(0, completionColumn)); // "P0,c3P0"
       
   844     QCOMPARE(si2.data().toString(), QLatin1String("c3P0"));
       
   845     si3 = sourceModel->index(10, completionColumn); // "p3,c3p3" (history)
       
   846     QCOMPARE(si3.data().toString(), QLatin1String("p3,c3p3"));
       
   847 
       
   848     // FILTERING ON
       
   849     // empty
       
   850     pi = completionModel->mapFromSource(si);
       
   851     QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P3"));
       
   852     pi = completionModel->mapFromSource(si2);
       
   853     QCOMPARE(pi.isValid(), false);
       
   854     pi = completionModel->mapFromSource(si3);
       
   855    QCOMPARE(completionModel->data(pi).toString(), QLatin1String("p3,c3p3"));
       
   856 
       
   857     // some text
       
   858     completer->setCompletionPrefix("P");
       
   859     pi = completionModel->mapFromSource(si);
       
   860     QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P3"));
       
   861     pi = completionModel->mapFromSource(si2);
       
   862     QCOMPARE(pi.isValid(), false);
       
   863     pi = completionModel->mapFromSource(si3);
       
   864     QCOMPARE(completionModel->data(pi).toString(), QLatin1String("p3,c3p3"));
       
   865 
       
   866     // invalid text
       
   867     completer->setCompletionPrefix("whatever");
       
   868     pi = completionModel->mapFromSource(si);
       
   869     QVERIFY(!pi.isValid());
       
   870     pi = completionModel->mapFromSource(si2);
       
   871     QVERIFY(!pi.isValid());
       
   872 
       
   873     // tree matching
       
   874     completer->setCompletionPrefix("P0,c");
       
   875     pi = completionModel->mapFromSource(si);
       
   876     QVERIFY(!pi.isValid());
       
   877     pi = completionModel->mapFromSource(si2);
       
   878     QCOMPARE(completionModel->data(pi).toString(), QLatin1String("c3P0"));
       
   879     pi = completionModel->mapFromSource(si3);
       
   880     QCOMPARE(pi.isValid(), false);
       
   881 
       
   882     // more tree matching
       
   883     completer->setCompletionPrefix("p3,");
       
   884     pi = completionModel->mapFromSource(si2);
       
   885     QVERIFY(!pi.isValid());
       
   886     pi = completionModel->mapFromSource(si3);
       
   887     QCOMPARE(completionModel->data(pi).toString(), QLatin1String("p3,c3p3"));
       
   888 
       
   889     // FILTERING OFF
       
   890     // empty
       
   891     completer->setCompletionPrefix("");
       
   892     completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
       
   893     pi = completionModel->mapFromSource(si);
       
   894     QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P3"));
       
   895 
       
   896     // some text
       
   897     completer->setCompletionPrefix("P");
       
   898     pi = completionModel->mapFromSource(si);
       
   899     QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P3"));
       
   900 
       
   901     // more text
       
   902     completer->setCompletionPrefix("P3");
       
   903     pi = completionModel->mapFromSource(si);
       
   904     QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P3"));
       
   905 
       
   906     // invalid text
       
   907     completer->setCompletionPrefix("whatever");
       
   908     pi = completionModel->mapFromSource(si);
       
   909     QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P3"));
       
   910 }
       
   911 
       
   912 void tst_QCompleter::historySearch()
       
   913 {
       
   914     delete completer;
       
   915     completer = new CsvCompleter;
       
   916     completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
       
   917     completer->setCaseSensitivity(Qt::CaseSensitive);
       
   918     setSourceModel(HISTORY_MODEL);
       
   919 
       
   920     const QAbstractProxyModel *completionModel =
       
   921       qobject_cast<const QAbstractProxyModel *>(completer->completionModel());
       
   922 
       
   923     // "p3,c3p3" and "p2,c4p2" are added in the tree root
       
   924 
       
   925     // FILTERING ON
       
   926     // empty
       
   927     completer->setCurrentRow(10);
       
   928     QCOMPARE(completer->currentCompletion(), QLatin1String("p3,c3p3"));
       
   929 
       
   930     // more text
       
   931     completer->setCompletionPrefix("p2");
       
   932     completer->setCurrentRow(1);
       
   933     QCOMPARE(completer->currentCompletion(), QLatin1String("p2,c4p2"));
       
   934 
       
   935     // comma separated text
       
   936     completer->setCompletionPrefix("p2,c4");
       
   937     completer->setCurrentRow(1);
       
   938     QCOMPARE(completionModel->rowCount(), 2);
       
   939     QCOMPARE(completer->currentCompletion(), QLatin1String("p2,c4p2"));
       
   940 
       
   941     // invalid text
       
   942     completer->setCompletionPrefix("whatever");
       
   943     QCOMPARE(completer->currentCompletion(), QString());
       
   944 
       
   945     // FILTERING OFF
       
   946     completer->setCompletionPrefix("");
       
   947     completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
       
   948     completer->setCurrentRow(10);
       
   949     QCOMPARE(completer->currentCompletion(), QLatin1String("p3,c3p3"));
       
   950 
       
   951     // more text
       
   952     completer->setCompletionPrefix("p2");
       
   953     completer->setCurrentRow(1);
       
   954     QCOMPARE(completer->currentCompletion(), QLatin1String("p2,c4p2"));
       
   955 
       
   956     // comma separated text
       
   957     completer->setCompletionPrefix("p2,c4");
       
   958     QCOMPARE(completionModel->rowCount(), 5);
       
   959 
       
   960     // invalid text
       
   961     completer->setCompletionPrefix("whatever");
       
   962     QCOMPARE(completer->currentCompletion(), QString());
       
   963 }
       
   964 
       
   965 void tst_QCompleter::setters()
       
   966 {
       
   967     delete completer;
       
   968     completer = new CsvCompleter;
       
   969     QVERIFY(completer->popup() != 0);
       
   970     QPointer<QDirModel> dirModel = new QDirModel(completer);
       
   971     QAbstractItemModel *oldModel = completer->model();
       
   972     completer->setModel(dirModel);
       
   973     QVERIFY(completer->popup()->model() != oldModel);
       
   974     QVERIFY(completer->popup()->model() == completer->completionModel());
       
   975     completer->setPopup(new QListView);
       
   976     QVERIFY(completer->popup()->model() == completer->completionModel());
       
   977     completer->setModel(new QStringListModel(completer));
       
   978     QVERIFY(dirModel == 0); // must have been deleted
       
   979 
       
   980     completer->setModel(0);
       
   981     completer->setWidget(0);
       
   982 }
       
   983 
       
   984 void tst_QCompleter::modelDeletion()
       
   985 {
       
   986     delete completer;
       
   987     completer = new CsvCompleter;
       
   988     QStringList list;
       
   989     list << "item1" << "item2" << "item3";
       
   990     QStringListModel *listModel = new QStringListModel(list);
       
   991     completer->setCompletionPrefix("i");
       
   992     completer->setModel(listModel);
       
   993     QVERIFY(completer->completionCount() == 3);
       
   994     QListView *view = new QListView;
       
   995     view->setModel(completer->completionModel());
       
   996     delete listModel;
       
   997     view->show();
       
   998     qApp->processEvents();
       
   999     delete view;
       
  1000     QVERIFY(completer->completionCount() == 0);
       
  1001     QVERIFY(completer->currentRow() == -1);
       
  1002 }
       
  1003 
       
  1004 void tst_QCompleter::multipleWidgets()
       
  1005 {
       
  1006     QStringList list;
       
  1007     list << "item1" << "item2" << "item2";
       
  1008     QCompleter completer(list);
       
  1009     completer.setCompletionMode(QCompleter::InlineCompletion);
       
  1010 
       
  1011     QWidget window;
       
  1012     window.show();
       
  1013     QApplication::setActiveWindow(&window);
       
  1014     QTest::qWaitForWindowShown(&window);
       
  1015     QTRY_VERIFY(qApp->activeWindow() == &window);
       
  1016 
       
  1017     QFocusEvent focusIn(QEvent::FocusIn);
       
  1018     QFocusEvent focusOut(QEvent::FocusOut);
       
  1019 
       
  1020     QComboBox *comboBox = new QComboBox(&window);
       
  1021     comboBox->setEditable(true);
       
  1022     comboBox->setCompleter(&completer);
       
  1023     comboBox->setFocus();
       
  1024     comboBox->show();
       
  1025     window.activateWindow();
       
  1026     QApplication::setActiveWindow(&window);
       
  1027     QTest::qWait(50);
       
  1028     QTRY_VERIFY(qApp->focusWidget() == comboBox);
       
  1029     comboBox->lineEdit()->setText("it");
       
  1030     QCOMPARE(comboBox->currentText(), QString("it")); // should not complete with setText
       
  1031     QTest::keyPress(comboBox, 'e');
       
  1032     QCOMPARE(comboBox->currentText(), QString("item1"));
       
  1033     comboBox->clearEditText();
       
  1034     QCOMPARE(comboBox->currentText(), QString("")); // combo box text must not change!
       
  1035 
       
  1036     QLineEdit *lineEdit = new QLineEdit(&window);
       
  1037     lineEdit->setCompleter(&completer);
       
  1038     lineEdit->show();
       
  1039     lineEdit->setFocus();
       
  1040     QTest::qWait(50);
       
  1041     QTRY_VERIFY(qApp->focusWidget() == lineEdit);
       
  1042     lineEdit->setText("it");
       
  1043     QCOMPARE(lineEdit->text(), QString("it")); // should not completer with setText
       
  1044     QCOMPARE(comboBox->currentText(), QString("")); // combo box text must not change!
       
  1045     QTest::keyPress(lineEdit, 'e');
       
  1046     QCOMPARE(lineEdit->text(), QString("item1"));
       
  1047     QCOMPARE(comboBox->currentText(), QString("")); // combo box text must not change!
       
  1048 }
       
  1049 
       
  1050 void tst_QCompleter::focusIn()
       
  1051 {
       
  1052     QStringList list;
       
  1053     list << "item1" << "item2" << "item2";
       
  1054     QCompleter completer(list);
       
  1055 
       
  1056     QWidget window;
       
  1057     window.show();
       
  1058     QTest::qWait(100);
       
  1059     window.activateWindow();
       
  1060     QApplication::setActiveWindow(&window);
       
  1061     QTest::qWait(100);
       
  1062 
       
  1063     QTRY_COMPARE(qApp->activeWindow(), &window);
       
  1064 
       
  1065     QComboBox *comboBox = new QComboBox(&window);
       
  1066     comboBox->setEditable(true);
       
  1067     comboBox->setCompleter(&completer);
       
  1068     comboBox->show();
       
  1069     comboBox->lineEdit()->setText("it");
       
  1070 
       
  1071     QLineEdit *lineEdit = new QLineEdit(&window);
       
  1072     lineEdit->setCompleter(&completer);
       
  1073     lineEdit->setText("it");
       
  1074     lineEdit->show();
       
  1075 
       
  1076     QLineEdit *lineEdit2 = new QLineEdit(&window); // has no completer!
       
  1077     lineEdit2->show();
       
  1078 
       
  1079     comboBox->setFocus();
       
  1080     QTRY_VERIFY(completer.widget() == comboBox);
       
  1081     lineEdit->setFocus();
       
  1082     QTRY_VERIFY(completer.widget() == lineEdit);
       
  1083     comboBox->setFocus();
       
  1084     QTRY_VERIFY(completer.widget() == comboBox);
       
  1085     lineEdit2->setFocus();
       
  1086     QTRY_VERIFY(completer.widget() == comboBox);
       
  1087 }
       
  1088 
       
  1089 void tst_QCompleter::dynamicSortOrder()
       
  1090 {
       
  1091     QStandardItemModel model;
       
  1092     QCompleter completer(&model);
       
  1093     completer.setModelSorting(QCompleter::CaseSensitivelySortedModel);
       
  1094     QStandardItem *root = model.invisibleRootItem();
       
  1095     for (int i = 0; i < 20; i++) {
       
  1096         root->appendRow(new QStandardItem(QString("%1").arg(i)));
       
  1097     }
       
  1098     root->appendRow(new QStandardItem("13"));
       
  1099     root->sortChildren(0, Qt::AscendingOrder);
       
  1100     completer.setCompletionPrefix("1");
       
  1101     QCOMPARE(completer.completionCount(), 12);
       
  1102     completer.setCompletionPrefix("13");
       
  1103     QCOMPARE(completer.completionCount(), 2);
       
  1104 
       
  1105     root->sortChildren(0, Qt::DescendingOrder);
       
  1106     completer.setCompletionPrefix("13");
       
  1107     QCOMPARE(completer.completionCount(), 2);
       
  1108     completer.setCompletionPrefix("1");
       
  1109     QCOMPARE(completer.completionCount(), 12);
       
  1110 }
       
  1111 
       
  1112 void tst_QCompleter::disabledItems()
       
  1113 {
       
  1114     QLineEdit lineEdit;
       
  1115     QStandardItemModel *model = new QStandardItemModel(&lineEdit);
       
  1116     QStandardItem *suggestions = new QStandardItem("suggestions");
       
  1117     suggestions->setEnabled(false);
       
  1118     model->appendRow(suggestions);
       
  1119     model->appendRow(new QStandardItem("suggestions Enabled"));
       
  1120     QCompleter *completer = new QCompleter(model, &lineEdit);
       
  1121     QSignalSpy spy(completer, SIGNAL(activated(const QString &)));
       
  1122     lineEdit.setCompleter(completer);
       
  1123     lineEdit.show();
       
  1124 
       
  1125     QTest::keyPress(&lineEdit, Qt::Key_S);
       
  1126     QTest::keyPress(&lineEdit, Qt::Key_U);
       
  1127     QAbstractItemView *view = lineEdit.completer()->popup();
       
  1128     QVERIFY(view->isVisible());
       
  1129     QTest::mouseClick(view->viewport(), Qt::LeftButton, 0, view->visualRect(view->model()->index(0, 0)).center());
       
  1130     QCOMPARE(spy.count(), 0);
       
  1131     QVERIFY(view->isVisible());
       
  1132     QTest::mouseClick(view->viewport(), Qt::LeftButton, 0, view->visualRect(view->model()->index(1, 0)).center());
       
  1133     QCOMPARE(spy.count(), 1);
       
  1134     QVERIFY(!view->isVisible());
       
  1135 }
       
  1136 
       
  1137 void tst_QCompleter::task178797_activatedOnReturn()
       
  1138 {
       
  1139     QStringList words;
       
  1140     words << "foobar1" << "foobar2";
       
  1141     QLineEdit *ledit = new QLineEdit;
       
  1142     QCompleter *completer = new QCompleter(words);
       
  1143     ledit->setCompleter(completer);
       
  1144     QSignalSpy spy(completer, SIGNAL(activated(const QString)));
       
  1145     QCOMPARE(spy.count(), 0);
       
  1146     ledit->show();
       
  1147     QTest::keyClick(ledit, Qt::Key_F);
       
  1148     qApp->processEvents();
       
  1149     QVERIFY(qApp->activePopupWidget());
       
  1150     QTest::keyClick(qApp->activePopupWidget(), Qt::Key_Down);
       
  1151     qApp->processEvents();
       
  1152     QTest::keyClick(qApp->activePopupWidget(), Qt::Key_Return);
       
  1153     qApp->processEvents();
       
  1154     QCOMPARE(spy.count(), 1);
       
  1155 }
       
  1156 
       
  1157 class task189564_StringListModel : public QStringListModel
       
  1158 {
       
  1159     const QString omitString;
       
  1160     Qt::ItemFlags flags(const QModelIndex &index) const
       
  1161     {
       
  1162         Qt::ItemFlags flags = Qt::ItemIsEnabled;
       
  1163         if (data(index, Qt::DisplayRole).toString() != omitString)
       
  1164             flags |= Qt::ItemIsSelectable;
       
  1165         return flags;
       
  1166     }
       
  1167 public:
       
  1168     task189564_StringListModel(const QString &omitString, QObject *parent = 0)
       
  1169         : QStringListModel(parent)
       
  1170         , omitString(omitString)
       
  1171     {
       
  1172     }
       
  1173 };
       
  1174 
       
  1175 void tst_QCompleter::task189564_omitNonSelectableItems()
       
  1176 {
       
  1177     const QString prefix("a");
       
  1178     Q_ASSERT(!prefix.isEmpty());
       
  1179     const int n = 5;
       
  1180     Q_ASSERT(n > 0);
       
  1181 
       
  1182     QStringList strings;
       
  1183     for (int i = 0; i < n; ++i)
       
  1184         strings << QString("%1%2").arg(prefix).arg(i);
       
  1185     const QString omitString(strings.at(n / 2));
       
  1186     task189564_StringListModel model(omitString);
       
  1187     model.setStringList(strings);
       
  1188     QCompleter completer_(&model);
       
  1189     completer_.setCompletionPrefix(prefix);
       
  1190 
       
  1191     QAbstractItemModel *completionModel = completer_.completionModel();
       
  1192     QModelIndexList matches1 =
       
  1193         completionModel->match(completionModel->index(0, 0), Qt::DisplayRole, prefix, -1);
       
  1194     QCOMPARE(matches1.size(), n - 1);
       
  1195     QModelIndexList matches2 =
       
  1196         completionModel->match(completionModel->index(0, 0), Qt::DisplayRole, omitString);
       
  1197     QVERIFY(matches2.isEmpty());
       
  1198 }
       
  1199 
       
  1200 class task246056_ComboBox : public QComboBox
       
  1201 {
       
  1202     Q_OBJECT
       
  1203 public:
       
  1204     task246056_ComboBox()
       
  1205     {
       
  1206         setEditable(true);
       
  1207         setInsertPolicy(NoInsert);
       
  1208         Q_ASSERT(completer());
       
  1209         completer()->setCompletionMode(QCompleter::PopupCompletion);
       
  1210         completer()->setCompletionRole(Qt::DisplayRole);
       
  1211         connect(lineEdit(), SIGNAL(editingFinished()), SLOT(setCompletionPrefix()));
       
  1212     }
       
  1213 private slots:
       
  1214     void setCompletionPrefix() { completer()->setCompletionPrefix(lineEdit()->text()); }
       
  1215 };
       
  1216 
       
  1217 void tst_QCompleter::task246056_setCompletionPrefix()
       
  1218 {
       
  1219     task246056_ComboBox *comboBox = new task246056_ComboBox;
       
  1220     comboBox->addItem("");
       
  1221     comboBox->addItem("a1");
       
  1222     comboBox->addItem("a2");
       
  1223     comboBox->show();
       
  1224     comboBox->setFocus();
       
  1225     QTest::qWait(100);
       
  1226     QTest::keyPress(comboBox, 'a');
       
  1227     QTest::keyPress(comboBox->completer()->popup(), Qt::Key_Down);
       
  1228     QTest::keyPress(comboBox->completer()->popup(), Qt::Key_Down);
       
  1229     QTest::keyPress(comboBox->completer()->popup(), Qt::Key_Enter); // don't crash!
       
  1230 }
       
  1231 
       
  1232 class task250064_TextEdit : public QTextEdit
       
  1233 {
       
  1234 public:
       
  1235     QCompleter *completer;
       
  1236 
       
  1237     task250064_TextEdit()
       
  1238     {
       
  1239         completer = new QCompleter;
       
  1240         completer->setWidget(this);
       
  1241     }
       
  1242 
       
  1243     void keyPressEvent (QKeyEvent *e)
       
  1244     {
       
  1245         completer->popup();
       
  1246         QTextEdit::keyPressEvent(e);
       
  1247     }
       
  1248 };
       
  1249 
       
  1250 class task250064_Widget : public QWidget
       
  1251 {
       
  1252     Q_OBJECT
       
  1253 public:
       
  1254     task250064_TextEdit *textEdit;
       
  1255 
       
  1256     task250064_Widget(task250064_TextEdit *textEdit)
       
  1257         : textEdit(textEdit)
       
  1258     {
       
  1259         QTabWidget *tabWidget = new QTabWidget;
       
  1260         tabWidget->setFocusPolicy(Qt::ClickFocus);
       
  1261         tabWidget->addTab(textEdit, "untitled");
       
  1262 
       
  1263         QVBoxLayout *layout = new QVBoxLayout(this);
       
  1264         layout->addWidget(tabWidget);
       
  1265 
       
  1266         textEdit->setPlainText("bla bla bla");
       
  1267         textEdit->setFocus();
       
  1268     }
       
  1269 
       
  1270     void setCompletionModel()
       
  1271     {
       
  1272         textEdit->completer->setModel(0);
       
  1273     }
       
  1274 };
       
  1275 
       
  1276 void tst_QCompleter::task250064_lostFocus()
       
  1277 {
       
  1278     task250064_TextEdit *textEdit = new task250064_TextEdit;
       
  1279     task250064_Widget *widget = new task250064_Widget(textEdit);
       
  1280     widget->show();
       
  1281     QTest::qWait(100);
       
  1282     QTest::keyPress(textEdit, 'a');
       
  1283     Qt::FocusPolicy origPolicy = textEdit->focusPolicy();
       
  1284     QVERIFY(origPolicy != Qt::NoFocus);
       
  1285     widget->setCompletionModel();
       
  1286     QCOMPARE(textEdit->focusPolicy(), origPolicy);
       
  1287 }
       
  1288 
       
  1289 void tst_QCompleter::task253125_lineEditCompletion_data()
       
  1290 {
       
  1291     QTest::addColumn<QStringList>("list");
       
  1292     QTest::addColumn<int>("completionMode");
       
  1293 
       
  1294     QStringList list = QStringList()
       
  1295         << "alpha" << "beta"    << "gamma"   << "delta" << "epsilon" << "zeta"
       
  1296         << "eta"   << "theta"   << "iota"    << "kappa" << "lambda"  << "mu"
       
  1297         << "nu"    << "xi"      << "omicron" << "pi"    << "rho"     << "sigma"
       
  1298         << "tau"   << "upsilon" << "phi"     << "chi"   << "psi"     << "omega";
       
  1299 
       
  1300     QTest::newRow("Inline") << list << (int)QCompleter::InlineCompletion;
       
  1301     QTest::newRow("Filtered") << list << (int)QCompleter::PopupCompletion;
       
  1302     QTest::newRow("Unfiltered") << list << (int)QCompleter::UnfilteredPopupCompletion;
       
  1303 }
       
  1304 
       
  1305 void tst_QCompleter::task253125_lineEditCompletion()
       
  1306 {
       
  1307     QFETCH(QStringList, list);
       
  1308     QFETCH(int, completionMode);
       
  1309 
       
  1310     QStringListModel *model = new QStringListModel;
       
  1311     model->setStringList(list);
       
  1312 
       
  1313     QCompleter *completer = new QCompleter(list);
       
  1314     completer->setModel(model);
       
  1315     completer->setCompletionMode((QCompleter::CompletionMode)completionMode);
       
  1316 
       
  1317     QLineEdit edit;
       
  1318     edit.setCompleter(completer);
       
  1319     edit.show();
       
  1320     edit.setFocus();
       
  1321 
       
  1322 #ifdef Q_WS_X11
       
  1323     qt_x11_wait_for_window_manager(&edit);
       
  1324 #endif
       
  1325     QTest::qWait(10);
       
  1326     QApplication::setActiveWindow(&edit);
       
  1327     QTRY_COMPARE(QApplication::activeWindow(), &edit);
       
  1328 
       
  1329     QTest::keyClick(&edit, 'i');
       
  1330     QCOMPARE(edit.completer()->currentCompletion(), QString("iota"));
       
  1331     QTest::keyClick(edit.completer()->popup(), Qt::Key_Down);
       
  1332     QTest::keyClick(edit.completer()->popup(), Qt::Key_Enter);
       
  1333 
       
  1334     QCOMPARE(edit.text(), QString("iota"));
       
  1335 
       
  1336     delete completer;
       
  1337     delete model;
       
  1338 }
       
  1339 
       
  1340 void tst_QCompleter::task247560_keyboardNavigation()
       
  1341 {
       
  1342     QStandardItemModel model;
       
  1343 
       
  1344     for (int i = 0; i < 5; i++) {
       
  1345         for (int j = 0; j < 5; j++) {
       
  1346             model.setItem(i, j, new QStandardItem(QString("row %1 column %2").arg(i).arg(j)));
       
  1347         }
       
  1348     }
       
  1349 
       
  1350 
       
  1351     QCompleter completer(&model);
       
  1352     completer.setCompletionColumn(1);
       
  1353 
       
  1354     QLineEdit edit;
       
  1355     edit.setCompleter(&completer);
       
  1356     edit.show();
       
  1357     edit.setFocus();
       
  1358 
       
  1359 #ifdef Q_WS_X11
       
  1360     qt_x11_wait_for_window_manager(&edit);
       
  1361 #endif
       
  1362 
       
  1363     QTest::qWait(10);
       
  1364     QApplication::setActiveWindow(&edit);
       
  1365     QTRY_COMPARE(QApplication::activeWindow(), &edit);
       
  1366 
       
  1367     QTest::keyClick(&edit, 'r');
       
  1368     QTest::keyClick(edit.completer()->popup(), Qt::Key_Down);
       
  1369     QTest::keyClick(edit.completer()->popup(), Qt::Key_Down);
       
  1370     QTest::keyClick(edit.completer()->popup(), Qt::Key_Enter);
       
  1371 
       
  1372     QCOMPARE(edit.text(), QString("row 1 column 1"));
       
  1373 
       
  1374     edit.clear();
       
  1375 
       
  1376     QTest::keyClick(&edit, 'r');
       
  1377     QTest::keyClick(edit.completer()->popup(), Qt::Key_Up);
       
  1378     QTest::keyClick(edit.completer()->popup(), Qt::Key_Up);
       
  1379     QTest::keyClick(edit.completer()->popup(), Qt::Key_Enter);
       
  1380 
       
  1381     QCOMPARE(edit.text(), QString("row 3 column 1"));
       
  1382 }
       
  1383 
       
  1384 QTEST_MAIN(tst_QCompleter)
       
  1385 #include "tst_qcompleter.moc"