diff --git a/kdevplatform/project/tests/test_projectmodel.cpp b/kdevplatform/project/tests/test_projectmodel.cpp index e3475ac771..534540b72e 100644 --- a/kdevplatform/project/tests/test_projectmodel.cpp +++ b/kdevplatform/project/tests/test_projectmodel.cpp @@ -1,546 +1,546 @@ /*************************************************************************** * Copyright 2010 Andreas Pakulat * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "test_projectmodel.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace KDevelop; void debugItemModel(QAbstractItemModel* m, const QModelIndex& parent=QModelIndex(), int depth=0) { Q_ASSERT(m); qDebug() << QByteArray(depth*2, '-') << m->data(parent).toString(); for(int i=0; irowCount(parent); i++) { debugItemModel(m, m->index(i, 0, parent), depth+1); } } void TestProjectModel::initTestCase() { AutoTestShell::init(); TestCore::initialize(Core::NoUi); qRegisterMetaType("QModelIndex"); model = ICore::self()->projectController()->projectModel(); new ModelTest( model, this ); proxy = new ProjectProxyModel( model ); new ModelTest(proxy, proxy); proxy->setSourceModel(model); } void TestProjectModel::init() { model->clear(); } void TestProjectModel::cleanupTestCase() { TestCore::shutdown(); } void TestProjectModel::testCreateFileSystemItems() { QFETCH( int, itemType ); QFETCH( Path, itemPath ); QFETCH( Path, expectedItemPath ); QFETCH( QString, expectedItemText ); QFETCH( QStringList, expectedRelativeItemPath ); QFETCH( int, expectedItemRow ); ProjectBaseItem* newitem = nullptr; switch( itemType ) { case ProjectBaseItem::Folder: newitem = new ProjectFolderItem( nullptr, itemPath ); break; case ProjectBaseItem::BuildFolder: newitem = new ProjectBuildFolderItem( nullptr, itemPath ); break; case ProjectBaseItem::File: newitem = new ProjectFileItem( nullptr, itemPath ); break; } int origRowCount = model->rowCount(); model->appendRow( newitem ); QCOMPARE( model->rowCount(), origRowCount+1 ); QCOMPARE( newitem->row(), expectedItemRow ); QModelIndex idx = model->index( expectedItemRow, 0, QModelIndex() ); QVERIFY( model->itemFromIndex( idx ) ); QCOMPARE( model->itemFromIndex( idx ), newitem ); QCOMPARE( newitem->text(), expectedItemText ); QCOMPARE( newitem->path(), expectedItemPath ); if( itemType == ProjectBaseItem::File ) { QCOMPARE( dynamic_cast( newitem )->fileName(), expectedItemText ); } if( itemType == ProjectBaseItem::Folder || itemType == ProjectBaseItem::BuildFolder ) { QCOMPARE( dynamic_cast( newitem )->folderName(), expectedItemText ); } QCOMPARE( newitem->type(), itemType ); QCOMPARE( model->data( idx ).toString(), expectedItemText ); QCOMPARE( model->indexFromItem( newitem ), idx ); QCOMPARE( model->pathFromIndex( idx ), expectedRelativeItemPath ); QCOMPARE( model->pathToIndex( expectedRelativeItemPath ), idx ); } void TestProjectModel::testCreateFileSystemItems_data() { QTest::addColumn( "itemType" ); QTest::addColumn( "itemPath" ); QTest::addColumn( "expectedItemPath" ); QTest::addColumn( "expectedItemText" ); QTest::addColumn( "expectedRelativeItemPath" ); QTest::addColumn( "expectedItemRow" ); QTest::newRow("RootFolder") << (int)ProjectBaseItem::Folder << Path(QUrl::fromLocalFile(QStringLiteral("/rootdir"))) << Path(QUrl::fromLocalFile(QStringLiteral("/rootdir/"))) << QStringLiteral("rootdir") << ( QStringList() << QStringLiteral("rootdir") ) << 0; QTest::newRow("RootBuildFolder") << (int)ProjectBaseItem::BuildFolder << Path(QUrl::fromLocalFile(QStringLiteral("/rootdir"))) << Path(QUrl::fromLocalFile(QStringLiteral("/rootdir/"))) << QStringLiteral("rootdir") << ( QStringList() << QStringLiteral("rootdir") ) << 0; QTest::newRow("RootFile") << (int)ProjectBaseItem::File << Path(QUrl::fromLocalFile(QStringLiteral("/rootfile"))) << Path(QUrl::fromLocalFile(QStringLiteral("/rootfile"))) << QStringLiteral("rootfile") << ( QStringList() << QStringLiteral("rootfile") ) << 0; } void TestProjectModel::testCreateTargetItems() { QFETCH( int, itemType ); QFETCH( QString, itemText ); QFETCH( QString, expectedItemText ); QFETCH( QStringList, expectedItemPath ); QFETCH( int, expectedItemRow ); ProjectBaseItem* newitem = nullptr; switch( itemType ) { case ProjectBaseItem::Target: newitem = new ProjectTargetItem( nullptr, itemText ); break; case ProjectBaseItem::LibraryTarget: newitem = new ProjectLibraryTargetItem( nullptr, itemText ); break; } int origRowCount = model->rowCount(); model->appendRow( newitem ); QCOMPARE( model->rowCount(), origRowCount+1 ); QCOMPARE( newitem->row(), expectedItemRow ); QModelIndex idx = model->index( expectedItemRow, 0, QModelIndex() ); QVERIFY( model->itemFromIndex( idx ) ); QCOMPARE( model->itemFromIndex( idx ), newitem ); QCOMPARE( newitem->text(), expectedItemText ); QCOMPARE( newitem->type(), itemType ); QCOMPARE( model->data( idx ).toString(), expectedItemText ); QCOMPARE( model->indexFromItem( newitem ), idx ); QCOMPARE( model->pathFromIndex( idx ), expectedItemPath ); QCOMPARE( model->pathToIndex( expectedItemPath ), idx ); } void TestProjectModel::testCreateTargetItems_data() { QTest::addColumn( "itemType" ); QTest::addColumn( "itemText" ); QTest::addColumn( "expectedItemText" ); QTest::addColumn( "expectedItemPath" ); QTest::addColumn( "expectedItemRow" ); QTest::newRow("RootTarget") << (int)ProjectBaseItem::Target << "target" << QStringLiteral("target") << ( QStringList() << QStringLiteral("target") ) << 0; QTest::newRow("RootLibraryTarget") << (int)ProjectBaseItem::LibraryTarget << "libtarget" << QStringLiteral("libtarget") << ( QStringList() << QStringLiteral("libtarget") ) << 0; } void TestProjectModel::testChangeWithProxyModel() { QSortFilterProxyModel* proxy = new QSortFilterProxyModel( this ); proxy->setSourceModel( model ); ProjectFolderItem* root = new ProjectFolderItem( nullptr, Path(QUrl::fromLocalFile(QStringLiteral("/folder1"))) ); root->appendRow( new ProjectFileItem( nullptr, Path(QUrl::fromLocalFile(QStringLiteral("/folder1/file1"))) ) ); model->appendRow( root ); QCOMPARE( model->rowCount(), 1 ); QCOMPARE( proxy->rowCount(), 1 ); model->removeRow( 0 ); QCOMPARE( model->rowCount(), 0 ); QCOMPARE( proxy->rowCount(), 0 ); } void TestProjectModel::testCreateSimpleHierarchy() { QString folderName = QStringLiteral("rootfolder"); QString fileName = QStringLiteral("file"); QString targetName = QStringLiteral("testtarged"); QString cppFileName = QStringLiteral("file.cpp"); ProjectFolderItem* rootFolder = new ProjectFolderItem( nullptr, Path(QUrl::fromLocalFile("/"+folderName)) ); QCOMPARE(rootFolder->baseName(), folderName); ProjectFileItem* file = new ProjectFileItem( fileName, rootFolder ); QCOMPARE(file->baseName(), fileName); ProjectTargetItem* target = new ProjectTargetItem( nullptr, targetName ); rootFolder->appendRow( target ); ProjectFileItem* targetfile = new ProjectFileItem( nullptr, Path(rootFolder->path(), cppFileName), target ); model->appendRow( rootFolder ); QCOMPARE( model->rowCount(), 1 ); QModelIndex folderIdx = model->index( 0, 0, QModelIndex() ); QCOMPARE( model->data( folderIdx ).toString(), folderName ); QCOMPARE( model->rowCount( folderIdx ), 2 ); QCOMPARE( model->itemFromIndex( folderIdx ), rootFolder ); QVERIFY( rootFolder->hasFileOrFolder( fileName ) ); QModelIndex fileIdx = model->index( 0, 0, folderIdx ); QCOMPARE( model->data( fileIdx ).toString(), fileName ); QCOMPARE( model->rowCount( fileIdx ), 0 ); QCOMPARE( model->itemFromIndex( fileIdx ), file ); QModelIndex targetIdx = model->index( 1, 0, folderIdx ); QCOMPARE( model->data( targetIdx ).toString(), targetName ); QCOMPARE( model->rowCount( targetIdx ), 1 ); QCOMPARE( model->itemFromIndex( targetIdx ), target ); QModelIndex targetFileIdx = model->index( 0, 0, targetIdx ); QCOMPARE( model->data( targetFileIdx ).toString(), cppFileName ); QCOMPARE( model->rowCount( targetFileIdx ), 0 ); QCOMPARE( model->itemFromIndex( targetFileIdx ), targetfile ); rootFolder->removeRow( 1 ); QCOMPARE( model->rowCount( folderIdx ), 1 ); delete file; file = nullptr; // Check that we also find a folder with the fileName new ProjectFolderItem( fileName, rootFolder ); QVERIFY( rootFolder->hasFileOrFolder( fileName ) ); delete rootFolder; QCOMPARE( model->rowCount(), 0 ); } void TestProjectModel::testItemSanity() { ProjectBaseItem* parent = new ProjectBaseItem( nullptr, QStringLiteral("test") ); ProjectBaseItem* child = new ProjectBaseItem( nullptr, QStringLiteral("test"), parent ); ProjectBaseItem* child2 = new ProjectBaseItem( nullptr, QStringLiteral("ztest"), parent ); ProjectFileItem* child3 = new ProjectFileItem( nullptr, Path(QUrl(QStringLiteral("file:///bcd"))), parent ); ProjectFileItem* child4 = new ProjectFileItem( nullptr, Path(QUrl(QStringLiteral("file:///abcd"))), parent ); // Just some basic santiy checks on the API QCOMPARE( parent->child( 0 ), child ); QCOMPARE( parent->row(), -1 ); QVERIFY( !parent->child( -1 ) ); QVERIFY( !parent->file() ); QVERIFY( !parent->folder() ); QVERIFY( !parent->project() ); QVERIFY( !parent->child( parent->rowCount() ) ); QCOMPARE( parent->iconName(), QString() ); QCOMPARE( parent->index(), QModelIndex() ); QCOMPARE( child->type(), (int)ProjectBaseItem::BaseItem ); QCOMPARE( child->lessThan( child2 ), true ); QCOMPARE( child3->lessThan( child4 ), false ); // Check that model is properly emitting data-changes model->appendRow( parent ); QCOMPARE( parent->index(), model->index(0, 0, QModelIndex()) ); QSignalSpy s( model, SIGNAL(dataChanged(QModelIndex,QModelIndex)) ); parent->setPath( Path(QStringLiteral("/newtest")) ); QCOMPARE( s.count(), 1 ); QCOMPARE( model->data( parent->index() ).toString(), QStringLiteral("newtest") ); parent->removeRow( child->row() ); } void TestProjectModel::testTakeRow() { - ProjectBaseItem* parent = new ProjectBaseItem( nullptr, QStringLiteral("test") ); - ProjectBaseItem* child = new ProjectBaseItem( nullptr, QStringLiteral("test"), parent ); - ProjectBaseItem* subchild = new ProjectBaseItem( nullptr, QStringLiteral("subtest"), child ); + QScopedPointer parent(new ProjectBaseItem( nullptr, QStringLiteral("test") )); + QScopedPointer child(new ProjectBaseItem( nullptr, QStringLiteral("test"), parent.data() )); + QScopedPointer subchild(new ProjectBaseItem( nullptr, QStringLiteral("subtest"), child.data() )); - model->appendRow( parent ); + model->appendRow( parent.data() ); QCOMPARE( parent->model(), model ); QCOMPARE( child->model(), model ); QCOMPARE( subchild->model(), model ); parent->takeRow( child->row() ); QCOMPARE( child->model(), static_cast(nullptr) ); QCOMPARE( subchild->model(), static_cast(nullptr) ); } void TestProjectModel::testRename() { QFETCH( int, itemType ); QFETCH( QString, itemText ); QFETCH( QString, newName ); QFETCH( bool, datachangesignal ); QFETCH( QString, expectedItemText ); QFETCH( int, expectedRenameCode ); const Path projectFolder = Path(QUrl::fromLocalFile(QStringLiteral("/dummyprojectfolder"))); - TestProject* proj = new TestProject; - ProjectFolderItem* rootItem = new ProjectFolderItem( proj, projectFolder, nullptr); + QScopedPointer proj(new TestProject()); + ProjectFolderItem* rootItem = new ProjectFolderItem( proj.data(), projectFolder, nullptr); proj->setProjectItem( rootItem ); new ProjectFileItem(QStringLiteral("existing"), rootItem); ProjectBaseItem* item = nullptr; if( itemType == ProjectBaseItem::Target ) { - item = new ProjectTargetItem( proj, itemText, rootItem ); + item = new ProjectTargetItem( proj.data(), itemText, rootItem ); } else if( itemType == ProjectBaseItem::File ) { item = new ProjectFileItem( itemText, rootItem ); } else if( itemType == ProjectBaseItem::Folder ) { item = new ProjectFolderItem( itemText, rootItem ); } else if( itemType == ProjectBaseItem::BuildFolder ) { item = new ProjectBuildFolderItem( itemText, rootItem ); } Q_ASSERT( item ); QCOMPARE(item->model(), model); QSignalSpy s( model, SIGNAL(dataChanged(QModelIndex,QModelIndex)) ); ProjectBaseItem::RenameStatus stat = item->rename( newName ); QCOMPARE( (int)stat, expectedRenameCode ); if( datachangesignal ) { QCOMPARE( s.count(), 1 ); QCOMPARE( qvariant_cast( s.takeFirst().at(0) ), item->index() ); } else { QCOMPARE( s.count(), 0 ); } QCOMPARE( item->text(), expectedItemText ); } void TestProjectModel::testRename_data() { QTest::addColumn( "itemType" ); QTest::addColumn( "itemText" ); QTest::addColumn( "newName" ); QTest::addColumn( "datachangesignal" ); QTest::addColumn( "expectedItemText" ); QTest::addColumn( "expectedRenameCode" ); QTest::newRow("RenameableTarget") << (int)ProjectBaseItem::Target << QStringLiteral("target") << QStringLiteral("othertarget") << true << QStringLiteral("othertarget") << (int)ProjectBaseItem::RenameOk; QTest::newRow("RenameableFile") << (int)ProjectBaseItem::File << QStringLiteral("newfile.cpp") << QStringLiteral("otherfile.cpp") << true << QStringLiteral("otherfile.cpp") << (int)ProjectBaseItem::RenameOk; QTest::newRow("SourceAndDestinationFileEqual") << (int)ProjectBaseItem::File << QStringLiteral("newfile.cpp") << QStringLiteral("newfile.cpp") << false << QStringLiteral("newfile.cpp") << (int)ProjectBaseItem::RenameOk; QTest::newRow("RenameableFolder") << (int)ProjectBaseItem::Folder << QStringLiteral("newfolder") << QStringLiteral("otherfolder") << true << QStringLiteral("otherfolder") << (int)ProjectBaseItem::RenameOk; QTest::newRow("SourceAndDestinationFolderEqual") << (int)ProjectBaseItem::Folder << QStringLiteral("newfolder") << QStringLiteral("newfolder") << false << QStringLiteral("newfolder") << (int)ProjectBaseItem::RenameOk; QTest::newRow("RenameableBuildFolder") << (int)ProjectBaseItem::BuildFolder << QStringLiteral("newbfolder") << QStringLiteral("otherbfolder") << true << QStringLiteral("otherbfolder") << (int)ProjectBaseItem::RenameOk; QTest::newRow("SourceAndDestinationBuildFolderEqual") << (int)ProjectBaseItem::BuildFolder << QStringLiteral("newbfolder") << QStringLiteral("newbfolder") << false << QStringLiteral("newbfolder") << (int)ProjectBaseItem::RenameOk; QTest::newRow("ExistingFileError") << (int)ProjectBaseItem::Folder << QStringLiteral("mynew") << QStringLiteral("existing") << false << QStringLiteral("mynew") << (int)ProjectBaseItem::ExistingItemSameName; QTest::newRow("InvalidNameError") << (int)ProjectBaseItem::File << QStringLiteral("mynew") << QStringLiteral("other/bash") << false << QStringLiteral("mynew") << (int)ProjectBaseItem::InvalidNewName; } void TestProjectModel::testWithProject() { - TestProject* proj = new TestProject(); - ProjectFolderItem* rootItem = new ProjectFolderItem( proj, Path(QUrl::fromLocalFile(QStringLiteral("/dummyprojectfolder"))), nullptr); + QScopedPointer proj(new TestProject()); + ProjectFolderItem* rootItem = new ProjectFolderItem( proj.data(), Path(QUrl::fromLocalFile(QStringLiteral("/dummyprojectfolder"))), nullptr); proj->setProjectItem( rootItem ); ProjectBaseItem* item = model->itemFromIndex( model->index( 0, 0 ) ); QCOMPARE( item, rootItem ); QCOMPARE( item->text(), proj->name() ); QCOMPARE( item->path(), proj->path() ); } void TestProjectModel::testItemsForPath() { QFETCH(Path, path); QFETCH(ProjectBaseItem*, root); QFETCH(int, matches); model->appendRow(root); auto items = model->itemsForPath(IndexedString(path.pathOrUrl())); QCOMPARE(items.size(), matches); foreach(ProjectBaseItem* item, items) { QVERIFY(item->path() == path); } model->clear(); } void TestProjectModel::testItemsForPath_data() { QTest::addColumn("path"); QTest::addColumn("root"); QTest::addColumn("matches"); { ProjectFolderItem* root = new ProjectFolderItem(nullptr, Path(QUrl::fromLocalFile(QDir::tempPath()))); ProjectFileItem* file = new ProjectFileItem(QStringLiteral("a"), root); QTest::newRow("find one") << file->path() << static_cast(root) << 1; } { ProjectFolderItem* root = new ProjectFolderItem(nullptr, Path(QUrl::fromLocalFile(QDir::tempPath()))); ProjectFolderItem* folder = new ProjectFolderItem(QStringLiteral("a"), root); ProjectFileItem* file = new ProjectFileItem(QStringLiteral("foo"), folder); ProjectTargetItem* target = new ProjectTargetItem(nullptr, QStringLiteral("b"), root); ProjectFileItem* file2 = new ProjectFileItem(nullptr, file->path(), target); Q_UNUSED(file2); QTest::newRow("find two") << file->path() << static_cast(root) << 2; } } void TestProjectModel::testProjectProxyModel() { ProjectFolderItem* root = new ProjectFolderItem(nullptr, Path(QUrl::fromLocalFile(QDir::tempPath()))); new ProjectFileItem(QStringLiteral("b1"), root); new ProjectFileItem(QStringLiteral("a1"), root); new ProjectFileItem(QStringLiteral("d1"), root); new ProjectFileItem(QStringLiteral("c1"), root); model->appendRow(root); QModelIndex proxyRoot = proxy->mapFromSource(root->index()); QCOMPARE(model->rowCount(root->index()), 4); QCOMPARE(proxy->rowCount(proxyRoot), 4); QCOMPARE(proxy->index(0, 0, proxy->index(0, 0)).data().toString(), QStringLiteral("a1")); QCOMPARE(proxy->index(1, 0, proxy->index(0, 0)).data().toString(), QStringLiteral("b1")); QCOMPARE(proxy->index(2, 0, proxy->index(0, 0)).data().toString(), QStringLiteral("c1")); QCOMPARE(proxy->index(3, 0, proxy->index(0, 0)).data().toString(), QStringLiteral("d1")); model->clear(); } void TestProjectModel::testProjectFileSet() { - TestProject* project = new TestProject; + QScopedPointer project(new TestProject()); QVERIFY(project->fileSet().isEmpty()); Path path(QUrl::fromLocalFile(QDir::tempPath() + "/a")); - ProjectFileItem* item = new ProjectFileItem(project, path, project->projectItem()); + ProjectFileItem* item = new ProjectFileItem(project.data(), path, project->projectItem()); QCOMPARE(project->fileSet().size(), 1); qDebug() << path << project->fileSet().toList().at(0).toUrl(); QCOMPARE(Path(project->fileSet().toList().at(0).toUrl()), path); delete item; QVERIFY(project->fileSet().isEmpty()); } void TestProjectModel::testProjectFileIcon() { QMimeDatabase db; - ProjectFileItem* item = new ProjectFileItem(nullptr, Path(QDir::tempPath() + "/foo.txt")); + QScopedPointer item(new ProjectFileItem(nullptr, Path(QDir::tempPath() + "/foo.txt"))); const QString txtIcon = db.mimeTypeForUrl(item->path().toUrl()).iconName(); QCOMPARE(item->iconName(), txtIcon); item->setPath(Path(QDir::tempPath() + "/bar.cpp")); QCOMPARE(item->iconName(), db.mimeTypeForUrl(item->path().toUrl()).iconName()); QVERIFY(item->iconName() != txtIcon); } -QTEST_MAIN( TestProjectModel) +QTEST_MAIN(TestProjectModel) diff --git a/kdevplatform/sublime/tests/test_areaoperation.cpp b/kdevplatform/sublime/tests/test_areaoperation.cpp index 52aa6ac81b..9fecec5b1a 100644 --- a/kdevplatform/sublime/tests/test_areaoperation.cpp +++ b/kdevplatform/sublime/tests/test_areaoperation.cpp @@ -1,726 +1,724 @@ /*************************************************************************** * Copyright 2006-2007 Alexander Dymo * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "test_areaoperation.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "areaprinter.h" using namespace Sublime; struct ViewCounter { ViewCounter() {} Area::WalkerMode operator()(AreaIndex *index) { count += index->views().count(); return Area::ContinueWalker; } int count = 0; }; void TestAreaOperation::init() { m_controller = new Controller(this); Document *doc1 = new UrlDocument(m_controller, QUrl::fromLocalFile(QStringLiteral("~/foo.cpp"))); Document *doc2 = new UrlDocument(m_controller, QUrl::fromLocalFile(QStringLiteral("~/boo.cpp"))); Document *doc3 = new UrlDocument(m_controller, QUrl::fromLocalFile(QStringLiteral("~/moo.cpp"))); Document *doc4 = new UrlDocument(m_controller, QUrl::fromLocalFile(QStringLiteral("~/zoo.cpp"))); //documents for tool views Document *tool1 = new ToolDocument(QStringLiteral("tool1"), m_controller, new SimpleToolWidgetFactory(QStringLiteral("tool1"))); Document *tool2 = new ToolDocument(QStringLiteral("tool2"), m_controller, new SimpleToolWidgetFactory(QStringLiteral("tool2"))); Document *tool3 = new ToolDocument(QStringLiteral("tool3"), m_controller, new SimpleToolWidgetFactory(QStringLiteral("tool3"))); //areas (aka perspectives) //view object names are in form AreaNumber.DocumentNumber.ViewNumber //"tool" prefix is there for tooldocument views m_area1 = new Area(m_controller, QStringLiteral("Area 1")); m_pView111 = doc1->createView(); m_pView111->setObjectName(QStringLiteral("view1.1.1")); m_area1->addView(m_pView111); m_pView121 = doc2->createView(); m_pView121->setObjectName(QStringLiteral("view1.2.1")); m_area1->addView(m_pView121); m_pView122 = doc2->createView(); m_pView122->setObjectName(QStringLiteral("view1.2.2")); m_area1->addView(m_pView122); m_pView131 = doc3->createView(); m_pView131->setObjectName(QStringLiteral("view1.3.1")); m_area1->addView(m_pView131); View *view = tool1->createView(); view->setObjectName(QStringLiteral("toolview1.1.1")); m_area1->addToolView(view, Sublime::Left); view = tool2->createView(); view->setObjectName(QStringLiteral("toolview1.2.1")); m_area1->addToolView(view, Sublime::Bottom); view = tool2->createView(); view->setObjectName(QStringLiteral("toolview1.2.2")); m_area1->addToolView(view, Sublime::Bottom); m_area2 = new Area(m_controller, QStringLiteral("Area 2")); View *view211 = doc1->createView(); view211->setObjectName(QStringLiteral("view2.1.1")); m_area2->addView(view211); View *view212 = doc1->createView(); view212->setObjectName(QStringLiteral("view2.1.2")); m_area2->addView(view212); View *view221 = doc2->createView(); view221->setObjectName(QStringLiteral("view2.2.1")); m_area2->addView(view221, view211, Qt::Vertical); View *view231 = doc3->createView(); view231->setObjectName(QStringLiteral("view2.3.1")); m_area2->addView(view231, view221, Qt::Horizontal); View *view241 = doc4->createView(); view241->setObjectName(QStringLiteral("view2.4.1")); m_area2->addView(view241, view212, Qt::Vertical); view = tool1->createView(); view->setObjectName(QStringLiteral("toolview2.1.1")); m_area2->addToolView(view, Sublime::Bottom); view = tool2->createView(); view->setObjectName(QStringLiteral("toolview2.2.1")); m_area2->addToolView(view, Sublime::Right); view = tool3->createView(); view->setObjectName(QStringLiteral("toolview2.3.1")); m_area2->addToolView(view, Sublime::Top); view = tool3->createView(); view->setObjectName(QStringLiteral("toolview2.3.2")); m_area2->addToolView(view, Sublime::Top); m_area3 = new Area(m_controller, QStringLiteral("Area 3")); View *view0 = doc1->createView(); view0->setObjectName(QStringLiteral("view3.1.1")); m_area3->addView(view0); View *view1 = doc2->createView(); view1->setObjectName(QStringLiteral("view3.1.2")); m_area3->addView(view1, view0); View *view2 = doc3->createView(); view2->setObjectName(QStringLiteral("view3.1.3")); m_area3->addView(view2, view1); View *view3 = doc4->createView(); view3->setObjectName(QStringLiteral("view3.1.4")); m_area3->addView(view3, view1); m_controller->addDefaultArea(m_area1); m_controller->addDefaultArea(m_area2); m_controller->addDefaultArea(m_area3); } void TestAreaOperation::cleanup() { delete m_area1; delete m_area2; delete m_controller; m_area1 = nullptr; m_area2 = nullptr; m_controller = nullptr; } void TestAreaOperation::areaConstruction() { //check if areas has proper object names QCOMPARE(m_area1->objectName(), QStringLiteral("Area 1")); QCOMPARE(m_area2->objectName(), QStringLiteral("Area 2")); //check that area1 contents is properly initialised AreaViewsPrinter viewsPrinter1; m_area1->walkViews(viewsPrinter1, m_area1->rootIndex()); QCOMPARE(viewsPrinter1.result, QStringLiteral("\n\ [ view1.1.1 view1.2.1 view1.2.2 view1.3.1 ]\n\ ")); AreaToolViewsPrinter toolViewsPrinter1; m_area1->walkToolViews(toolViewsPrinter1, Sublime::AllPositions); QCOMPARE(toolViewsPrinter1.result, QStringLiteral("\n\ toolview1.1.1 [ left ]\n\ toolview1.2.1 [ bottom ]\n\ toolview1.2.2 [ bottom ]\n\ ")); //check that area2 contents is properly initialised AreaViewsPrinter viewsPrinter2; m_area2->walkViews(viewsPrinter2, m_area2->rootIndex()); QCOMPARE(viewsPrinter2.result, QStringLiteral("\n\ [ vertical splitter ]\n\ [ vertical splitter ]\n\ [ view2.1.1 view2.1.2 ]\n\ [ view2.4.1 ]\n\ [ horizontal splitter ]\n\ [ view2.2.1 ]\n\ [ view2.3.1 ]\n\ ")); AreaToolViewsPrinter toolViewsPrinter2; m_area2->walkToolViews(toolViewsPrinter2, Sublime::AllPositions); QCOMPARE(toolViewsPrinter2.result, QStringLiteral("\n\ toolview2.1.1 [ bottom ]\n\ toolview2.2.1 [ right ]\n\ toolview2.3.1 [ top ]\n\ toolview2.3.2 [ top ]\n\ ")); } void TestAreaOperation::mainWindowConstruction() { //====== check for m_area1 ====== MainWindow mw1(m_controller); m_controller->showArea(m_area1, &mw1); checkArea1(&mw1); ///////////// //====== check for m_area2 ====== MainWindow mw2(m_controller); m_controller->showArea(m_area2, &mw2); checkArea2(&mw2); } void TestAreaOperation::checkArea1(MainWindow *mw) { Area *area = mw->area(); //check that all docks have their widgets foreach (View *dock, mw->toolDocks()) { //QVERIFY(dock->widget() != 0); QVERIFY(dock->hasWidget()); } QCOMPARE(mw->toolDocks().count(), area->toolViews().count()); //check that mainwindow have all splitters and widgets in splitters inside centralWidget QWidget *central = mw->centralWidget(); QVERIFY(central != nullptr); QVERIFY(central->inherits("QWidget")); QWidget *splitter = central->findChild(); QVERIFY(splitter); QVERIFY(splitter->inherits("QSplitter")); //check that we have a container and 4 views inside Container *container = splitter->findChild(); QVERIFY(container); ViewCounter c; area->walkViews(c, area->rootIndex()); QCOMPARE(container->count(), c.count); for (int i = 0; i < container->count(); ++i) QVERIFY(container->widget(i) != nullptr); } void TestAreaOperation::checkArea2(MainWindow *mw) { Area *area = mw->area(); //check that all docks have their widgets foreach (View *dock, mw->toolDocks()) { //QVERIFY(dock->widget() != 0); QVERIFY(dock->hasWidget()); } QCOMPARE(mw->toolDocks().count(), area->toolViews().count()); //check that mainwindow have all splitters and widgets in splitters inside centralWidget QWidget *central = mw->centralWidget(); QVERIFY(central != nullptr); QVERIFY(central->inherits("QWidget")); QWidget *splitter = central->findChild(); QVERIFY(splitter); QVERIFY(splitter->inherits("QSplitter")); //check that we have 4 properly initialized containers const QList containers = splitter->findChildren(); QCOMPARE(containers.count(), 4); int widgetCount = 0; for (Container* c : containers) { for (int i = 0; i < c->count(); ++i) QVERIFY(c->widget(i) != nullptr); widgetCount += c->count(); } ViewCounter c; area->walkViews(c, area->rootIndex()); QCOMPARE(widgetCount, c.count); //check that we have 7 splitters: 2 vertical and 1 horizontal, rest is not split QList splitters = splitter->findChildren(); splitters.append(qobject_cast(splitter)); QCOMPARE(splitters.count(), 6+1); //6 child splitters + 1 central itself = 7 splitters int verticalSplitterCount = 0; int horizontalSplitterCount = 0; foreach (QSplitter *s, splitters) { if (s->count() == 1) continue; //this is a splitter with container inside, its orientation is not relevant if (s->orientation() == Qt::Vertical) verticalSplitterCount += 1; else horizontalSplitterCount += 1; } QCOMPARE(verticalSplitterCount, 2); QCOMPARE(horizontalSplitterCount, 1); } void TestAreaOperation::areaCloning() { //show m_area1 in MainWindow1 MainWindow mw1(m_controller); m_controller->showArea(m_area1, &mw1); checkArea1(&mw1); //now try to show the same area in MainWindow2 and check that we get a clone MainWindow mw2(m_controller); m_controller->showArea(m_area1, &mw2); //two mainwindows have different areas QVERIFY(mw1.area() != mw2.area()); //the area for the second mainwindow is a clone of the //original area and should have the same name. QVERIFY(mw2.area()->objectName() == mw1.area()->objectName()); //check mainwindow layouts - original and copy checkArea1(&mw1); checkArea1(&mw2); } /*! Functor used by areaSwitchingInSameMainWindow() Walks all Views and checks if they got a widget. hasWidget will be set to false if any View lacks a widget.*/ struct AreaWidgetChecker { AreaWidgetChecker() = default; Area::WalkerMode operator()(AreaIndex *index) { foreach (View *view, index->views()) { if (!view->hasWidget()) { failureMessage += view->objectName() + " has no widget\n"; foundViewWithoutWidget = true; } } return Area::ContinueWalker; } Area::WalkerMode operator()(View *view, Sublime::Position) { if (!view->hasWidget()) { foundViewWithoutWidget = true; failureMessage += view->objectName() + " has no widget\n"; } return Area::ContinueWalker; } - char* message() { - return qstrdup(failureMessage.toLatin1().data()); - } + bool foundViewWithoutWidget = false; QString failureMessage; }; void TestAreaOperation::areaSwitchingInSameMainwindow() { MainWindow mw(m_controller); m_controller->showArea(m_area1, &mw); checkArea1(&mw); m_controller->showArea(m_area2, &mw); checkArea2(&mw); //check what happened to area1 widgets, they should be intact AreaWidgetChecker checker; m_area1->walkViews(checker, m_area1->rootIndex()); m_area1->walkToolViews(checker, Sublime::AllPositions); - QVERIFY2(!checker.foundViewWithoutWidget, checker.message()); + QVERIFY2(!checker.foundViewWithoutWidget, checker.failureMessage.toLatin1().data()); } void TestAreaOperation::simpleViewAdditionAndDeletion() { // set TabBarOpenAfterCurrent=0, otherwise we'd have a different order of tabs int oldTabBarOpenAfterCurrent; { KConfigGroup uiGroup = KSharedConfig::openConfig()->group("UiSettings"); oldTabBarOpenAfterCurrent = uiGroup.readEntry("TabBarOpenAfterCurrent", 1); uiGroup.writeEntry("TabBarOpenAfterCurrent", 0); uiGroup.sync(); } m_controller->loadSettings(); MainWindow mw(m_controller); m_controller->addMainWindow(&mw); m_controller->showArea(m_area1, &mw); checkArea1(&mw); Document *doc5 = new UrlDocument(m_controller, QUrl::fromLocalFile(QStringLiteral("~/new.cpp"))); View *view = doc5->createView(); view->setObjectName(QStringLiteral("view1.5.1")); m_area1->addView(view); checkAreaViewsDisplay(&mw, m_area1, QStringLiteral("\n[ view1.1.1 view1.2.1 view1.2.2 view1.3.1 view1.5.1 ]\n"), 1, 1, QStringLiteral("Added an url view (view1.5.1)")); //now remove view and check that area is valid delete m_area1->removeView(view); checkAreaViewsDisplay(&mw, m_area1, QStringLiteral("\n[ view1.1.1 view1.2.1 view1.2.2 view1.3.1 ]\n"), 1, 1, QStringLiteral("Removed the url view (view1.5.1)")); //now remove all other views one by one and leave an empty container const QList list(m_area1->views()); for (View* view : list) { delete m_area1->removeView(view); } checkAreaViewsDisplay(&mw, m_area1, QStringLiteral("\n[ horizontal splitter ]\n"), 0, 1, QStringLiteral("Removed all views. Only horizontal splitter should remain.")); //add a view again and check that mainwindow is correctly reconstructed view = doc5->createView(); view->setObjectName(QStringLiteral("view1.5.1")); m_area1->addView(view); checkAreaViewsDisplay(&mw, m_area1, QStringLiteral("\n[ view1.5.1 ]\n"), 1, 1, QStringLiteral("Added a single view to previously emptied mainwindow.")); { KConfigGroup uiGroup = KSharedConfig::openConfig()->group("UiSettings"); uiGroup.writeEntry("TabBarOpenAfterCurrent", oldTabBarOpenAfterCurrent); uiGroup.sync(); } m_controller->loadSettings(); } void TestAreaOperation::complexViewAdditionAndDeletion() { Area *area = m_area2; MainWindow mw(m_controller); m_controller->addMainWindow(&mw); m_controller->showArea(m_area2, &mw); Document *doc5 = new UrlDocument(m_controller, QUrl::fromLocalFile(QStringLiteral("~/new.cpp"))); View *view = doc5->createView(); view->setObjectName(QStringLiteral("view2.5.1")); View *view221 = findNamedView(area, QStringLiteral("view2.2.1")); QVERIFY(view221); area->addView(view, view221, Qt::Vertical); checkAreaViewsDisplay(&mw, area, QStringLiteral("\n\ [ vertical splitter ]\n\ [ vertical splitter ]\n\ [ view2.1.1 view2.1.2 ]\n\ [ view2.4.1 ]\n\ [ horizontal splitter ]\n\ [ vertical splitter ]\n\ [ view2.2.1 ]\n\ [ view2.5.1 ]\n\ [ view2.3.1 ]\n\ "), 5, 8+1); //now delete view221 delete area->removeView(view221); checkAreaViewsDisplay(&mw, area, QStringLiteral("\n\ [ vertical splitter ]\n\ [ vertical splitter ]\n\ [ view2.1.1 view2.1.2 ]\n\ [ view2.4.1 ]\n\ [ horizontal splitter ]\n\ [ view2.5.1 ]\n\ [ view2.3.1 ]\n\ "), 4, 6+1); //remove one more view, this time the one inside non-empty container View *view211 = findNamedView(area, QStringLiteral("view2.1.1")); delete m_area2->removeView(view211); checkAreaViewsDisplay(&mw, area, QStringLiteral("\n\ [ vertical splitter ]\n\ [ vertical splitter ]\n\ [ view2.1.2 ]\n\ [ view2.4.1 ]\n\ [ horizontal splitter ]\n\ [ view2.5.1 ]\n\ [ view2.3.1 ]\n\ "), 4, 6+1); //and now remove all remaining views one by one delete m_area2->removeView(findNamedView(area, QStringLiteral("view2.1.2"))); checkAreaViewsDisplay(&mw, area, QStringLiteral("\n\ [ vertical splitter ]\n\ [ view2.4.1 ]\n\ [ horizontal splitter ]\n\ [ view2.5.1 ]\n\ [ view2.3.1 ]\n\ "), 3, 4+1); delete m_area2->removeView(findNamedView(area, QStringLiteral("view2.4.1"))); checkAreaViewsDisplay(&mw, area, QStringLiteral("\n\ [ horizontal splitter ]\n\ [ view2.5.1 ]\n\ [ view2.3.1 ]\n\ "), 2, 2+1); delete m_area2->removeView(findNamedView(area, QStringLiteral("view2.5.1"))); checkAreaViewsDisplay(&mw, area, QStringLiteral("\n\ [ view2.3.1 ]\n\ "), 1, 1); delete m_area2->removeView(findNamedView(area, QStringLiteral("view2.3.1"))); checkAreaViewsDisplay(&mw, area, QStringLiteral("\n\ [ horizontal splitter ]\n\ "), 0, 1); } void TestAreaOperation::toolViewAdditionAndDeletion() { MainWindow mw(m_controller); m_controller->showArea(m_area1, &mw); checkArea1(&mw); Document *tool4 = new ToolDocument(QStringLiteral("tool4"), m_controller, new SimpleToolWidgetFactory(QStringLiteral("tool4"))); View *view = tool4->createView(); view->setObjectName(QStringLiteral("toolview1.4.1")); m_area1->addToolView(view, Sublime::Right); //check that area is in valid state AreaToolViewsPrinter toolViewsPrinter1; m_area1->walkToolViews(toolViewsPrinter1, Sublime::AllPositions); QCOMPARE(toolViewsPrinter1.result, QStringLiteral("\n\ toolview1.1.1 [ left ]\n\ toolview1.2.1 [ bottom ]\n\ toolview1.2.2 [ bottom ]\n\ toolview1.4.1 [ right ]\n\ ")); //check that mainwindow has newly added tool view foreach (View *dock, mw.toolDocks()) QVERIFY(dock->widget() != nullptr); QCOMPARE(mw.toolDocks().count(), m_area1->toolViews().count()); //now remove tool view m_area1->removeToolView(view); AreaToolViewsPrinter toolViewsPrinter2; //check that area doesn't have it anymore m_area1->walkToolViews(toolViewsPrinter2, Sublime::AllPositions); QCOMPARE(toolViewsPrinter2.result, QStringLiteral("\n\ toolview1.1.1 [ left ]\n\ toolview1.2.1 [ bottom ]\n\ toolview1.2.2 [ bottom ]\n\ ")); //check that mainwindow has newly added tool view foreach (View *dock, mw.toolDocks()) QVERIFY(dock->widget() != nullptr); QCOMPARE(mw.toolDocks().count(), m_area1->toolViews().count()); } void TestAreaOperation::testAddingViewAfter() { const QList list(m_area3->views()); for (View* view : list) { qDebug() << "name of view : " << view->objectName() << " , it's index : " << m_area3->views().indexOf(view); } } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// void TestAreaOperation::splitViewActiveTabsTest() { MainWindow mw(m_controller); m_controller->showArea(m_area1, &mw); checkArea1(&mw); // at first show of the area, the active view should be m_pView111 QCOMPARE(mw.activeView(), m_pView111); // Try to get to the main container : // get the central widget QWidget *pCentral = mw.centralWidget(); QVERIFY(pCentral); QVERIFY(pCentral->inherits("QWidget")); // get its first splitter QWidget *pSplitter = pCentral->findChild(); QVERIFY(pSplitter); QVERIFY(pSplitter->inherits("QSplitter")); // finally, get the splitter's container Container *pContainer = pSplitter->findChild(); QVERIFY(pContainer); // verify that the current active widget in the container is the one in activeview (m_pView111) QCOMPARE(pContainer->currentWidget(), mw.activeView()->widget()); // activate the second tab of the area (view212) mw.activateView(m_pView121); // verify that the active view was correctly updated to m_pView121 QCOMPARE(mw.activeView(), m_pView121); // check if the container's current widget was updated to the active view's QCOMPARE(pContainer->currentWidget(), mw.activeView()->widget()); // now, create a split view of the active view (m_pView121) Sublime::View *pNewView = mw.activeView()->document()->createView(); pNewView->setObjectName("splitOf" + mw.activeView()->objectName()); m_area1->addView(pNewView, mw.activeView(), Qt::Vertical); // verify that creating a new view did not break the central widget QCOMPARE(pCentral, mw.centralWidget()); // verify that creating a new view did not break the main splitter QCOMPARE(pSplitter, pCentral->findChild()); // creating a new view created two new children splitters, get them QVERIFY(pSplitter->findChildren().size() == 2); QWidget *pFirstSplitter = pSplitter->findChildren().at(0); QVERIFY(pFirstSplitter); QWidget *pSecondSplitter = pSplitter->findChildren().at(1); QVERIFY(pSecondSplitter); // for each splitter, get the corresponding container Container *pFirstContainer = pFirstSplitter->findChild(); QVERIFY(pFirstContainer); Container *pSecondContainer = pSecondSplitter->findChild(); QVERIFY(pSecondContainer); // the active view should have remained view121 QCOMPARE(mw.activeView(), m_pView121); // pFirstContainer should contain the newView's widget QVERIFY(pFirstContainer->hasWidget(pNewView->widget())); // the new view's widget should be the current widget of the new container QCOMPARE(pFirstContainer->currentWidget(), pNewView->widget()); // pSecondContainer should contain all the old views widgets QVERIFY(pSecondContainer->hasWidget(m_pView111->widget())); QVERIFY(pSecondContainer->hasWidget(m_pView121->widget())); QVERIFY(pSecondContainer->hasWidget(m_pView122->widget())); QVERIFY(pSecondContainer->hasWidget(m_pView131->widget())); // the active widget should be the current widget of the second container QCOMPARE(pSecondContainer->currentWidget(), mw.activeView()->widget()); //////////////////////////////////////////////////////////////////////////// // now, activate the new view and check if all went well mw.activateView(pNewView); // active view should now be newView QCOMPARE(mw.activeView(), pNewView); // the active widget should be the current widget of the new container QCOMPARE(pFirstContainer->currentWidget(), mw.activeView()->widget()); // the current widget of the old container should have remained view121's QCOMPARE(pSecondContainer->currentWidget(), m_pView121->widget()); //////////////////////////////////////////////////////////////////////////// // now delete newView and check area state delete m_area1->removeView(pNewView); // verify that deleting the view did not broke the central widget QCOMPARE(pCentral, mw.centralWidget()); // removing the view should have destroyed the sub splitters and containers, // so get the main one and verify that deleting the view did not break it QCOMPARE(pSplitter, pCentral->findChild()); // get the new container inside the main splitter pContainer = pSplitter->findChild(); QVERIFY(pContainer); // active view should now be back to m_pView121 again QCOMPARE(mw.activeView(), m_pView121); // check also the container current widget QCOMPARE(pContainer->currentWidget(), mw.activeView()->widget()); } void TestAreaOperation::checkAreaViewsDisplay(MainWindow *mw, Area *area, const QString &printedAreas, int containerCount, int splitterCount, const QString& location) { //check area AreaViewsPrinter viewsPrinter; area->walkViews(viewsPrinter, area->rootIndex()); QCOMPARE(viewsPrinter.result, printedAreas); //check mainwindow QWidget *central = mw->centralWidget(); QVERIFY(central != nullptr); QVERIFY(central->inherits("QWidget")); QWidget *splitter = central->findChild(); QVERIFY(splitter); QVERIFY(splitter->inherits("QSplitter")); //check containers const QList containers = splitter->findChildren(); QString failMsg = QStringLiteral("\nFailure while checking area contents @ %1\n" "Expected %2 containers in central splitter but got %3 \n"). arg(location).arg(containerCount).arg(containers.count()); QVERIFY2(containers.count() == containerCount, failMsg.toLatin1().data()); int widgetCount = 0; for (Container* c : containers) { for (int i = 0; i < c->count(); ++i) { QVERIFY(c->widget(i) != nullptr); QVERIFY(c->widget(i)->parentWidget() != nullptr); } widgetCount += c->count(); } ViewCounter c; area->walkViews(c, area->rootIndex()); QCOMPARE(widgetCount, c.count); QList splitters = splitter->findChildren(); splitters.append(qobject_cast(splitter)); QCOMPARE(splitters.count(), splitterCount); } View *TestAreaOperation::findNamedView(Area *area, const QString &name) { foreach (View *view, area->views()) if (view->objectName() == name) return view; return nullptr; } /////////// QTEST_MAIN(TestAreaOperation) diff --git a/kdevplatform/sublime/tests/test_controller.cpp b/kdevplatform/sublime/tests/test_controller.cpp index aab9681c3e..36d2e32e22 100644 --- a/kdevplatform/sublime/tests/test_controller.cpp +++ b/kdevplatform/sublime/tests/test_controller.cpp @@ -1,87 +1,87 @@ /*************************************************************************** * Copyright 2007 Alexander Dymo * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "test_controller.h" #include #include #include #include #include #include #include using namespace Sublime; void TestController::documentDeletion() { Controller controller; Document *doc = new ToolDocument(QStringLiteral("tool"), &controller, new SimpleToolWidgetFactory(QStringLiteral("tool"))); QCOMPARE(controller.documents().count(), 1); delete doc; QCOMPARE(controller.documents().count(), 0); } void TestController::areaDeletion() { - Controller* controller = new Controller; - Document *doc = new ToolDocument(QStringLiteral("tool"), controller, new SimpleToolWidgetFactory(QStringLiteral("tool"))); + Controller controller; + Document *doc = new ToolDocument(QStringLiteral("tool"), &controller, new SimpleToolWidgetFactory(QStringLiteral("tool"))); //create a view which does not belong to an area View* view1 = doc->createView(); Q_UNUSED(view1); //create an area and two views in it - Area *area = new Area(controller, QStringLiteral("MyArea")); - controller->addDefaultArea(area); - QCOMPARE(controller->defaultAreas().count(), 1); + Area *area = new Area(&controller, QStringLiteral("MyArea")); + controller.addDefaultArea(area); + QCOMPARE(controller.defaultAreas().count(), 1); View* view2 = doc->createView(); view2->setObjectName(QStringLiteral("VIEW2")); area->addView(view2); View* view3 = doc->createView(); view3->setObjectName(QStringLiteral("VIEW3")); area->addView(view3); QCOMPARE(doc->views().count(), 3); QCOMPARE(area->views().count(), 2); delete area; view2 = nullptr; view3= nullptr; QEXPECT_FAIL("", "Fails because of delayed view deletion", Continue); QCOMPARE(doc->views().count(), 1); - QCOMPARE(controller->defaultAreas().count(), 0); + QCOMPARE(controller.defaultAreas().count(), 0); QTest::qWait(100); // wait for deleteLaters qDebug() << "Deleting doc"; delete doc; QTest::qWait(100); // wait for deleteLaters qDebug() << "View2 & view3 are destructored at this point (but no earlier)."; } void TestController::namedAreas() { Controller controller; Area *area1 = new Area(&controller, QStringLiteral("1")); controller.addDefaultArea(area1); Area *area2 = new Area(&controller, QStringLiteral("2")); controller.addDefaultArea(area2); QCOMPARE(controller.defaultArea(QStringLiteral("1")), area1); QCOMPARE(controller.defaultArea(QStringLiteral("2")), area2); } QTEST_MAIN(TestController) diff --git a/kdevplatform/sublime/tests/test_toolviewtoolbar.cpp b/kdevplatform/sublime/tests/test_toolviewtoolbar.cpp index 3edc91cc87..3be4e7c6f6 100644 --- a/kdevplatform/sublime/tests/test_toolviewtoolbar.cpp +++ b/kdevplatform/sublime/tests/test_toolviewtoolbar.cpp @@ -1,131 +1,144 @@ /*************************************************************************** * This file is part of KDevelop * * Copyright 2008 Andreas Pakulat * * Copyright 2008 Manuel Breugelmans * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "test_toolviewtoolbar.h" #include #include #include #include #include #include #include #include using namespace Sublime; class ToolViewToolBarFactory : public SimpleToolWidgetFactory { public: explicit ToolViewToolBarFactory(const QString &id): SimpleToolWidgetFactory(id) {} QList toolBarActions( QWidget* ) const override { - QAction* action = new QAction(actionText, nullptr); - return QList() << action; + return actionList; } - QString actionText; + + ~ToolViewToolBarFactory() override + { + qDeleteAll(actionList); + } + + void addAction(const QString &text) + { + QAction* action = new QAction(text, nullptr); + actionList.append(action); + } + +private: + QList actionList; }; void TestToolViewToolBar::init() { // this is starting to become a GeneralFixture controller = new Controller(this); area = new Area( controller, QStringLiteral("Area") ); MainWindow* mw = new MainWindow(controller); // a horizontal tool with toolbar ToolViewToolBarFactory* factoryT1 = new ToolViewToolBarFactory(QStringLiteral("tool1factory")); actionTextT1 = QStringLiteral("Tool1Action"); - factoryT1->actionText = actionTextT1; + factoryT1->addAction(actionTextT1); tool1 = new ToolDocument( QStringLiteral("tool1"), controller, factoryT1 ); viewT11 = tool1->createView(); area->addToolView( viewT11, Sublime::Bottom ); // a vertical tool with toolbar ToolViewToolBarFactory* factoryT2 = new ToolViewToolBarFactory(QStringLiteral("tool2factory")); actionTextT2 = QStringLiteral("Tool2Action"); - factoryT2->actionText = actionTextT2; + factoryT2->addAction(actionTextT2); tool2 = new ToolDocument( QStringLiteral("tool2"), controller, factoryT2 ); viewT21 = tool2->createView(); area->addToolView( viewT21, Sublime::Left ); controller->showArea(area, mw); } void TestToolViewToolBar::cleanup() { delete controller; } QToolBar* TestToolViewToolBar::fetchToolBarFor(Sublime::View* view) { QWidget* toolWidget = view->widget(); const char* loc = "fetchToolBarFor"; Q_UNUSED(loc); Q_ASSERT_X(toolWidget, loc, "Tool refuses to create widget (null)."); Q_ASSERT(toolWidget->parent()); QMainWindow* toolWin = dynamic_cast(toolWidget->parent()); Q_ASSERT_X(toolWin, loc, "Tool widget's parent is not a QMainWindow."); QList toolBars = toolWin->findChildren(); int barCount = toolBars.count(); char* failMsg = qstrdup(QStringLiteral("Expected to find a toolbar but found %1").arg(barCount).toLatin1().data()); Q_UNUSED(failMsg); Q_ASSERT_X(barCount == 1, loc, failMsg); + delete [] failMsg; return toolBars.at(0); } void TestToolViewToolBar::assertGoodBar(QToolBar* toolbar, const QString& actionText) { QVERIFY( toolbar ); QVERIFY( !toolbar->isFloatable() ); QCOMPARE( toolbar->iconSize(), QSize( 16, 16 ) ); QList actions = toolbar->actions(); QCOMPARE( actions.count(), 1 ); QCOMPARE( actions.at(0)->text(), actionText); QCOMPARE( toolbar->orientation(), Qt::Horizontal ); } void TestToolViewToolBar::horizontalTool() { // viewT11 was added with Sublime::Bottom, so it should have a horizontal bar QToolBar* bar = fetchToolBarFor(viewT11); assertGoodBar(bar, actionTextT1); } void TestToolViewToolBar::verticalTool() { // viewT21 was added with Sublime::Left, so it should have a vertical bar QToolBar* bar = fetchToolBarFor(viewT21); assertGoodBar(bar, actionTextT2); } void TestToolViewToolBar::toolViewMove() { area->moveToolView( viewT11, Sublime::Right ); area->moveToolView( viewT21, Sublime::Bottom ); QToolBar* barT1 = fetchToolBarFor(viewT11); QToolBar* barT2 = fetchToolBarFor(viewT21); assertGoodBar(barT1, actionTextT1); assertGoodBar(barT2, actionTextT2); } QTEST_MAIN(TestToolViewToolBar) diff --git a/kdevplatform/sublime/tests/test_viewactivation.cpp b/kdevplatform/sublime/tests/test_viewactivation.cpp index 018a3c01de..f7c5c86c39 100644 --- a/kdevplatform/sublime/tests/test_viewactivation.cpp +++ b/kdevplatform/sublime/tests/test_viewactivation.cpp @@ -1,228 +1,229 @@ /*************************************************************************** * Copyright 2007 Alexander Dymo * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "test_viewactivation.h" #include #include #include #include #include #include #include #include #include #include #include #include using namespace Sublime; template class SpecialWidgetFactory: public SimpleToolWidgetFactory { public: explicit SpecialWidgetFactory(const QString &id): SimpleToolWidgetFactory(id) {} QWidget* create(ToolDocument *doc, QWidget *parent = nullptr) override { QWidget *w = new QWidget(parent); Widget *inner = new Widget(w); inner->setObjectName(doc->title()+"_inner"); w->setObjectName(doc->title()+"_outer"); return w; } }; void TestViewActivation::initTestCase() { qRegisterMetaType("View*"); } void TestViewActivation::init() { controller = new Controller(this); doc1 = new ToolDocument(QStringLiteral("doc1"), controller, new SimpleToolWidgetFactory(QStringLiteral("doc1"))); //this document will create special widgets - QListView nested in QWidget doc2 = new ToolDocument(QStringLiteral("doc2"), controller, new SpecialWidgetFactory(QStringLiteral("doc2"))); doc3 = new ToolDocument(QStringLiteral("doc3"), controller, new SimpleToolWidgetFactory(QStringLiteral("doc3"))); doc4 = new ToolDocument(QStringLiteral("doc4"), controller, new SimpleToolWidgetFactory(QStringLiteral("doc4"))); tool1 = new ToolDocument(QStringLiteral("tool1"), controller, new SimpleToolWidgetFactory(QStringLiteral("tool1"))); tool2 = new ToolDocument(QStringLiteral("tool2"), controller, new SimpleToolWidgetFactory(QStringLiteral("tool2"))); tool3 = new ToolDocument(QStringLiteral("tool3"), controller, new SimpleToolWidgetFactory(QStringLiteral("tool3"))); area = new Area(controller, QStringLiteral("Area")); view211 = doc1->createView(); view211->setObjectName(QStringLiteral("view211")); area->addView(view211); view212 = doc1->createView(); view212->setObjectName(QStringLiteral("view212")); area->addView(view212); view221 = doc2->createView(); area->addView(view221, view211, Qt::Vertical); view231 = doc3->createView(); area->addView(view231, view221, Qt::Horizontal); view241 = doc4->createView(); area->addView(view241, view212, Qt::Vertical); viewT11 = tool1->createView(); area->addToolView(viewT11, Sublime::Bottom); viewT21 = tool2->createView(); area->addToolView(viewT21, Sublime::Right); viewT31 = tool3->createView(); area->addToolView(viewT31, Sublime::Top); viewT32 = tool3->createView(); area->addToolView(viewT32, Sublime::Top); } void TestViewActivation::cleanup() { delete controller; } void TestViewActivation::signalsOnViewCreationAndDeletion() { Controller *controller = new Controller(this); ToolDocument *doc1 = new ToolDocument(QStringLiteral("doc1"), controller, new SimpleToolWidgetFactory(QStringLiteral("doc1"))); Area *area = new Area(controller, QStringLiteral("Area")); QSignalSpy spy(controller, SIGNAL(viewAdded(Sublime::View*))); View *v = doc1->createView(); area->addView(v); QCOMPARE(spy.count(), 1); QSignalSpy spy2(controller, SIGNAL(aboutToRemoveView(Sublime::View*))); area->removeView(v); QCOMPARE(spy2.count(), 1); QSignalSpy spy3(controller, SIGNAL(toolViewAdded(Sublime::View*))); v = doc1->createView(); area->addToolView(v, Sublime::Bottom); QCOMPARE(spy3.count(), 1); QSignalSpy spy4(controller, SIGNAL(aboutToRemoveToolView(Sublime::View*))); area->removeToolView(v); QCOMPARE(spy4.count(), 1); delete controller; } void TestViewActivation::viewActivation() { MainWindow* mw = new MainWindow(controller); controller->addDefaultArea(area); // Q_ASSERT without this. controller->addMainWindow(mw); controller->showArea(area, mw); //we should have an active view immediatelly after the area is shown QCOMPARE(mw->activeView(), view211); //add some widgets that are not in layout QTextEdit *breaker = new QTextEdit(mw); breaker->setObjectName(QStringLiteral("breaker")); QTextEdit *toolBreaker = new QTextEdit(mw); toolBreaker->setObjectName(QStringLiteral("toolBreaker")); QDockWidget *dock = new QDockWidget(mw); dock->setWidget(toolBreaker); mw->addDockWidget(Qt::LeftDockWidgetArea, dock); + QFocusEvent focusEvent(QEvent::FocusIn); //now post events to the widgets and see if mainwindow has the right active views //activate view - qApp->sendEvent(view212->widget(), new QFocusEvent(QEvent::FocusIn)); + qApp->sendEvent(view212->widget(), &focusEvent); QString failMsg = QStringLiteral("\nWas expecting %1 to be active but got %2"). arg(view212->objectName(), mw->activeView()->objectName()); QVERIFY2(mw->activeView() == view212, failMsg.toLatin1().data()); //activate tool view and check that both view and tool view are active - qApp->sendEvent(viewT31->widget(), new QFocusEvent(QEvent::FocusIn)); + qApp->sendEvent(viewT31->widget(), &focusEvent); QCOMPARE(mw->activeView(), view212); QCOMPARE(mw->activeToolView(), viewT31); //active another view - qApp->sendEvent(view241->widget(), new QFocusEvent(QEvent::FocusIn)); + qApp->sendEvent(view241->widget(), &focusEvent); QCOMPARE(mw->activeView(), view241); QCOMPARE(mw->activeToolView(), viewT31); //focus a widget not in the area - qApp->sendEvent(breaker, new QFocusEvent(QEvent::FocusIn)); + qApp->sendEvent(breaker, &focusEvent); QCOMPARE(mw->activeView(), view241); QCOMPARE(mw->activeToolView(), viewT31); //focus a dock not in the area - qApp->sendEvent(toolBreaker, new QFocusEvent(QEvent::FocusIn)); + qApp->sendEvent(toolBreaker, &focusEvent); QCOMPARE(mw->activeView(), view241); QCOMPARE(mw->activeToolView(), viewT31); //focus inner widget for view221 QListView *inner = mw->findChild(QStringLiteral("doc2_inner")); QVERIFY(inner); - qApp->sendEvent(inner, new QFocusEvent(QEvent::FocusIn)); + qApp->sendEvent(inner, &focusEvent); QCOMPARE(mw->activeView(), view221); QCOMPARE(mw->activeToolView(), viewT31); } void TestViewActivation::activationInMultipleMainWindows() { MainWindow mw(controller); controller->showArea(area, &mw); QCOMPARE(mw.activeView(), view211); //check that new mainwindow always have active view right after displaying area MainWindow mw2(controller); controller->showArea(area, &mw2); QVERIFY(mw2.activeView()); QCOMPARE(mw2.activeView()->document(), doc1); } void TestViewActivation::activationAfterViewRemoval() { MainWindow mw(controller); controller->showArea(area, &mw); QCOMPARE(mw.activeView(), view211); //check what happens if we remove a view which is not the only one in container delete area->removeView(view211); QCOMPARE(mw.activeView(), view212); //check what happens if we remove a view which is alone in container mw.activateView(view231); QCOMPARE(mw.activeView(), view231); delete area->removeView(view231); QCOMPARE(mw.activeView(), view221); } void TestViewActivation::activationAfterRemovalSimplestCase() { //we don't have split views - just two views in one area index MainWindow mw(controller); Area *area = new Area(controller, QStringLiteral("Area")); View *v1 = doc1->createView(); View *v2 = doc2->createView(); area->addView(v1); area->addView(v2, v1); controller->showArea(area, &mw); mw.activateView(v2); //delete active view and check that previous is activated delete area->removeView(v2); QCOMPARE(mw.activeView(), v1); } QTEST_MAIN(TestViewActivation)