2 * This file is part of KDevelop
3 * Copyright 2008 Manuel Breugelmans <mbr.nxi@gmail.com>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 #include "itestrunner.h"
23 #include "itestframework.h"
24 #include "internal/toolviewdata.h"
26 #include "internal/selectionstore.h"
27 #include "ui_runnerwindow.h"
29 #include "internal/runnermodel.h"
30 #include "internal/resultsmodel.h"
31 #include "internal/runnerwindow.h"
36 #include <KSelectAction>
37 #include <QDockWidget>
41 #include "interfaces/icore.h"
42 #include "interfaces/iproject.h"
43 #include "interfaces/iprojectcontroller.h"
44 #include "interfaces/iuicontroller.h"
45 #include "sublime/area.h"
46 #include "sublime/controller.h"
47 #include "sublime/mainwindow.h"
48 #include "sublime/tooldocument.h"
49 #include "sublime/view.h"
51 Q_DECLARE_METATYPE(KDevelop::IProject
*)
54 using Sublime::Document
;
55 using Sublime::ToolDocument
;
58 using KDevelop::ICore
;
59 using KDevelop::IProject
;
60 using KDevelop::IProjectController
;
61 using KDevelop::IToolViewFactory
;
62 using KDevelop::IUiController
;
65 using Veritas::RunnerModel
;
66 using Veritas::RunnerWindow
;
67 using Veritas::ResultsModel
;
68 using Veritas::ITestRunner
;
69 using Veritas::ITestFramework
;
71 class ITestRunner::Private
87 IProject
* selectedProject
;
88 Sublime::View
*resultsView
;
89 Sublime::Area
*resultsArea
;
90 ResultsModel
*resultsModel
;
92 ITestFramework
* framework
;
95 QString
resultsViewId() const {
96 Q_ASSERT(g_toolViewStore
.contains(framework
));
97 ToolViewData
& tvd
= g_toolViewStore
[framework
];
98 int id
= tvd
.runner2id
[self
];
99 return QString("org.kdevelop.%1ResultsView%2").arg(framework
->name()).arg(id
);
104 ITestRunner::ITestRunner(ITestFramework
* framework
)
105 : QObject(0), d(new ITestRunner::Private
)
108 d
->framework
= framework
;
109 Q_ASSERT(g_toolViewStore
.contains(framework
));
110 ToolViewData
& tvd
= g_toolViewStore
[framework
];
111 tvd
.runner2id
[this] = tvd
.runnerToolCounter
;
112 tvd
.runnerToolCounter
++;
114 QStringList resultHeaders
;
115 resultHeaders
<< i18n("Test") << i18n("Message")
116 << i18n("File") << i18n("Line");
117 d
->resultsModel
= new ResultsModel(resultHeaders
, this);
118 d
->window
= new RunnerWindow(d
->resultsModel
);
120 connect(this, SIGNAL(registerFinished(Veritas::Test
*)),
121 this, SLOT(setupToolView(Veritas::Test
*)));
124 void ITestRunner::setupToolView(Veritas::Test
* root
)
126 if (!root
) { kDebug() << "root null"; return; }
127 if (d
->previousRoot
) {
129 ss
.saveTree(d
->previousRoot
);
130 ss
.restoreTree(root
);
132 d
->previousRoot
= root
;
133 RunnerModel
* model
= new RunnerModel
;
134 model
->setRootItem(root
);
135 model
->setExpectedResults(Veritas::RunError
);
136 d
->window
->setModel(model
);
137 d
->window
->runnerView()->setRootIsDecorated(false);
138 d
->window
->resetProgressBar();
139 if (!d
->resultsView
) spawnResultsView();
142 ITestRunner::~ITestRunner()
147 QWidget
* ITestRunner::resultsWidget()
149 return d
->window
->resultsWidget();
152 void ITestRunner::removeResultsView()
154 if (d
->resultsView
&& d
->resultsArea
) {
155 d
->resultsArea
->removeToolView(d
->resultsView
);
159 QWidget
* ITestRunner::runnerWidget()
161 IProjectController
* ipc
= ICore::self()->projectController();
162 foreach(IProject
* proj
, ipc
->projects()) {
163 d
->window
->addProjectToPopup(proj
);
165 connect(ipc
, SIGNAL(projectOpened(KDevelop::IProject
*)),
166 d
->window
, SLOT(addProjectToPopup(KDevelop::IProject
*)));
167 connect(ipc
, SIGNAL(projectClosed(KDevelop::IProject
*)),
168 d
->window
, SLOT(rmProjectFromPopup(KDevelop::IProject
*)));
170 connect(d
->window
->projectPopup(), SIGNAL(triggered(QAction
*)),
171 this, SLOT(setSelected(QAction
*)));
173 connect(d
->window
->ui()->actionReload
, SIGNAL(triggered(bool)),
174 this, SLOT(reload()));
176 connect(d
->window
, SIGNAL(openVerbose(Veritas::Test
*)),
177 this, SLOT(openVerbose(Veritas::Test
*)));
183 /*! TODO rename this a bit. just make reload() pure virtual instead of registerTests */
184 void ITestRunner::reload()
186 registerTests(); // implemented by concrete plugins
189 IProject
* ITestRunner::project() const
191 return d
->selectedProject
;
194 void ITestRunner::setSelected(QAction
* action
)
196 kDebug() << action
->data().value
<IProject
*>();
197 d
->selectedProject
= action
->data().value
<IProject
*>();
201 class Filter
: public QObject
204 Filter(QObject
* parent
) : QObject(parent
), m_parent(parent
) {}
206 bool eventFilter(QObject
* obj
, QEvent
* event
) {
207 if (event
->type() == QEvent::ContextMenu
) return true;
208 if (m_parent
) return m_parent
->eventFilter(obj
, event
);
214 class ResultsViewFactory
: public KDevelop::IToolViewFactory
217 ResultsViewFactory(const QString
& id
, ITestRunner
*runner
): m_runner(runner
), m_id(id
) {}
219 virtual QWidget
* create(QWidget
*parent
= 0) {
221 return m_runner
->resultsWidget();
222 // TODO this is bad. Currently only a single
223 // resultsWidget is ever created, which means
224 // that multiple resultsviews for a particular
225 // runnertoolview will segfault kdevelop.
226 // Introducing multiple resultViews requires
227 // changes in RunnerWindow. Luckily a user
228 // cannot close nor create multiple ones, so
229 // the situation above is impossible.
231 virtual Qt::DockWidgetArea
defaultPosition() {
232 return Qt::BottomDockWidgetArea
;
234 virtual QString
id() const {
237 virtual void viewCreated(Sublime::View
* view
) {
238 QWidget
* w
= view
->widget();
240 QObject
* p
= w
->parent();
242 QDockWidget
* d
= qobject_cast
<QDockWidget
*>(p
);
244 d
->setFeatures(d
->features() & 0xfffc);
245 Filter
* f
= new Filter(d
);
246 d
->installEventFilter(f
);
250 ITestRunner
*m_runner
;
256 class UiToolViewFactory
: public Sublime::ToolFactory
259 UiToolViewFactory(IToolViewFactory
*factory
): m_factory(factory
) {}
260 ~UiToolViewFactory() { delete m_factory
; }
261 virtual QWidget
* create(Sublime::ToolDocument
*doc
, QWidget
*parent
= 0) {
263 return m_factory
->create(parent
);
265 QList
<QAction
*> toolBarActions(QWidget
* viewWidget
) const {
266 Q_UNUSED(viewWidget
);
267 //return m_factory->toolBarActions(viewWidget);
268 return QList
<QAction
*>();
270 QString
id() const { return m_factory
->id(); }
273 IToolViewFactory
*m_factory
;
277 class ResultsViewFinder
280 ResultsViewFinder(const QString
& id
) : m_id(id
), found(false) {}
281 Area::WalkerMode
operator()(View
*view
, Sublime::Position position
) {
283 Document
* doc
= view
->document();
284 if (m_id
== doc
->documentSpecifier()) {
286 return Area::StopWalker
;
288 return Area::ContinueWalker
;
295 void ITestRunner::spawnResultsView()
297 // only allow a single view.
298 IUiController
* uic
= ICore::self()->uiController();
299 Sublime::Controller
* ctr
= uic
->controller();
300 foreach(Area
* a
, ctr
->allAreas()) {
301 ResultsViewFinder
rvf(d
->resultsViewId());
302 a
->walkToolViews(rvf
, Sublime::AllPositions
);
304 kDebug() << "Not adding twice, found a resultsview for this runner.";
309 // these tool views should not show up in the 'Add Tool View' dialog.
310 // either use the ugly code below or fix this in UiController.
311 //uic->addToolView("Test Results", new ResultsViewFactory(resultsViewId(), this));
313 // this is bad. might want to make this available in IUiController
314 ResultsViewFactory
* fac
= new ResultsViewFactory(d
->resultsViewId(), this);
315 QList
<Sublime::MainWindow
*> mws
= ctr
->mainWindows();
316 if (mws
.isEmpty() || !mws
[0]) {
317 kDebug() << "No mainwindow not adding results view.";
321 Sublime::MainWindow
* mw
= mws
[0]; // just take the first one.
322 d
->resultsArea
= mw
->area();
323 ToolDocument
*doc
= new ToolDocument(QString("Test Results"), ctr
, new UiToolViewFactory(fac
));
324 d
->resultsView
= doc
->createView();
325 Sublime::Position pos
= Sublime::dockAreaToPosition(fac
->defaultPosition());
326 d
->resultsArea
->addToolView(d
->resultsView
, pos
);
327 connect(d
->resultsView
, SIGNAL(raise(Sublime::View
*)),
328 ctr
, SLOT(raiseToolView(Sublime::View
*)));
329 fac
->viewCreated(d
->resultsView
);
332 #include "itestrunner.moc"