tests/auto/xmlpatternsview/view/MainWindow.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
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 
       
    42 #include <QCloseEvent>
       
    43 #include <QFileDialog>
       
    44 #include <QFileInfo>
       
    45 #include <QHeaderView>
       
    46 #include <QMenu>
       
    47 #include <QMessageBox>
       
    48 #include <QProcess>
       
    49 #include <QSettings>
       
    50 #include <QTextStream>
       
    51 
       
    52 #include "ASTItem.h"
       
    53 #include "FunctionSignaturesView.h"
       
    54 #include "Global.h"
       
    55 #include "TestCaseView.h"
       
    56 #include "TestResultView.h"
       
    57 #include "TestSuite.h"
       
    58 #include "TreeModel.h"
       
    59 #include "TreeSortFilter.h"
       
    60 #include "UserTestCase.h"
       
    61 
       
    62 #include "MainWindow.h"
       
    63 
       
    64 using namespace QPatternistSDK;
       
    65 
       
    66 MainWindow::MainWindow() : m_userTC(new UserTestCase()),
       
    67                            m_currentTC(0)
       
    68 {
       
    69     setupUi(this);
       
    70 
       
    71     /* I want to do this in Designer.. */
       
    72     testSuiteView->header()->setSortIndicator(0, Qt::AscendingOrder);
       
    73     testSuiteView->header()->setSortIndicatorShown(true);
       
    74     testSuiteView->header()->setClickable(true);
       
    75 
       
    76     setupActions();
       
    77 
       
    78     QStringList suiteHeaders;
       
    79     suiteHeaders << QLatin1String("Name")
       
    80                  << QLatin1String("Pass")
       
    81                  << QLatin1String("Fail")
       
    82                  << QLatin1String("Total");
       
    83 
       
    84     TreeSortFilter *const proxy = new TreeSortFilter(this);
       
    85     connect(searchInput,    SIGNAL(textChanged(const QString &)),
       
    86             proxy,          SLOT(setFilterFixedString(const QString &)));
       
    87 
       
    88     proxy->setSourceModel(new TreeModel(suiteHeaders, this));
       
    89     testSuiteView->setModel(proxy);
       
    90 
       
    91     /* --------- Test Result View ---------- */
       
    92     testResultView = new TestResultView(this);
       
    93     testResultView->setAllowedAreas(Qt::AllDockWidgetAreas);
       
    94     addDockWidget(Qt::RightDockWidgetArea, testResultView);
       
    95     /* ----------------------------------- */
       
    96 
       
    97     /* --------- Test Case View ---------- */
       
    98     testCaseView = new TestCaseView(this);
       
    99     testCaseView->setAllowedAreas(Qt::AllDockWidgetAreas);
       
   100     addDockWidget(Qt::LeftDockWidgetArea, testCaseView);
       
   101 
       
   102     connect(this,           SIGNAL(testCaseSelected(TestCase *const)),
       
   103             testCaseView,   SLOT(displayTestCase(TestCase *const)));
       
   104     connect(this,           SIGNAL(testCaseSelected(TestCase *const)),
       
   105             testResultView, SLOT(displayTestResult(TestCase *const)));
       
   106     connect(focusURI,       SIGNAL(textChanged(const QString &)),
       
   107             m_userTC,       SLOT(focusDocumentChanged(const QString &)));
       
   108     /* ----------------------------------- */
       
   109 
       
   110     /* ----- Function Signature View ----- */
       
   111     functionView = new FunctionSignaturesView(this);
       
   112     functionView->setAllowedAreas(Qt::AllDockWidgetAreas);
       
   113     addDockWidget(Qt::RightDockWidgetArea, functionView);
       
   114     /* ----------------------------------- */
       
   115 
       
   116     /* Appears here, because the menu uses actions in the QDockWidgets. */
       
   117     setupMenu();
       
   118 
       
   119     readSettings();
       
   120 
       
   121     /* Connect this after readSettings(), otherwise readSettings() triggers writeSettings(). */
       
   122     connect(sourceTab,      SIGNAL(currentChanged(int)),
       
   123                             SLOT(writeSettings()));
       
   124     connect(testSuiteView,  SIGNAL(clicked(const QModelIndex &)),
       
   125                             SLOT(writeSettings()));
       
   126     connect(sourceInput,    SIGNAL(textChanged()),
       
   127                             SLOT(writeSettings()));
       
   128 }
       
   129 
       
   130 MainWindow::~MainWindow()
       
   131 {
       
   132     delete m_userTC;
       
   133 }
       
   134 
       
   135 QModelIndex MainWindow::sourceIndex(const QModelIndex &proxyIndex) const
       
   136 {
       
   137     return static_cast<TreeSortFilter *>(testSuiteView->model())->mapToSource(proxyIndex);
       
   138 }
       
   139 
       
   140 TreeModel *MainWindow::sourceModel() const
       
   141 {
       
   142     const TreeSortFilter *const proxy = static_cast<TreeSortFilter *>(testSuiteView->model());
       
   143     return static_cast<TreeModel *>(proxy->sourceModel());
       
   144 }
       
   145 
       
   146 void MainWindow::on_testSuiteView_clicked(const QModelIndex &index)
       
   147 {
       
   148     if(index.isValid())
       
   149     {
       
   150         TestItem *const node = static_cast<TestItem *>(sourceIndex(index).internalPointer());
       
   151         Q_ASSERT(node);
       
   152 
       
   153         if(node->isFinalNode())
       
   154         {
       
   155             m_currentTC = static_cast<TestCase *>(node);
       
   156             testCaseSelected(m_currentTC);
       
   157             return;
       
   158         }
       
   159     }
       
   160 
       
   161     /* In all other cases: */
       
   162     m_currentTC = 0;
       
   163     testCaseSelected(0);
       
   164 }
       
   165 
       
   166 void MainWindow::on_sourceInput_textChanged()
       
   167 {
       
   168     m_userTC->setSourceCode(sourceInput->toPlainText());
       
   169 }
       
   170 
       
   171 void MainWindow::on_actionOpen_triggered()
       
   172 {
       
   173     const QString fileName(QFileDialog::getOpenFileName(this,
       
   174                                                         QLatin1String("Open Test Suite Catalog"),
       
   175                                                         m_previousOpenedCatalog.toLocalFile(),
       
   176                                                         QLatin1String("Test Suite Catalog file (*.xml)")));
       
   177 
       
   178     /* "If the user presses Cancel, it returns a null string." */
       
   179     if(fileName.isNull())
       
   180         return;
       
   181 
       
   182     m_currentSuiteType = TestSuite::XQuerySuite;
       
   183     openCatalog(QUrl::fromLocalFile(fileName), true, TestSuite::XQuerySuite);
       
   184 }
       
   185 
       
   186 void MainWindow::on_actionOpenXSLTSCatalog_triggered()
       
   187 {
       
   188     const QString fileName(QFileDialog::getOpenFileName(this,
       
   189                                                         QLatin1String("Open Test Suite Catalog"),
       
   190                                                         m_previousOpenedCatalog.toLocalFile(),
       
   191                                                         QLatin1String("Test Suite Catalog file (*.xml)")));
       
   192 
       
   193     /* "If the user presses Cancel, it returns a null string." */
       
   194     if(fileName.isNull())
       
   195         return;
       
   196 
       
   197     m_currentSuiteType = TestSuite::XsltSuite;
       
   198     openCatalog(QUrl::fromLocalFile(fileName), true, TestSuite::XsltSuite);
       
   199 }
       
   200 
       
   201 void MainWindow::on_actionOpenXSDTSCatalog_triggered()
       
   202 {
       
   203     const QString fileName(QFileDialog::getOpenFileName(this,
       
   204                                                         QLatin1String("Open Test Suite Catalog"),
       
   205                                                         m_previousOpenedCatalog.toLocalFile(),
       
   206                                                         QLatin1String("Test Suite Catalog file (*.xml)")));
       
   207 
       
   208     /* "If the user presses Cancel, it returns a null string." */
       
   209     if(fileName.isNull())
       
   210         return;
       
   211 
       
   212     m_currentSuiteType = TestSuite::XsdSuite;
       
   213     openCatalog(QUrl::fromLocalFile(fileName), true, TestSuite::XsdSuite);
       
   214 }
       
   215 
       
   216 void MainWindow::openCatalog(const QUrl &fileName,
       
   217                              const bool reportError,
       
   218                              const TestSuite::SuiteType suiteType)
       
   219 {
       
   220     setCurrentFile(fileName);
       
   221     m_previousOpenedCatalog = fileName;
       
   222 
       
   223     QString errorMsg;
       
   224     TestSuite *const loadedSuite = TestSuite::openCatalog(fileName, errorMsg, false, suiteType);
       
   225 
       
   226     if(!loadedSuite)
       
   227     {
       
   228         if(reportError)
       
   229         {
       
   230             QMessageBox::information(this, QLatin1String("Failed to load catalog file"),
       
   231                                      errorMsg, QMessageBox::Ok);
       
   232         }
       
   233 
       
   234         return;
       
   235     }
       
   236 
       
   237     TreeModel *const prevModel = sourceModel();
       
   238     prevModel->setRoot(loadedSuite);
       
   239     m_currentTC = 0;
       
   240 
       
   241     testCaseCount->setText(QString::number(loadedSuite->resultSummary().second));
       
   242     /* Switch to the tab containing the loaded test suite. */
       
   243     sourceTab->setCurrentIndex(0);
       
   244 
       
   245     setWindowTitle(QCoreApplication::applicationName() +
       
   246                    QLatin1String(" -- ") +
       
   247                    QFileInfo(fileName.toLocalFile()).fileName());
       
   248 
       
   249     /* @p reportError is set when not auto-loading on startup, and
       
   250      * we only want to save when the user opens from the GUI. */
       
   251     if(reportError)
       
   252         writeSettings();
       
   253 }
       
   254 
       
   255 void MainWindow::on_sourceTab_currentChanged(int index)
       
   256 {
       
   257     if(index == 1)
       
   258     {
       
   259         m_currentTC = m_userTC;
       
   260         testCaseSelected(m_userTC);
       
   261     }
       
   262     else
       
   263         on_testSuiteView_clicked(testSuiteView->currentIndex());
       
   264 }
       
   265 
       
   266 void MainWindow::on_actionExecute_triggered()
       
   267 {
       
   268     Q_ASSERT(testCaseView);
       
   269     TestSuite *const ts = static_cast<TestSuite *>(sourceModel()->root());
       
   270 
       
   271     const TestItem::ExecutionStage stage = compileOnly->isChecked() ? TestItem::CompileOnly
       
   272                                                                     : TestItem::CompileAndRun;
       
   273 
       
   274     m_userTC->setLanguage(isXSLT20->isChecked() ? QXmlQuery::XSLT20 : QXmlQuery::XQuery10);
       
   275 
       
   276     if(m_currentTC)
       
   277     {
       
   278         const TestResult::List rlist(m_currentTC->execute(stage, ts));
       
   279         Q_ASSERT(rlist.count() == 1);
       
   280         const TestResult *const result = rlist.first();
       
   281         Q_ASSERT(result);
       
   282         testResultView->displayTestResult(result);
       
   283     }
       
   284     else
       
   285     {
       
   286         const QModelIndexList indexes = testSuiteView->selectionModel()->selectedIndexes();
       
   287         for (int i = 0; i < indexes.count(); ++i) {
       
   288             const QModelIndex source(sourceIndex(indexes.at(i)));
       
   289 
       
   290             TestItem *const ti = static_cast<TestItem *>(source.internalPointer());
       
   291             if(!ti)
       
   292                 return;
       
   293 
       
   294             /* ti is a TestGroup. It now executes its children, changed(TreeItem *) signals is
       
   295              * emitted which the view receives, and thus updates. */
       
   296             ti->execute(stage, ts);
       
   297         }
       
   298     }
       
   299 }
       
   300 
       
   301 void MainWindow::readSettings()
       
   302 {
       
   303     QSettings settings;
       
   304 
       
   305     settings.beginGroup(QLatin1String("MainWindow"));
       
   306     restoreState(settings.value(QLatin1String("state")).toByteArray(), Global::versionNumber);
       
   307     resize(settings.value(QLatin1String("size"), QSize(400, 400)).toSize());
       
   308     move(settings.value(QLatin1String("pos"), QPoint(200, 200)).toPoint());
       
   309     m_previousOpenedCatalog = settings.value(QLatin1String("PreviousOpenedCatalogFile")).toUrl();
       
   310     focusURI->setText(settings.value(QLatin1String("focusURI")).toString());
       
   311     isXSLT20->setChecked(settings.value(QLatin1String("isXSLT20")).toBool());
       
   312     compileOnly->setChecked(settings.value(QLatin1String("compileOnly")).toBool());
       
   313     m_currentSuiteType = (TestSuite::SuiteType)settings.value(QLatin1String("PreviousSuiteType"), isXSLT20->isChecked() ? TestSuite::XsltSuite : TestSuite::XQuerySuite).toInt();
       
   314 
       
   315     /* Open the previously opened catalog. */
       
   316     if(!m_previousOpenedCatalog.isEmpty())
       
   317     {
       
   318         openCatalog(m_previousOpenedCatalog, false, m_currentSuiteType);
       
   319     }
       
   320 
       
   321     sourceInput->setPlainText(settings.value(QLatin1String("sourceInput")).toString());
       
   322     testResultView->resultViewSelection->setCurrentIndex(
       
   323             settings.value(QLatin1String("ResultViewMethod"), 0).toInt());
       
   324     testResultView->outputStack->setCurrentIndex(settings.value(
       
   325             QLatin1String("ResultViewMethod"), 0).toInt());
       
   326 
       
   327     /* Restore the selected test case/group. */
       
   328     const QStringList rows(settings.value(QLatin1String("SelectedTestSuiteRow"),
       
   329                                           QString())
       
   330                            .toString().split(QLatin1Char(',')));
       
   331 
       
   332     if(!rows.isEmpty()) /* Ok, we have a selection. */
       
   333     {
       
   334         QAbstractItemModel *const model = testSuiteView->model();
       
   335         Q_ASSERT(model);
       
   336         QModelIndex p;
       
   337 
       
   338         for(int i = rows.count() - 1; i >= 0;  --i)
       
   339         {
       
   340             const QModelIndex childIndex(model->index(rows.at(i).toInt(), 0 , p));
       
   341 
       
   342             if(childIndex.isValid())
       
   343             {
       
   344                 testSuiteView->scrollTo(p); /* Work around for Qt issue #87575. */
       
   345                 p = childIndex;
       
   346             }
       
   347         }
       
   348 
       
   349         testSuiteView->scrollTo(p); /* Scrolls to it. */
       
   350         testSuiteView->setCurrentIndex(p); /* Selects it. */
       
   351         on_testSuiteView_clicked(p); /* Loads the test case in the Test Case View. */
       
   352     }
       
   353 
       
   354     /* Do it here. In this way the user-entered test case gets selected, if that tab
       
   355      * was previously used. */
       
   356     sourceTab->setCurrentIndex(settings.value(QLatin1String("SelectedTab"), 0).toInt());
       
   357     on_sourceTab_currentChanged(sourceTab->currentIndex());
       
   358 
       
   359     settings.endGroup();
       
   360 }
       
   361 
       
   362 void MainWindow::writeSettings()
       
   363 {
       
   364     QSettings settings;
       
   365 
       
   366     settings.beginGroup(QLatin1String("MainWindow"));
       
   367     settings.setValue(QLatin1String("state"), saveState(Global::versionNumber));
       
   368     settings.setValue(QLatin1String("pos"), pos());
       
   369     settings.setValue(QLatin1String("size"), size());
       
   370     settings.setValue(QLatin1String("sourceInput"), sourceInput->toPlainText());
       
   371     settings.setValue(QLatin1String("PreviousOpenedCatalogFile"), m_previousOpenedCatalog);
       
   372     settings.setValue(QLatin1String("PreviousSuiteType"), m_currentSuiteType);
       
   373     settings.setValue(QLatin1String("SelectedTab"), sourceTab->currentIndex());
       
   374     settings.setValue(QLatin1String("ResultViewMethod"),
       
   375                       testResultView->resultViewSelection->currentIndex());
       
   376     settings.setValue(QLatin1String("focusURI"),
       
   377                       focusURI->text());
       
   378     settings.setValue(QLatin1String("isXSLT20"),
       
   379                       isXSLT20->isChecked());
       
   380     settings.setValue(QLatin1String("compileOnly"),
       
   381                       compileOnly->isChecked());
       
   382 
       
   383     /* Store the selected test case/group. */
       
   384     QModelIndex selected(sourceIndex(testSuiteView->currentIndex()));
       
   385     if(selected.isValid())
       
   386     {
       
   387         QString result;
       
   388 
       
   389         do
       
   390         {
       
   391             result.append(QString::number(selected.row()));
       
   392             selected = selected.parent();
       
   393 
       
   394             if(selected.isValid())
       
   395                 result.append(QLatin1Char(','));
       
   396             else
       
   397                 break;
       
   398         }
       
   399         while(true);
       
   400 
       
   401         settings.setValue(QLatin1String("SelectedTestSuiteRow"), result);
       
   402     }
       
   403 
       
   404     settings.endGroup();
       
   405 }
       
   406 
       
   407 void MainWindow::setCurrentFile(const QUrl &f)
       
   408 {
       
   409     const QString fileName(f.toLocalFile());
       
   410     QSettings settings;
       
   411     settings.beginGroup(QLatin1String("MainWindow"));
       
   412     QStringList files(settings.value(QLatin1String("RecentFileList")).toStringList());
       
   413 
       
   414     files.removeAll(fileName);
       
   415     files.prepend(fileName);
       
   416     while(files.size() > MaximumRecentFiles)
       
   417         files.removeLast();
       
   418 
       
   419     settings.setValue(QLatin1String("RecentFileList"), files);
       
   420     settings.endGroup();
       
   421 
       
   422     updateRecentFileActions();
       
   423 }
       
   424 
       
   425 void MainWindow::updateRecentFileActions()
       
   426 {
       
   427     QSettings settings;
       
   428     settings.beginGroup(QLatin1String("MainWindow"));
       
   429     const QStringList files(settings.value(QLatin1String("RecentFileList")).toStringList());
       
   430     settings.endGroup();
       
   431 
       
   432     const int numRecentFiles = qMin(files.size(), static_cast<int>(MaximumRecentFiles));
       
   433 
       
   434     for(int i = 0; i < numRecentFiles; ++i)
       
   435     {
       
   436         const QString text(QString::fromLatin1("&%1 %2").arg(i + 1).arg(QFileInfo(files[i]).filePath()));
       
   437         m_recentFileActs[i]->setText(text);
       
   438         m_recentFileActs[i]->setData(QUrl::fromLocalFile(files[i]));
       
   439         m_recentFileActs[i]->setVisible(true);
       
   440     }
       
   441 
       
   442     for(int j = numRecentFiles; j < MaximumRecentFiles; ++j)
       
   443         m_recentFileActs[j]->setVisible(false);
       
   444 }
       
   445 
       
   446 void MainWindow::openRecentFile()
       
   447 {
       
   448     const QAction *const action = qobject_cast<QAction *>(sender());
       
   449     if(action)
       
   450         openCatalog(action->data().toUrl(), true, TestSuite::XQuerySuite);
       
   451 }
       
   452 
       
   453 void MainWindow::closeEvent(QCloseEvent *ev)
       
   454 {
       
   455     writeSettings();
       
   456     ev->accept();
       
   457 }
       
   458 
       
   459 void MainWindow::setupActions()
       
   460 {
       
   461     connect(actionQuit, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));
       
   462 
       
   463     for(int i = 0; i < MaximumRecentFiles; ++i)
       
   464     {
       
   465         m_recentFileActs[i] = new QAction(this);
       
   466         m_recentFileActs[i]->setVisible(false);
       
   467         connect(m_recentFileActs[i], SIGNAL(triggered()),
       
   468                 this, SLOT(openRecentFile()));
       
   469     }
       
   470 }
       
   471 
       
   472 void MainWindow::setupMenu()
       
   473 {
       
   474     QMenu *const menFile = findChild<QMenu *>(QLatin1String("menuFile"));
       
   475     Q_ASSERT(menFile);
       
   476     QAction *const actOpen = findChild<QAction *>(QLatin1String("actionExecute"));
       
   477     Q_ASSERT(actOpen);
       
   478     QMenu *const recent = new QMenu(QLatin1String("O&pen Recent"), this);
       
   479 
       
   480     menFile->insertMenu(actOpen, recent);
       
   481     menFile->insertSeparator(actOpen);
       
   482 
       
   483     for(int i = 0; i < MaximumRecentFiles; ++i)
       
   484         recent->addAction(m_recentFileActs[i]);
       
   485 
       
   486     updateRecentFileActions();
       
   487 
       
   488     QMenu *const menWindows = findChild<QMenu *>(QLatin1String("menuWindows"));
       
   489     Q_ASSERT(menWindows);
       
   490 
       
   491     menWindows->addAction(testCaseView->toggleViewAction());
       
   492     menWindows->addAction(testResultView->toggleViewAction());
       
   493     menWindows->addAction(functionView->toggleViewAction());
       
   494 }
       
   495 
       
   496 void MainWindow::on_actionRestart_triggered()
       
   497 {
       
   498     if(QProcess::startDetached(QCoreApplication::applicationFilePath()))
       
   499         QApplication::closeAllWindows();
       
   500     else
       
   501     {
       
   502         QTextStream err(stderr);
       
   503         err << "Failed to start " << qPrintable(QCoreApplication::applicationFilePath()) << endl;
       
   504     }
       
   505 }
       
   506 
       
   507 
       
   508 // vim: et:ts=4:sw=4:sts=4