/**************************************************************************** ** ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the Qt Autotester project. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** ** ** ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "mainwindow.h" #include "ui_mainwindow.h" #include "testprofile.h" #include "test.h" #include "qtdirectory.h" #include "qtdirectorydialog.h" #include "testview.h" #include "testviewlayout.h" #include "testgraphicsview.h" #include "clearablelineedit.h" #include "logger.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef Q_WS_MAC enum { DEFAULT_FONT_SIZE = 12 }; static const char *DEFAULT_FONT_FAMILY = "Monaco"; #else #ifdef Q_WS_X11 enum { DEFAULT_FONT_SIZE = 9 }; static const char *DEFAULT_FONT_FAMILY = "Monospace"; #else enum { DEFAULT_FONT_SIZE = 10 }; static const char *DEFAULT_FONT_FAMILY = "Courier"; #endif #endif QtDirectory *MainWindow::currentRepository = 0; TestProfile *MainWindow::currentProfile = 0; TestGraphicsView *MainWindow::view = 0; QMap MainWindow::testviews; QStandardItemModel *MainWindow::currentAutoTestModel = 0; /************************************************************************************************** **************************************************************************************************/ static void clearItemSelection(QStandardItem *item) { item->setData(Qt::Unchecked, Qt::CheckStateRole); for (int i = 0 ; i < item->rowCount() ; i++) { clearItemSelection(item->child(i)); } } /************************************************************************************************** **************************************************************************************************/ static void checkDirectorySelection(QStandardItem *item) { bool allChildrenChecked = true; for (int i = 0 ; i < item->rowCount() ; i++) { if (item->child(i)->data(Qt::UserRole + 1).toBool()) checkDirectorySelection(item->child(i)); if (item->child(i)->data(Qt::CheckStateRole) != Qt::Checked) { allChildrenChecked = false; } } if (allChildrenChecked) item->setData(Qt::Checked, Qt::CheckStateRole); } /************************************************************************************************** **************************************************************************************************/ static QStandardItem * findChildItemRecursive(QStandardItem *item, const QString &text) { if (QString::compare(item->text(), text) == 0) return item; for (int i = 0 ; i < item->rowCount() ; i++) { QStandardItem *found = findChildItemRecursive(item->child(i), text); if (found) return found; } return 0; } /************************************************************************************************** **************************************************************************************************/ bool CustomProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { QModelIndex index = sourceModel()->index(source_row, 0, source_parent); return filterAcceptsIndex(index, source_parent); } /************************************************************************************************** **************************************************************************************************/ bool CustomProxyModel::filterAcceptsIndex(QModelIndex index, QModelIndex parent, bool skipParentCheck, bool skipChildrenCheck) const { bool parentIsRoot = sourceModel()->data(parent).toString().startsWith("All Tests"); QModelIndex grandparent = sourceModel()->parent(parent); if (sourceModel()->data(index).toString().startsWith("All Tests")) return true; if (sourceModel()->data(index).toString().contains(filterRegExp())) return true; if (!skipChildrenCheck && sourceModel()->hasChildren(index)) { int count = sourceModel()->rowCount(index); for (int i = 0; i < count; i++) { QModelIndex childIndex = sourceModel()->index(i, 0, index); if (filterAcceptsIndex(childIndex, index, true)) return true; } } if (!skipParentCheck && !parentIsRoot && filterAcceptsIndex(parent, grandparent, false, true)) return true; return false; } /************************************************************************************************** **************************************************************************************************/ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow), dialog(new QtDirectoryDialog), inSetProfile(false), alreadyRestored(false), elapsedTimerID(0) { ui->setupUi(this); setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea); QWidget* titleWidget = new QWidget(this); ui->dockWidget->setTitleBarWidget(titleWidget); delete ui->filter; ui->filter = new ClearableLineEdit(ui->dockWidgetContents); ui->verticalLayout->insertWidget(1, ui->filter); connect(ui->filter, SIGNAL(textChanged(QString)), this, SLOT(on_filter_textChanged(QString))); ui->filter->setEnabled(false); #if QT_VERSION >= 0x040700 ui->filter->setPlaceholderText("Filter"); #endif ui->addVersion->setIcon(QIcon::fromTheme("list-add", QIcon(":/images/plus.png"))); ui->remVersion->setIcon(QIcon::fromTheme("list-remove", QIcon(":/images/minus.png"))); ui->reloadProfile->setIcon(QIcon::fromTheme("view-refresh", QIcon(":/images/reload.png"))); ui->saveProfile->setIcon(QIcon::fromTheme("document-save", QIcon(":/images/filesave.png"))); ui->remProfile->setIcon(QIcon::fromTheme("edit-delete", QIcon(":/images/delete.png"))); ui->runTests->setIcon(QIcon::fromTheme("media-playback-start", QIcon(":/images/start.png"))); ui->runTestsNoQMake->setIcon(QIcon::fromTheme("media-playback-start", QIcon(":/images/start.png"))); ui->stopTests->setIcon(QIcon::fromTheme("media-playback-stop", QIcon(":/images/stop.png"))); ui->skipCurrent->setIcon(QIcon::fromTheme("go-next", QIcon(":/images/next.png"))); ui->actionSave_Results->setIcon(QIcon::fromTheme("document-save")); ui->actionQuit->setIcon(QIcon::fromTheme("application-exit")); ui->actionRun_Tests->setIcon(QIcon::fromTheme("media-playback-start")); ui->actionStop_Tests->setIcon(QIcon::fromTheme("media-playback-stop")); ui->actionSkip_Current_Test->setIcon(QIcon::fromTheme("go-next")); ui->actionDefault_Zoom->setIcon(QIcon::fromTheme("zoom-original")); ui->actionZoom_to_Fit->setIcon(QIcon::fromTheme("zoom-fit-best")); ui->actionZoom_In->setIcon(QIcon::fromTheme("zoom-in")); ui->actionZoom_Out->setIcon(QIcon::fromTheme("zoom-out")); ui->actionShow_Explorer->setIcon(QIcon::fromTheme("system-file-manager")); ui->actionShow_Run_Panel->setIcon(QIcon::fromTheme("media-playback-start")); ui->actionShow_Output->setIcon(QIcon::fromTheme("utilities-terminal")); ui->actionSave_Results->setShortcut(QKeySequence::Save); ui->actionQuit->setShortcut(QKeySequence::Quit); ui->actionZoom_In->setShortcut(QKeySequence::ZoomIn); ui->actionZoom_Out->setShortcut(QKeySequence::ZoomOut); QFont font; font.setFamily(QString::fromUtf8(DEFAULT_FONT_FAMILY)); font.setPointSize(DEFAULT_FONT_SIZE); ui->output->setFont(font); connect(Logger::getIt(), SIGNAL(newLog(QString)), this, SLOT(onNewLogReceived(QString))); view = new TestGraphicsView(ui->viewContainer); view->setObjectName(QString::fromUtf8("graphicsView")); view->setFrameShape(QFrame::NoFrame); ui->viewContainerLayout->addWidget(view); onZoomLevelChanged(1.0); connect(view, SIGNAL(zoomLevelChanged(qreal)), this, SLOT(onZoomLevelChanged(qreal))); connect(dialog, SIGNAL(accepted()), this, SLOT(onDialogAccepted())); timerID = startTimer(0); restoreWindowSettings(); } /************************************************************************************************** **************************************************************************************************/ MainWindow::~MainWindow() { delete ui; delete dialog; delete currentAutoTestModel; foreach (QtDirectory *repo, repositories.values()) delete repo; foreach (TestProfile *profile, profiles.values()) delete profile; } /************************************************************************************************** **************************************************************************************************/ void MainWindow::addProfile(TestProfile *profile) { if (!profile) return; if (profiles.contains(profile->name())) return; profiles.insert(profile->name(), profile); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::removeProfile(const QString &name) { if (!profiles.contains(name)) return; delete profiles[name]; profiles.remove(name); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::addTest(const QString &name, const QString &path, const QString &proFile) { if (!currentProfile) return; if (currentProfile->testNames().contains(name)) return; Test *test = new Test(name, path, proFile); currentProfile->addTest(test); TestView *testview = new TestView(test); testviews.insert(name, testview); view->itemsLayout()->addItem(testview); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::removeTest(const QString &name) { if (!currentProfile || !currentProfile->testNames().contains(name)) return; view->itemsLayout()->removeTestView(testviews.value(name)); delete testviews[name]; testviews.remove(name); currentProfile->removeTest(name); QStandardItem *rootItem = currentAutoTestModel->invisibleRootItem()->child(0); QStandardItem *item = findChildItemRecursive(rootItem, name); if (item->data(Qt::CheckStateRole) == Qt::Checked) item->setData(Qt::Unchecked, Qt::CheckStateRole); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::setCurrentQtRepo(const QString &repoName) { if (!repositories.contains(repoName)) return; currentRepository = repositories.value(repoName); if (currentAutoTestModel) { delete currentAutoTestModel; delete proxyModel; currentAutoTestModel = 0; proxyModel = 0; } ui->profiles->clear(); ui->qtvariants->clear(); ui->qtvariants->addItems(currentRepository->variants()); QFileInfo f(currentRepository->testSrcDir()); if (!f.exists()) { ui->qtversions->setStyleSheet("QComboBox { color:red; }"); ui->qtvariants->setEnabled(false); ui->profiles->setEnabled(false); // clear TestViews foreach (TestView *tview, testviews.values()) { view->itemsLayout()->removeTestView(tview); delete tview; } testviews.clear(); currentProfile = 0; return; } else { ui->qtversions->setStyleSheet(""); ui->qtvariants->setEnabled(true); ui->profiles->setEnabled(true); } currentAutoTestModel = currentRepository->createModelFromPro(); proxyModel = new CustomProxyModel; proxyModel->setSourceModel(currentAutoTestModel); proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); ui->treeView->setModel(proxyModel); QStandardItem *rootItem = currentAutoTestModel->invisibleRootItem()->child(0, 0); ui->treeView->setExpanded(proxyModel->mapFromSource(currentAutoTestModel->indexFromItem(rootItem)), true); connect(currentAutoTestModel, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(onModelItemChanged(QStandardItem*))); ui->filter->setText(""); ui->remVersion->setEnabled(true); if (currentProfile) setCurrentProfile(currentProfile->name()); else setCurrentProfile(""); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::setCurrentProfile(const QString &profileName) { if (!currentRepository || !currentAutoTestModel) return; TestProfile *profile = profiles.value(profileName); if (!profile && !profileName.isEmpty()) return; inSetProfile = true; // clear TestViews foreach (TestView *tview, testviews.values()) { view->itemsLayout()->removeTestView(tview); delete tview; } testviews.clear(); if (currentProfile && currentProfile->name().isEmpty()) { ui->profiles->setItemText(0, ""); delete currentProfile; currentProfile = 0; } if (profileName.isEmpty()) { // temporary profile currentProfile = new TestProfile; } else { currentProfile = profile; } QString var = currentProfile->variant(); if (var.isEmpty()) { currentProfile->setVariant(ui->qtvariants->currentText()); } else { int idx = ui->qtvariants->findText(var); if (idx >= 0) { ui->qtvariants->setCurrentIndex(idx); } else { ui->qtvariants->addItem(var); ui->qtvariants->setCurrentIndex(ui->qtvariants->count() - 1); } } QStandardItem *rootItem = currentAutoTestModel->invisibleRootItem()->child(0); // clear old selection clearItemSelection(rootItem); // Set new selection according to profile QStringList testNames = currentProfile->testNames(); foreach (const QString &testName, testNames) { QStandardItem *item = findChildItemRecursive(rootItem, testName); Test *test = currentProfile->test(testName); if (item) { test->setAvailable(true); item->setData(Qt::Checked, Qt::CheckStateRole); TestView *testview = new TestView(test); testviews.insert(testName, testview); view->itemsLayout()->addItem(testview); } else { test->setAvailable(false); } } checkDirectorySelection(rootItem); connect(currentProfile, SIGNAL(stateChanged(TestProfile::ProfileState)), this, SLOT(onProfileStateChanged(TestProfile::ProfileState))); connect(currentProfile, SIGNAL(runningStateChanged()), this, SLOT(onProfileRunningStateChanged())); inSetProfile = false; } /************************************************************************************************** **************************************************************************************************/ void MainWindow::on_filter_textChanged(const QString &text) { if (!proxyModel) return; proxyModel->setFilterRegExp(text); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::onModelItemChanged(QStandardItem *item) { if (!currentProfile) return; if (!inSetProfile) { if (item->data(Qt::UserRole + 1).toBool()) { // The item is a directory if (QString::compare(item->text(), QLatin1String("All Tests")) == 0 && item->data(Qt::CheckStateRole) == Qt::Unchecked && proxyModel->filterRegExp().isEmpty()) { foreach (const QString &test, currentProfile->testNames()) { delete testviews[test]; currentProfile->removeTest(test); } testviews.clear(); view->itemsLayout()->clearItems(); } for (int i = 0 ; i < item->rowCount() ; i++) { if (proxyModel->filterAcceptsIndex(item->child(i)->index(), item->index(), true)) item->child(i)->setData(item->data(Qt::CheckStateRole), Qt::CheckStateRole); } } else { // The item is an auto-test if (item->data(Qt::CheckStateRole) == Qt::Checked) { addTest(item->text(), item->data(Qt::UserRole).toString(), item->data(Qt::UserRole + 2).toString()); } else { removeTest(item->text()); } } } ui->runTests->setEnabled(currentProfile->testCount() > 0); ui->actionRun_Tests->setEnabled(currentProfile->testCount() > 0); ui->arguments->setReadOnly(currentProfile->testCount() == 0); ui->runTestsNoQMake->setEnabled(currentProfile->testCount() > 0); ui->actionRun_Tests_Skip_QMake->setEnabled(currentProfile->testCount() > 0); ui->actionSave_Results->setEnabled(currentProfile->testCount() > 0); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::on_addVersion_clicked() { dialog->promptDialog(); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::on_remVersion_clicked() { if (!currentRepository) return; QMessageBox::StandardButton result = QMessageBox::question(this, "Delete Qt Version", QString("Delete Qt version %1?").arg(currentRepository->name()), QMessageBox::Yes | QMessageBox::No); if (result == QMessageBox::Yes) { QtDirectory *oldDir = currentRepository; currentRepository = 0; ui->qtversions->removeItem(ui->qtversions->currentIndex()); ui->qtversions->setStyleSheet(""); repositories.remove(oldDir->name()); delete oldDir; if (ui->qtversions->currentIndex() == -1) { delete currentAutoTestModel; delete proxyModel; currentAutoTestModel = 0; proxyModel = 0; ui->remVersion->setEnabled(false); ui->profiles->clear(); ui->qtvariants->clear(); } saveRepoSettings(); } } /************************************************************************************************** **************************************************************************************************/ void MainWindow::onDialogAccepted() { QString name = dialog->name(); QString location = dialog->location(); if (repositories.contains(name)) return; #ifdef Q_WS_WIN QtDirectory *dir = new QtDirectory(name, location, dialog->makeLocation()); #else QtDirectory *dir = new QtDirectory(name, location); #endif repositories.insert(name, dir); ui->qtversions->addItem(name); ui->qtversions->setCurrentIndex(ui->qtversions->findText(name)); if (ui->profiles->count() == 0) { ui->profiles->addItem("", ""); foreach (const TestProfile *profile, profiles.values()) { ui->profiles->addItem(profile->name(), profile->name()); } ui->profiles->setCurrentIndex(profiles.count() > 0 ? 1 : 0); } saveRepoSettings(); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::on_qtversions_currentIndexChanged(const QString &text) { setCurrentQtRepo(text); int qtRepoIndex = ui->qtversions->currentIndex(); ui->profiles->setEnabled(qtRepoIndex != -1); ui->label_2->setEnabled(qtRepoIndex != -1); ui->filter->setEnabled(qtRepoIndex != -1); ui->qtversions->setEnabled(qtRepoIndex != -1); ui->qtvariants->setEnabled(qtRepoIndex != -1); } void MainWindow::on_qtvariants_currentIndexChanged(const QString &text) { if (currentProfile) currentProfile->setVariant(text); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::on_profiles_currentIndexChanged(int index) { if (index == -1) { ui->reloadProfile->setEnabled(false); ui->saveProfile->setEnabled(false); ui->remProfile->setEnabled(false); ui->runTests->setEnabled(false); ui->runTestsNoQMake->setEnabled(false); ui->arguments->setReadOnly(true); ui->actionRun_Tests->setEnabled(false); ui->actionRun_Tests_Skip_QMake->setEnabled(false); ui->actionSave_Results->setEnabled(false); // clear TestViews foreach (TestView *tview, testviews.values()) { view->itemsLayout()->removeTestView(tview); delete tview; } testviews.clear(); if (currentProfile && currentProfile->name().isEmpty()) { delete currentProfile; } currentProfile = 0; return; } setCurrentProfile(ui->profiles->itemData(index).toString()); if (currentProfile && currentProfile->testCount() < 1) { ui->runTests->setEnabled(false); ui->runTestsNoQMake->setEnabled(false); ui->arguments->setReadOnly(true); ui->actionRun_Tests->setEnabled(false); ui->actionRun_Tests_Skip_QMake->setEnabled(false); ui->actionSave_Results->setEnabled(false); } if (ui->profiles->itemData(index).toString().isEmpty()) { ui->remProfile->setEnabled(false); ui->reloadProfile->setEnabled(false); ui->saveProfile->setEnabled(false); } else { ui->remProfile->setEnabled(true); if (currentProfile->state() == TestProfile::Saved) { ui->reloadProfile->setEnabled(false); ui->saveProfile->setEnabled(false); } else { ui->reloadProfile->setEnabled(true); ui->saveProfile->setEnabled(true); } } } /************************************************************************************************** **************************************************************************************************/ void MainWindow::onProfileStateChanged(TestProfile::ProfileState newState) { QString currentText = ui->profiles->currentText(); if (newState == TestProfile::Unsaved) { if (!currentText.endsWith(QLatin1Char('*'))) currentText += QLatin1Char('*'); ui->reloadProfile->setEnabled(true); ui->saveProfile->setEnabled(true); } else { if (currentText.endsWith(QLatin1Char('*'))) currentText.truncate(currentText.length() - 1); ui->reloadProfile->setEnabled(false); ui->saveProfile->setEnabled(false); } ui->profiles->setItemText(ui->profiles->currentIndex(), currentText); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::onProfileRunningStateChanged() { if (!currentProfile) return; if (currentProfile->runningState() == TestProfile::Running) { ui->elapsedTime->setText("00:00:00"); if (!elapsedTimerID) elapsedTimerID = startTimer(100); elapsedTimer.start(); ui->runTests->setEnabled(false); ui->runTestsNoQMake->setEnabled(false); ui->arguments->setReadOnly(true); ui->actionRun_Tests->setEnabled(false); ui->actionRun_Tests_Skip_QMake->setEnabled(false); ui->actionSave_Results->setEnabled(false); ui->stopTests->setEnabled(true); ui->skipCurrent->setEnabled(true); ui->actionStop_Tests->setEnabled(true); ui->actionSkip_Current_Test->setEnabled(true); ui->dockWidget->setEnabled(false); } else { if (elapsedTimerID) { killTimer(elapsedTimerID); elapsedTimerID = 0; } ui->runTests->setEnabled(true); ui->runTestsNoQMake->setEnabled(true); ui->arguments->setReadOnly(false); ui->actionRun_Tests->setEnabled(true); ui->actionRun_Tests_Skip_QMake->setEnabled(true); ui->actionSave_Results->setEnabled(true); ui->stopTests->setEnabled(false); ui->skipCurrent->setEnabled(false); ui->actionStop_Tests->setEnabled(false); ui->actionSkip_Current_Test->setEnabled(false); ui->dockWidget->setEnabled(true); } } /************************************************************************************************** **************************************************************************************************/ void MainWindow::on_reloadProfile_clicked() { if (!currentProfile) return; if (currentProfile->state() == TestProfile::Unsaved) { QMessageBox::StandardButton result = QMessageBox::question(this, "Reload Profile", "The changes made to this profile will be lost.\nDo you want to continue?", QMessageBox::Yes | QMessageBox::No); if (result == QMessageBox::Yes) { currentProfile->restore(); setCurrentProfile(currentProfile->name()); saveProfileSettings(); } } } /************************************************************************************************** **************************************************************************************************/ void MainWindow::on_remProfile_clicked() { if (!currentProfile) return; if (currentProfile->name().isEmpty()) return; QMessageBox::StandardButton result = QMessageBox::question(this, "Delete Profile", QString("Delete profile %1?").arg(currentProfile->name()), QMessageBox::Yes | QMessageBox::No); if (result == QMessageBox::Yes) { TestProfile *profile = currentProfile; ui->profiles->removeItem(ui->profiles->currentIndex()); removeProfile(profile->name()); saveProfileSettings(); } } /************************************************************************************************** **************************************************************************************************/ void MainWindow::on_saveProfile_clicked() { if (!currentRepository) return; if (currentProfile->name().isEmpty()) { QMessageBox prompt; prompt.setText("Enter profile name."); prompt.setStandardButtons(QMessageBox::Save | QMessageBox::Cancel); QLineEdit le(&prompt); le.resize(190, le.height()); prompt.layout()->setSpacing(25); le.setFocus(); le.move(prompt.sizeHint().width() / 2 - le.width() / 2, prompt.sizeHint().height() / 2 - le.sizeHint().height() / 2 - 10); int result = prompt.exec(); if (result == QMessageBox::Save) { if (le.text().isEmpty()) { QMessageBox::warning(this, "Save Profile", "Please enter a profile name."); return; } if (profiles.contains(le.text())) { QMessageBox::warning(this, "Save Profile", QString("A profile named %1 already exists.").arg(le.text())); return; } currentProfile->setName(le.text()); currentProfile->save(); addProfile(currentProfile); ui->profiles->addItem(le.text(), le.text()); ui->profiles->setCurrentIndex(ui->profiles->count() - 1); } } else { currentProfile->save(); } saveProfileSettings(); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::saveRepoSettings() { QSettings settings; settings.remove("qtversions"); settings.beginWriteArray("qtversions"); for (int i = 0 ; i < ui->qtversions->count(); i++) { QString repo = ui->qtversions->itemText(i); settings.setArrayIndex(i); settings.setValue("name", repositories.value(repo)->name()); settings.setValue("location", repositories.value(repo)->qmake()); #ifdef Q_WS_WIN settings.setValue("make", repositories.value(repo)->make()); #endif } settings.endArray(); saveProfileSettings(); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::saveProfileSettings() { QSettings settings; settings.remove("profiles"); settings.beginWriteArray("profiles"); int i = 0; foreach (const TestProfile *profile, profiles.values()) { settings.setArrayIndex(i); settings.setValue("name", profile->name()); settings.beginWriteArray("tests"); int j = 0; foreach (const Test *test, profile->savedTests()) { settings.setArrayIndex(j); settings.setValue("name", test->name()); settings.setValue("path", test->path()); settings.setValue("pro", test->proFile()); j++; } settings.endArray(); i++; } settings.endArray(); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::saveWindowSettings() { QSettings settings; settings.setValue("size", size()); settings.setValue("maximized", isMaximized()); settings.setValue("pos", pos()); settings.setValue("show-explorer", ui->dockWidget->isVisible()); settings.setValue("show-panel", ui->frame->isVisible()); settings.setValue("show-output", ui->outputDock->isVisible()); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::restoreSettings() { QSettings settings; QStringList repos; int size = settings.beginReadArray("qtversions"); for (int i = 0; i < size; ++i) { settings.setArrayIndex(i); QString name = settings.value("name").toString(); QString location = settings.value("location").toString(); #ifdef Q_WS_WIN QString make = settings.value("make").toString(); QtDirectory *dir = new QtDirectory(name, location, make); #else QtDirectory *dir = new QtDirectory(name, location); #endif repositories.insert(name, dir); repos.append(name); } settings.endArray(); size = settings.beginReadArray("profiles"); for (int i = 0; i < size; ++i) { settings.setArrayIndex(i); QString name = settings.value("name").toString(); TestProfile *profile = new TestProfile(name); addProfile(profile); int nbTests = settings.beginReadArray("tests"); for (int j = 0; j < nbTests; j++) { settings.setArrayIndex(j); QString testname = settings.value("name").toString(); QString path = settings.value("path").toString(); QString pro = settings.value("pro").toString(); Test *test = new Test(testname, path, pro); profile->addTestToList(test); } settings.endArray(); } settings.endArray(); int i = 0; foreach (const QString &repo, repos) { ui->qtversions->addItem(repo); QFileInfo f(repositories.value(repo)->testSrcDir()); if (!f.exists()) ui->qtversions->setItemData(i, QBrush(Qt::red), Qt::ForegroundRole); i++; } if (!repos.isEmpty()) { ui->profiles->addItem("", ""); foreach (const TestProfile *profile, profiles.values()) { ui->profiles->addItem(profile->name(), profile->name()); } ui->profiles->setCurrentIndex(profiles.count() > 0 ? 1 : 0); } } /************************************************************************************************** **************************************************************************************************/ void MainWindow::restoreWindowSettings() { QSettings settings; QSize size = settings.value("size", QSize(880, 600)).toSize(); bool maximized = settings.value("maximized", false).toBool(); QPoint pos = settings.value("pos").toPoint(); bool showExplorer = settings.value("show-explorer", true).toBool(); bool showPanel = settings.value("show-panel", true).toBool(); bool showOutput = settings.value("show-output", true).toBool(); resize(size); if (!pos.isNull()) move(pos); if (maximized) showMaximized(); ui->actionShow_Explorer->setChecked(showExplorer); ui->actionShow_Run_Panel->setChecked(showPanel); ui->actionShow_Output->setChecked(showOutput); ui->dockWidget->setVisible(showExplorer); ui->frame->setVisible(showPanel); ui->outputDock->setVisible(showOutput); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::on_runTests_clicked() { if (!currentProfile) return; Test::setRunQMake(true); currentProfile->run(); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::on_runTestsNoQMake_clicked() { if (!currentProfile) return; Test::setRunQMake(false); currentProfile->run(); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::on_stopTests_clicked() { if (!currentProfile) return; if (currentProfile->runningState() == TestProfile::NotRunning) return; currentProfile->cancelRun(); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::on_skipCurrent_clicked() { if (!currentProfile) return; if (currentProfile->runningState() == TestProfile::NotRunning) return; currentProfile->cancelRun(true); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::closeEvent(QCloseEvent *e) { if (currentProfile && currentProfile->runningState() == TestProfile::Running) currentProfile->cancelRun(); bool hasUnsavedProfile = false; foreach (const TestProfile *profile, profiles.values()) { if (profile->state() == TestProfile::Unsaved) { hasUnsavedProfile = true; break; } } if (hasUnsavedProfile) { QMessageBox::StandardButton result = QMessageBox::question(this, "Save Profiles", QString("Some profiles are not saved. Do you want to save these profiles before exiting?"), QMessageBox::SaveAll | QMessageBox::Discard | QMessageBox::Cancel); if (result == QMessageBox::Cancel) { e->ignore(); return; } else { if (result == QMessageBox::SaveAll) { foreach (TestProfile *profile, profiles.values()) { if (profile->state() == TestProfile::Unsaved) { profile->save(); } } } e->accept(); } } saveWindowSettings(); saveRepoSettings(); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::timerEvent(QTimerEvent *e) { Q_UNUSED(e); if (!view->isVisible()) return; if (e->timerId() == timerID) { if (!alreadyRestored) { alreadyRestored = true; killTimer(timerID); restoreSettings(); } } else if (e->timerId() == elapsedTimerID) { int elapsed = elapsedTimer.elapsed(); elapsed /= 1000; int hours = elapsed / 3600; elapsed -= hours * 3600; int minutes = elapsed / 60; elapsed -= minutes * 60; int seconds = elapsed; QString time = QString("%1:%2:%3").arg(hours, 2, 10, QLatin1Char('0')) .arg(minutes, 2, 10, QLatin1Char('0')) .arg(seconds, 2, 10, QLatin1Char('0')); ui->elapsedTime->setText(time); } } /************************************************************************************************** **************************************************************************************************/ void MainWindow::on_actionDefault_Zoom_triggered() { view->resetZoom(); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::on_actionZoom_to_Fit_triggered() { view->zoomFit(); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::on_actionZoom_In_triggered() { view->zoomIn(); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::on_actionZoom_Out_triggered() { view->zoomOut(); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::onZoomLevelChanged(qreal zoomLevel) { ui->actionDefault_Zoom->setEnabled(zoomLevel > 1.001 || zoomLevel < 0.999); ui->actionZoom_In->setEnabled(zoomLevel * ZOOM_IN_FACTOR < ZOOM_MAX); ui->actionZoom_Out->setEnabled(zoomLevel * ZOOM_OUT_FACTOR > ZOOM_MIN); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::on_actionSave_Results_triggered() { const QString resultsFilePath = QFileDialog::getSaveFileName(this, "Choose file to save test results to"); if (resultsFilePath.isEmpty()) return; const QMetaEnum statusEnum = Test::staticMetaObject.enumerator(Test::staticMetaObject.indexOfEnumerator("TestStatus")); QFile resultsFile(resultsFilePath); resultsFile.open(QIODevice::WriteOnly); QTextStream resultsStream(&resultsFile); QStringList testNames = currentProfile->testNames(); testNames.sort(); foreach (const QString &testName, testNames) { Test *test = currentProfile->test(testName); resultsStream << test->proFile() << ", " << statusEnum.valueToKey(test->status()) << "\n"; } } /************************************************************************************************** **************************************************************************************************/ void MainWindow::on_actionQuit_triggered() { QCoreApplication::quit(); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::on_actionRun_Tests_triggered() { on_runTests_clicked(); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::on_actionRun_Tests_Skip_QMake_triggered() { on_runTestsNoQMake_clicked(); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::on_actionStop_Tests_triggered() { on_stopTests_clicked(); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::on_actionSkip_Current_Test_triggered() { on_skipCurrent_clicked(); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::on_actionAbout_Autotester_triggered() { QString message = "

Qt AutoTester

" "

Based on Qt %1

" "

 

" "

Copyright 2010 Nokia Corporation. All rights reserved.

" "

The program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY" " OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

"; QMessageBox::about(this, "About Qt AutoTester", message.arg(qVersion())); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::on_arguments_textChanged(const QString &text) { Test::setGlobalArguments(text); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::on_actionShow_Explorer_triggered() { ui->dockWidget->setVisible(!ui->dockWidget->isVisible()); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::on_actionShow_Run_Panel_triggered() { ui->frame->setVisible(!ui->frame->isVisible()); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::on_actionShow_Output_triggered() { ui->outputDock->setVisible(!ui->outputDock->isVisible()); } /************************************************************************************************** **************************************************************************************************/ void MainWindow::onNewLogReceived(const QString &log) { ui->output->append(log.trimmed()); ui->output->verticalScrollBar()->setValue(ui->output->verticalScrollBar()->maximum()); }