[Ktutorial-commits] SF.net SVN: ktutorial:[238] trunk/ktutorial/ktutorial-library
Status: Alpha
Brought to you by:
danxuliu
From: <dan...@us...> - 2010-05-11 03:39:01
|
Revision: 238 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=238&view=rev Author: danxuliu Date: 2010-05-11 03:38:55 +0000 (Tue, 11 May 2010) Log Message: ----------- Add StepTextWidget to show the text of a step. HTML links in the text with the format "widget:nameOfTheWidget" can be used to highlight the referenced widget when a tutorial is being executed. Modified Paths: -------------- trunk/ktutorial/ktutorial-library/src/view/CMakeLists.txt trunk/ktutorial/ktutorial-library/src/view/StepWidget.cpp trunk/ktutorial/ktutorial-library/src/view/StepWidget.ui trunk/ktutorial/ktutorial-library/tests/view/CMakeLists.txt trunk/ktutorial/ktutorial-library/tests/view/StepWidgetTest.cpp Added Paths: ----------- trunk/ktutorial/ktutorial-library/src/view/StepTextWidget.cpp trunk/ktutorial/ktutorial-library/src/view/StepTextWidget.h trunk/ktutorial/ktutorial-library/tests/view/StepTextWidgetTest.cpp Modified: trunk/ktutorial/ktutorial-library/src/view/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-library/src/view/CMakeLists.txt 2010-04-26 05:30:40 UTC (rev 237) +++ trunk/ktutorial/ktutorial-library/src/view/CMakeLists.txt 2010-05-11 03:38:55 UTC (rev 238) @@ -1,6 +1,7 @@ -include_directories(${CMAKE_CURRENT_BINARY_DIR} ${KDE4_INCLUDES}) +include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${KDE4_INCLUDES}) set(ktutorial_view_SRCS + StepTextWidget.cpp StepWidget.cpp TutorialListModel.cpp TutorialManagerDialog.cpp @@ -13,4 +14,4 @@ kde4_add_library(ktutorial_view ${ktutorial_view_SRCS}) -target_link_libraries(ktutorial_view ${KDE4_KDEUI_LIBS}) +target_link_libraries(ktutorial_view ktutorial_extendedinformation ${KDE4_KDEUI_LIBS}) Added: trunk/ktutorial/ktutorial-library/src/view/StepTextWidget.cpp =================================================================== --- trunk/ktutorial/ktutorial-library/src/view/StepTextWidget.cpp (rev 0) +++ trunk/ktutorial/ktutorial-library/src/view/StepTextWidget.cpp 2010-05-11 03:38:55 UTC (rev 238) @@ -0,0 +1,208 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 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 General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include <QContextMenuEvent> +#include <QMenu> + +#include <KDebug> +#include <KLocalizedString> + +#include "StepTextWidget.h" +#include "../KTutorial.h" +#include "../extendedinformation/WidgetHighlighterManager.h" + +using extendedinformation::WidgetHighlighterManager; + +namespace view { + +//public: + +StepTextWidget::StepTextWidget(QWidget* parent /*= 0*/): + KTextEdit(parent), + mCurrentHighlightedWidget(0) { + setReadOnly(true); + setFrameShape(QFrame::NoFrame); + setFrameShadow(QFrame::Plain); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + viewport()->setCursor(Qt::ArrowCursor); + + QPalette palette = this->palette(); + palette.setColor(QPalette::Base, Qt::transparent); + setPalette(palette); + + setAlignment(Qt::AlignJustify | Qt::AlignVCenter); + + //Set a explicit text width to avoid some strange behavior: if the text + //width is set to QWIDGETSIZE_MAX without a previous text width set, the + //size returned by the document has weird values. Anyway, sizeHint is + //usually called before minimumSizeHint, so a text width will be already set + //when minimumSizeHint is called, but just in case. + document()->setTextWidth(0); + + connect(this, SIGNAL(textChanged()), this, SLOT(updateText())); +} + +bool StepTextWidget::eventFilter(QObject* watched, QEvent* event) { + if (watched != mCurrentHighlightedWidget) { + return false; + } + + if (event->type() != QEvent::FocusIn) { + return false; + } + + stopHighlightingCurrentWidget(); + + return false; +} + +int StepTextWidget::heightForWidth(int width) const { + return sizeForWidth(width).height(); +} + +QSize StepTextWidget::minimumSizeHint() const { + QSize size; + size.setHeight(sizeForWidth(QWIDGETSIZE_MAX).height()); + size.setWidth(sizeForWidth(0).width()); + + return size; +} + +QSize StepTextWidget::sizeHint() const { + return sizeForWidth(-1); +} + +//protected: + +void StepTextWidget::contextMenuEvent(QContextMenuEvent* event) { + QString anchor = anchorAt(event->pos()); + if (!anchor.startsWith(QLatin1String("widget:"))) { + KTextEdit::contextMenuEvent(event); + return; + } + + QMenu* menu = new QMenu(this); + + if (mCurrentHighlightedWidget && + mCurrentHighlightedWidget != widgetForAnchor(anchor)) { + stopHighlightingCurrentWidget(); + } + + if (!mCurrentHighlightedWidget) { + menu->addAction(i18nc("@item:inmenu", "Highlight"), + this, SLOT(highlightCurrentWidget())); + + mCurrentHighlightedWidget = widgetForAnchor(anchor); + } else { + menu->addAction(i18nc("@item:inmenu", "Stop highlighting"), + this, SLOT(stopHighlightingCurrentWidget())); + } + + menu->exec(event->globalPos()); + delete menu; +} + +void StepTextWidget::mouseMoveEvent(QMouseEvent* event) { + KTextEdit::mouseMoveEvent(event); + + if (anchorAt(event->pos()).startsWith(QLatin1String("widget:"))) { + viewport()->setCursor(Qt::PointingHandCursor); + } else { + viewport()->setCursor(Qt::ArrowCursor); + } +} + +void StepTextWidget::mousePressEvent(QMouseEvent* event) { + QString anchor = anchorAt(event->pos()); + if (event->button() != Qt::LeftButton || + !anchor.startsWith(QLatin1String("widget:"))) { + KTextEdit::mousePressEvent(event); + return; + } + + if (mCurrentHighlightedWidget && + mCurrentHighlightedWidget != widgetForAnchor(anchor)) { + stopHighlightingCurrentWidget(); + } + + if (!mCurrentHighlightedWidget) { + mCurrentHighlightedWidget = widgetForAnchor(anchor); + + highlightCurrentWidget(); + } else { + stopHighlightingCurrentWidget(); + } +} + +//private: + +QSize StepTextWidget::sizeForWidth(int width) const { + const qreal oldTextWidth = document()->textWidth(); + + if (width >= 0) { + document()->setTextWidth(width); + } else { + document()->adjustSize(); + } + + QSize size = document()->size().toSize(); + + document()->setTextWidth(oldTextWidth); + + return size; +} + +QWidget* StepTextWidget::widgetForAnchor(const QString& anchor) { + QString widgetName = anchor.mid(QString("widget:").length()); + return KTutorial::self()->findObject<QWidget*>(widgetName); +} + +//private slots: + +void StepTextWidget::updateText() { + updateGeometry(); + + if (mCurrentHighlightedWidget) { + stopHighlightingCurrentWidget(); + } +} + +void StepTextWidget::highlightCurrentWidget() { + if (!mCurrentHighlightedWidget) { + kWarning() << "The widget to highlight was not found!"; + } + + WidgetHighlighterManager::self()->highlight(mCurrentHighlightedWidget); + + mCurrentHighlightedWidget->installEventFilter(this); +} + +void StepTextWidget::stopHighlightingCurrentWidget() { + if (!mCurrentHighlightedWidget) { + kWarning() << "The widget to stop highlighting was not found!"; + } + + WidgetHighlighterManager::self()->stopHighlighting(mCurrentHighlightedWidget); + + mCurrentHighlightedWidget->removeEventFilter(this); + mCurrentHighlightedWidget = 0; +} + +} Property changes on: trunk/ktutorial/ktutorial-library/src/view/StepTextWidget.cpp ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-library/src/view/StepTextWidget.h =================================================================== --- trunk/ktutorial/ktutorial-library/src/view/StepTextWidget.h (rev 0) +++ trunk/ktutorial/ktutorial-library/src/view/StepTextWidget.h 2010-05-11 03:38:55 UTC (rev 238) @@ -0,0 +1,181 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 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 General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifndef VIEW_STEPTEXTWIDGET_H +#define VIEW_STEPTEXTWIDGET_H + +#include <KTextEdit> + +namespace view { + +/** + * A TextEdit with the appearance of a label to show the text of a step. + * It behaves like a QLabel with custom behavior for links. However, as QLabel + * doesn't provide a way to easily extend its link related behavior, a KTextEdit + * with a QLabel appearance (read only, size fit to text, no scroll bars...) is + * used instead. + * + * Links that exhibit a custom behavior are those with the format + * "widget:nameOfTheWidget". When the link is pressed with the left mouse + * button, the widget with the specified name is highlighted. When it is pressed + * again, the highlighting is stopped. If the right button is pressed, a context + * menu with an item to highlight or stop highlighting is shown. + * + * If a widget was being highlighted when the highglighting is started in + * another widget, the highlighting in the previous widget is stopped. The + * highlighting is also stopped when the widget gets the focus, or when the text + * is changed in the StepTextWidget. + * + * When the mouse cursor is moved over a "widget:" link, the arrow cursor is + * changed to a pointing hand cursor. + * + * The links are specified using HTML markup, for example, + * <a href="widget:theNameOfTheWidget">the text of the link</a> + */ +class StepTextWidget: public KTextEdit { +Q_OBJECT +public: + + /** + * Creates a new StepTextWidget. + * + * @param parent The parent widget. + */ + explicit StepTextWidget(QWidget* parent = 0); + + /** + * Watches the widget currently being highlighted and stops the highlighting + * when it is focused. + * + * @param watched The filtered object that received an event. + * @param event The event received. + * @return False, to allow the event to be handled further. + */ + virtual bool eventFilter(QObject* watched, QEvent* event); + + /** + * Returns the height of the size for the given width. + * + * @param width The width to get its height. + * @return The height for the width. + */ + virtual int heightForWidth(int width) const; + + /** + * Returns the recommended minimum size for this StepTextWidget. + * The size has the width of the longest word in the text and the height of + * a single line. + * + * @return The recommended minimum size. + */ + virtual QSize minimumSizeHint() const; + + /** + * Returns the recommended size for this StepTextWidget. + * The size is adjusted to fit the text as a rectangle, with a width bigger + * then the height. + * + * @return The recommended size. + */ + virtual QSize sizeHint() const; + +protected: + + /** + * Shows a custom context menu when a context menu is requested on a + * "widget:" anchor. + * The context menu will contain a "Stop highlighting" or a "Highlight" item + * depending on whether the widget is the one currently being highlighted or + * not. If the widget currently being highlighted is another one, it is + * stopped. + * + * @param event The context menu event. + */ + virtual void contextMenuEvent(QContextMenuEvent* event); + + /** + * Changes the cursor to a pointing hand when it is over a "widget:" anchor. + * + * @param event The mouse move event. + */ + virtual void mouseMoveEvent(QMouseEvent* event); + + /** + * When the mouse is pressed on a "widget:" anchor, it is highlighted or + * stopped being highlighted. + * If the widget currently being highlighted is another one, it is stopped. + * + * @param event The mouse press event. + */ + virtual void mousePressEvent(QMouseEvent* event); + +private: + + /** + * The widget currently being highlighted as a result of activating a link + * in this StepTextWidget. + */ + QWidget* mCurrentHighlightedWidget; + + /** + * Returns the size for the given text width. + * If the width is < 0, the size is adjusted to the text as a rectangle, + * with a width bigger than the height. + * If the width is >= 0, the size is the given width and a height bigger + * enough to show the whole text. The width may be bigger than the given one + * if the given one is not big enough to show the longest word in the text. + * + * @param width The width to get its size. + * @return The size for the width. + */ + QSize sizeForWidth(int width) const; + + /** + * Returns the widget referenced in the given anchor. + * The anchor must have a "widget:name" format. The widget is looked for + * using its name in KTutorial::findObject(QString). + * + * @param anchor The anchor to get its widget. + * @return The widget referenced in the anchor. + */ + QWidget* widgetForAnchor(const QString& anchor); + +private Q_SLOTS: + + /** + * Notifies the layout that the geometry of the widget has changed and stops + * the highlighting of the current widget, if any. + */ + void updateText(); + + /** + * Starts highlighting the current widget. + */ + void highlightCurrentWidget(); + + /** + * Stops highlighting the current widget. + * The current widget is cleared. + */ + void stopHighlightingCurrentWidget(); + +}; + +}; + +#endif Property changes on: trunk/ktutorial/ktutorial-library/src/view/StepTextWidget.h ___________________________________________________________________ Added: svn:eol-style + native Modified: trunk/ktutorial/ktutorial-library/src/view/StepWidget.cpp =================================================================== --- trunk/ktutorial/ktutorial-library/src/view/StepWidget.cpp 2010-04-26 05:30:40 UTC (rev 237) +++ trunk/ktutorial/ktutorial-library/src/view/StepWidget.cpp 2010-05-11 03:38:55 UTC (rev 238) @@ -65,7 +65,7 @@ //public slots: void StepWidget::setStep(Step* step) { - ui->textLabel->setText(step->text()); + ui->textWidget->setText(step->text()); setOptions(step->options()); adjustSize(); Modified: trunk/ktutorial/ktutorial-library/src/view/StepWidget.ui =================================================================== --- trunk/ktutorial/ktutorial-library/src/view/StepWidget.ui 2010-04-26 05:30:40 UTC (rev 237) +++ trunk/ktutorial/ktutorial-library/src/view/StepWidget.ui 2010-05-11 03:38:55 UTC (rev 238) @@ -1,7 +1,8 @@ -<ui version="4.0" > +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> <class>StepWidget</class> - <widget class="QWidget" name="StepWidget" > - <property name="geometry" > + <widget class="QWidget" name="StepWidget"> + <property name="geometry"> <rect> <x>0</x> <y>0</y> @@ -9,39 +10,30 @@ <height>306</height> </rect> </property> - <layout class="QVBoxLayout" > - <property name="spacing" > + <layout class="QVBoxLayout"> + <property name="spacing"> <number>0</number> </property> - <property name="leftMargin" > + <property name="margin"> <number>4</number> </property> - <property name="topMargin" > - <number>4</number> - </property> - <property name="rightMargin" > - <number>4</number> - </property> - <property name="bottomMargin" > - <number>4</number> - </property> <item> - <layout class="QHBoxLayout" > - <property name="spacing" > + <layout class="QHBoxLayout"> + <property name="spacing"> <number>0</number> </property> - <property name="leftMargin" > + <property name="leftMargin"> <number>0</number> </property> - <property name="topMargin" > + <property name="topMargin"> <number>0</number> </property> <item> <spacer> - <property name="orientation" > + <property name="orientation"> <enum>Qt::Horizontal</enum> </property> - <property name="sizeHint" > + <property name="sizeHint" stdset="0"> <size> <width>40</width> <height>20</height> @@ -50,17 +42,17 @@ </spacer> </item> <item> - <widget class="KPushButton" name="closeButton" > - <property name="focusPolicy" > + <widget class="KPushButton" name="closeButton"> + <property name="focusPolicy"> <enum>Qt::NoFocus</enum> </property> - <property name="toolTip" > - <string comment="@info:tooltip" >Close this tutorial</string> + <property name="toolTip"> + <string comment="@info:tooltip">Close this tutorial</string> </property> - <property name="whatsThis" > - <string comment="@info:whatsthis" >Click here to close the tutorial.<nl/>The tutorial can be closed when you have finished it, or at any time to cancel it.</string> + <property name="whatsThis"> + <string comment="@info:whatsthis">Click here to close the tutorial.<nl/>The tutorial can be closed when you have finished it, or at any time to cancel it.</string> </property> - <property name="flat" > + <property name="flat"> <bool>true</bool> </property> </widget> @@ -68,32 +60,23 @@ </layout> </item> <item> - <widget class="QLabel" name="textLabel" > - <property name="sizePolicy" > - <sizepolicy vsizetype="MinimumExpanding" hsizetype="MinimumExpanding" > + <widget class="view::StepTextWidget" name="textWidget"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="toolTip" > - <string comment="@info:tooltip" >The instructions for this step</string> + <property name="toolTip"> + <string comment="@info:tooltip">The instructions for this step</string> </property> - <property name="whatsThis" > - <string comment="@info:whatsthis" >Here appear the instructions for each step of the tutorial.<nl/>Once you complete one step, a new step with new instructions will be shown.</string> + <property name="whatsThis"> + <string comment="@info:whatsthis">Here appear the instructions for each step of the tutorial.<nl/>Once you complete one step, a new step with new instructions will be shown.</string> </property> - <property name="text" > - <string/> - </property> - <property name="alignment" > - <set>Qt::AlignJustify|Qt::AlignVCenter</set> - </property> - <property name="wordWrap" > - <bool>true</bool> - </property> </widget> </item> <item> - <widget class="QWidget" native="1" name="optionsWidget" /> + <widget class="QWidget" name="optionsWidget" native="true"/> </item> </layout> </widget> @@ -103,6 +86,11 @@ <extends>QPushButton</extends> <header>kpushbutton.h</header> </customwidget> + <customwidget> + <class>view::StepTextWidget</class> + <extends>QTextEdit</extends> + <header>StepTextWidget.h</header> + </customwidget> </customwidgets> <resources/> <connections/> Modified: trunk/ktutorial/ktutorial-library/tests/view/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-library/tests/view/CMakeLists.txt 2010-04-26 05:30:40 UTC (rev 237) +++ trunk/ktutorial/ktutorial-library/tests/view/CMakeLists.txt 2010-05-11 03:38:55 UTC (rev 238) @@ -17,6 +17,7 @@ ENDMACRO(UNIT_TESTS) unit_tests( + StepTextWidget StepWidget TutorialListModel TutorialManagerDialog @@ -29,6 +30,7 @@ ENDMACRO(MEM_TESTS) mem_tests( + StepTextWidget StepWidget TutorialListModel TutorialManagerDialog Added: trunk/ktutorial/ktutorial-library/tests/view/StepTextWidgetTest.cpp =================================================================== --- trunk/ktutorial/ktutorial-library/tests/view/StepTextWidgetTest.cpp (rev 0) +++ trunk/ktutorial/ktutorial-library/tests/view/StepTextWidgetTest.cpp 2010-05-11 03:38:55 UTC (rev 238) @@ -0,0 +1,365 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 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 General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include <QtTest> +#include <qtest_kde.h> + +#include <KXmlGuiWindow> + +#include "StepTextWidget.h" +#define protected public +#define private public +#include "../KTutorial.h" +#undef private +#undef protected +#include "../extendedinformation/WidgetHighlighter.h" + +using extendedinformation::WidgetHighlighter; + +namespace view { + +class StepTextWidgetTest: public QObject { +Q_OBJECT +public slots: + + void selectFirstContextMenuOption(); + +private slots: + + void init(); + void cleanup(); + + void testConstructor(); + + void testSizeHintWithBiggerText(); + void testSizeHintWithSmallerText(); + + void testHighlightWidgetClickingOnAnchor(); + void testStopHighlightingWidgetClickingOnAnchor(); + void testHighlightWidgetUsingContextMenu(); + void testStopHighlightingWidgetUsingContextMenu(); + void testHighlightSeveralWidgets(); + + void testStopHighlightingWidgetWhenFocused(); + + void testSetTextWhenWidgetIsBeingHighlighted(); + +private: + + QPoint centerOfText(const StepTextWidget& widget, const QString& text); + + void showContextMenuAndSelectFirstOption(const StepTextWidget& widget, + const QPoint& position); + +}; + +void StepTextWidgetTest::init() { + delete KTutorial::sSelf; + KTutorial::sSelf = new KTutorial(); +} + +void StepTextWidgetTest::cleanup() { +} + +void StepTextWidgetTest::testConstructor() { + QWidget parent; + StepTextWidget* widget = new StepTextWidget(&parent); + + QCOMPARE(widget->parentWidget(), &parent); + QVERIFY(widget->isReadOnly()); + QCOMPARE(widget->frameShape(), QFrame::NoFrame); + QCOMPARE(widget->frameShadow(), QFrame::Plain); + QCOMPARE(widget->horizontalScrollBarPolicy(), Qt::ScrollBarAlwaysOff); + QCOMPARE(widget->verticalScrollBarPolicy(), Qt::ScrollBarAlwaysOff); + QCOMPARE(widget->palette().color(QPalette::Base), QColor(Qt::transparent)); +} + +void StepTextWidgetTest::testSizeHintWithBiggerText() { + StepTextWidget widget; + widget.setText("Some short text"); + + QSize oldSizeHint = widget.sizeHint(); + + widget.setText("Some bigger text to be shown hopefully in several lines"); + + QSize newSizeHint = widget.sizeHint(); + QCOMPARE(widget.heightForWidth(newSizeHint.width()), newSizeHint.height()); + QVERIFY(newSizeHint.width() > newSizeHint.height()); + QVERIFY(newSizeHint.height() > widget.minimumSizeHint().height()); + QVERIFY(newSizeHint.width() > widget.minimumSizeHint().width()); + QVERIFY(newSizeHint.height() > oldSizeHint.height()); + QVERIFY(newSizeHint.width() > oldSizeHint.width()); +} + +void StepTextWidgetTest::testSizeHintWithSmallerText() { + StepTextWidget widget; + widget.setText("Some bigger text to be shown hopefully in several lines"); + + QSize oldSizeHint = widget.sizeHint(); + + widget.setText("Some short text"); + + QSize newSizeHint = widget.sizeHint(); + QCOMPARE(widget.heightForWidth(newSizeHint.width()), newSizeHint.height()); + QVERIFY(newSizeHint.width() > newSizeHint.height()); + QVERIFY(newSizeHint.height() < oldSizeHint.height()); + QVERIFY(newSizeHint.width() < oldSizeHint.width()); +} + +void StepTextWidgetTest::testHighlightWidgetClickingOnAnchor() { + KXmlGuiWindow mainWindow; + KTutorial::self()->setup(&mainWindow); + QWidget* widgetToHighlight = new QWidget(&mainWindow); + widgetToHighlight->setObjectName("widgetName"); + + StepTextWidget widget; + widget.setText("The <a href=\"widget:widgetName\">widget to highlight</a>"); + widget.show(); + + QPoint position = centerOfText(widget, "widget to highlight"); + QTest::mouseClick(widget.viewport(), Qt::LeftButton, Qt::NoModifier, + position, 500); + + QVERIFY(widgetToHighlight->findChild<WidgetHighlighter*>("")); +} + +void StepTextWidgetTest::testStopHighlightingWidgetClickingOnAnchor() { + KXmlGuiWindow mainWindow; + KTutorial::self()->setup(&mainWindow); + QWidget* widgetToHighlight = new QWidget(&mainWindow); + widgetToHighlight->setObjectName("widgetName"); + + StepTextWidget widget; + widget.setText("The <a href=\"widget:widgetName\">widget to highlight</a>"); + widget.show(); + + QPoint position = centerOfText(widget, "widget to highlight"); + QTest::mouseClick(widget.viewport(), Qt::LeftButton, Qt::NoModifier, + position, 500); + QTest::mouseClick(widget.viewport(), Qt::LeftButton, Qt::NoModifier, + position, 500); + + //Give the highlighter time to stop + QTest::qWait(500); + + QVERIFY(!widgetToHighlight->findChild<WidgetHighlighter*>("")); +} + +void StepTextWidgetTest::testHighlightWidgetUsingContextMenu() { + KXmlGuiWindow mainWindow; + KTutorial::self()->setup(&mainWindow); + QWidget* widgetToHighlight = new QWidget(&mainWindow); + widgetToHighlight->setObjectName("widgetName"); + + StepTextWidget widget; + widget.setText("The <a href=\"widget:widgetName\">widget to highlight</a>"); + widget.show(); + + //Give the widget time to be shown + QTest::qWait(500); + + QPoint position = centerOfText(widget, "widget to highlight"); + showContextMenuAndSelectFirstOption(widget, position); + + QVERIFY(widgetToHighlight->findChild<WidgetHighlighter*>("")); +} + +void StepTextWidgetTest::testStopHighlightingWidgetUsingContextMenu() { + KXmlGuiWindow mainWindow; + KTutorial::self()->setup(&mainWindow); + QWidget* widgetToHighlight = new QWidget(&mainWindow); + widgetToHighlight->setObjectName("widgetName"); + + StepTextWidget widget; + widget.setText("The <a href=\"widget:widgetName\">widget to highlight</a>"); + widget.show(); + + //Give the widget time to be shown + QTest::qWait(500); + + QPoint position = centerOfText(widget, "widget to highlight"); + showContextMenuAndSelectFirstOption(widget, position); + QTest::qWait(500); + showContextMenuAndSelectFirstOption(widget, position); + + //Give the highlighter time to stop + QTest::qWait(500); + + QVERIFY(!widgetToHighlight->findChild<WidgetHighlighter*>("")); +} + +void StepTextWidgetTest::testHighlightSeveralWidgets() { + KXmlGuiWindow mainWindow; + KTutorial::self()->setup(&mainWindow); + QWidget* widgetToHighlight1 = new QWidget(&mainWindow); + widgetToHighlight1->setObjectName("widget1"); + QWidget* widgetToHighlight2 = new QWidget(&mainWindow); + widgetToHighlight2->setObjectName("widget2"); + QWidget* widgetToHighlight3 = new QWidget(&mainWindow); + widgetToHighlight3->setObjectName("widget3"); + + StepTextWidget widget; + widget.setText("The <a href=\"widget:widget1\">first widget</a>, " +"<a href=\"widget:widget2\">second widget</a> and " +"<a href=\"widget:widget3\">third widget</a>"); + widget.show(); + + QPoint position1 = centerOfText(widget, "first widget"); + QPoint position2 = centerOfText(widget, "second widget"); + QPoint position3 = centerOfText(widget, "third widget"); + + QTest::mouseClick(widget.viewport(), Qt::LeftButton, Qt::NoModifier, + position1, 500); + QTest::mouseClick(widget.viewport(), Qt::LeftButton, Qt::NoModifier, + position2, 500); + + //Give the highlighter time to stop + QTest::qWait(500); + + QVERIFY(!widgetToHighlight1->findChild<WidgetHighlighter*>("")); + QVERIFY(widgetToHighlight2->findChild<WidgetHighlighter*>("")); + QVERIFY(!widgetToHighlight3->findChild<WidgetHighlighter*>("")); + + showContextMenuAndSelectFirstOption(widget, position3); + + //Give the highlighter time to stop + QTest::qWait(500); + + QVERIFY(!widgetToHighlight1->findChild<WidgetHighlighter*>("")); + QVERIFY(!widgetToHighlight2->findChild<WidgetHighlighter*>("")); + QVERIFY(widgetToHighlight3->findChild<WidgetHighlighter*>("")); + + showContextMenuAndSelectFirstOption(widget, position1); + + //Give the highlighter time to stop + QTest::qWait(500); + + QVERIFY(widgetToHighlight1->findChild<WidgetHighlighter*>("")); + QVERIFY(!widgetToHighlight2->findChild<WidgetHighlighter*>("")); + QVERIFY(!widgetToHighlight3->findChild<WidgetHighlighter*>("")); + + QTest::mouseClick(widget.viewport(), Qt::LeftButton, Qt::NoModifier, + position1, 500); + + //Give the highlighter time to stop + QTest::qWait(500); + + QVERIFY(!widgetToHighlight1->findChild<WidgetHighlighter*>("")); + QVERIFY(!widgetToHighlight2->findChild<WidgetHighlighter*>("")); + QVERIFY(!widgetToHighlight3->findChild<WidgetHighlighter*>("")); + + QTest::mouseClick(widget.viewport(), Qt::LeftButton, Qt::NoModifier, + position2, 500); + QTest::qWait(500); + showContextMenuAndSelectFirstOption(widget, position2); + + //Give the highlighter time to stop + QTest::qWait(500); + + QVERIFY(!widgetToHighlight1->findChild<WidgetHighlighter*>("")); + QVERIFY(!widgetToHighlight2->findChild<WidgetHighlighter*>("")); + QVERIFY(!widgetToHighlight3->findChild<WidgetHighlighter*>("")); +} + +void StepTextWidgetTest::testStopHighlightingWidgetWhenFocused() { + KXmlGuiWindow mainWindow; + KTutorial::self()->setup(&mainWindow); + QWidget* widgetToHighlight = new QWidget(&mainWindow); + widgetToHighlight->setObjectName("widgetName"); + mainWindow.setCentralWidget(widgetToHighlight); + mainWindow.show(); + + StepTextWidget widget; + widget.setText("The <a href=\"widget:widgetName\">widget to highlight</a>"); + widget.show(); + + QPoint position = centerOfText(widget, "widget to highlight"); + QTest::mouseClick(widget.viewport(), Qt::LeftButton, Qt::NoModifier, + position, 500); + + //To get the focus, the parent window of the widget must be active + mainWindow.activateWindow(); + widgetToHighlight->setFocus(); + + //Give the highlighter time to stop + QTest::qWait(500); + + QVERIFY(!widgetToHighlight->findChild<WidgetHighlighter*>("")); +} + +void StepTextWidgetTest::testSetTextWhenWidgetIsBeingHighlighted() { + KXmlGuiWindow mainWindow; + KTutorial::self()->setup(&mainWindow); + QWidget* widgetToHighlight = new QWidget(&mainWindow); + widgetToHighlight->setObjectName("widgetName"); + + StepTextWidget widget; + widget.setText("The <a href=\"widget:widgetName\">widget to highlight</a>"); + widget.show(); + + QPoint position = centerOfText(widget, "widget to highlight"); + QTest::mouseClick(widget.viewport(), Qt::LeftButton, Qt::NoModifier, + position, 500); + + widget.setText("Another text"); + + QVERIFY(!widgetToHighlight->findChild<WidgetHighlighter*>("")); +} + +/////////////////////////////////// Helpers //////////////////////////////////// + +void StepTextWidgetTest::selectFirstContextMenuOption() { + QVERIFY(QApplication::activePopupWidget()); + QTest::keyClick(QApplication::activePopupWidget(), Qt::Key_Down); + QTest::keyClick(QApplication::activePopupWidget(), Qt::Key_Enter); +} + +QPoint StepTextWidgetTest::centerOfText(const StepTextWidget& widget, + const QString& text) { + QTextCursor cursor = widget.document()->find(text); + + //The cursor rect doesn't include the selection, just a tiny rectangle for + //the cursor position. To ensure that the menu is shown on the anchor, set + //the cursor in the middle of the selection + cursor.setPosition((cursor.selectionStart() + cursor.selectionEnd()) / 2); + return widget.cursorRect(cursor).center(); +} + +void StepTextWidgetTest::showContextMenuAndSelectFirstOption( + const StepTextWidget& widget, const QPoint& position) { + //The context menu can't be triggered sending a right mouse button press + //event, as that is platform dependent (that event is not handled by + //QTextEdit or its parents, but by the QApplication for the platform that + //creates a context menu event when needed). A explicit QContextMenuEvent + //must be sent for it to work. + QContextMenuEvent event(QContextMenuEvent::Mouse, position, + widget.mapToGlobal(position)); + + //The context menu contains its own event loop, so it won't return to the + //test code until it is closed. Thus, the commands to execute on the dialog + //must be "queued", as calling QTest::keyClick after the button click won't + //work. + QTimer::singleShot(500, this, SLOT(selectFirstContextMenuOption())); + QApplication::sendEvent(widget.viewport(), &event); +} + +} + +QTEST_KDEMAIN(view::StepTextWidgetTest, GUI) + +#include "StepTextWidgetTest.moc" Property changes on: trunk/ktutorial/ktutorial-library/tests/view/StepTextWidgetTest.cpp ___________________________________________________________________ Added: svn:eol-style + native Modified: trunk/ktutorial/ktutorial-library/tests/view/StepWidgetTest.cpp =================================================================== --- trunk/ktutorial/ktutorial-library/tests/view/StepWidgetTest.cpp 2010-04-26 05:30:40 UTC (rev 237) +++ trunk/ktutorial/ktutorial-library/tests/view/StepWidgetTest.cpp 2010-05-11 03:38:55 UTC (rev 238) @@ -28,6 +28,7 @@ #undef protected #include "ui_StepWidget.h" +#include "StepTextWidget.h" #include "../Option.h" #include "../Step.h" @@ -76,7 +77,7 @@ int mDummySlotCallCount; int mAnotherDummySlotCallCount; - QLabel* textLabel(StepWidget* stepWidget); + StepTextWidget* textWidget(StepWidget* stepWidget); KPushButton* closeButton(StepWidget* stepWidget); }; @@ -88,8 +89,8 @@ i18n("Tutorial: %1", QString("Test tutorial"))); QCOMPARE(stepWidget.windowFlags(), Qt::Dialog | Qt::FramelessWindowHint); QVERIFY(closeButton(&stepWidget)); - QVERIFY(textLabel(&stepWidget)); - QCOMPARE(textLabel(&stepWidget)->text(), QString("")); + QVERIFY(textWidget(&stepWidget)); + QCOMPARE(textWidget(&stepWidget)->toPlainText(), QString("")); QVERIFY(stepWidget.mOptionsLayout); QCOMPARE(stepWidget.mOptionsLayout->count(), 0); } @@ -104,7 +105,7 @@ stepWidget.setStep(&step); - QCOMPARE(textLabel(&stepWidget)->text(), QString("First step")); + QCOMPARE(textWidget(&stepWidget)->toPlainText(), QString("First step")); QCOMPARE(stepWidget.mOptionsLayout->count(), 1); KPushButton* button1 = qobject_cast<KPushButton*>( stepWidget.mOptionsLayout->itemAt(0)->widget()); @@ -123,7 +124,7 @@ stepWidget.setStep(&step1); - QCOMPARE(textLabel(&stepWidget)->text(), QString("First step")); + QCOMPARE(textWidget(&stepWidget)->toPlainText(), QString("First step")); QCOMPARE(stepWidget.mOptionsLayout->count(), 1); KPushButton* button = qobject_cast<KPushButton*>( stepWidget.mOptionsLayout->itemAt(0)->widget()); @@ -138,7 +139,7 @@ stepWidget.setStep(&step2); - QCOMPARE(textLabel(&stepWidget)->text(), QString("Second step")); + QCOMPARE(textWidget(&stepWidget)->toPlainText(), QString("Second step")); QCOMPARE(stepWidget.mOptionsLayout->count(), 2); button = qobject_cast<KPushButton*>( stepWidget.mOptionsLayout->itemAt(0)->widget()); @@ -155,7 +156,7 @@ stepWidget.setStep(&step3); - QCOMPARE(textLabel(&stepWidget)->text(), QString("Third step")); + QCOMPARE(textWidget(&stepWidget)->toPlainText(), QString("Third step")); QCOMPARE(stepWidget.mOptionsLayout->count(), 0); QVERIFY(stepWidget.isVisible()); } @@ -169,7 +170,7 @@ stepWidget.setStep(&step); - QCOMPARE(textLabel(&stepWidget)->text(), QString("First step")); + QCOMPARE(textWidget(&stepWidget)->toPlainText(), QString("First step")); QCOMPARE(stepWidget.mOptionsLayout->count(), 1); KPushButton* button1 = qobject_cast<KPushButton*>( stepWidget.mOptionsLayout->itemAt(0)->widget()); @@ -312,8 +313,8 @@ /////////////////////////////////// Helpers //////////////////////////////////// -QLabel* StepWidgetTest::textLabel(StepWidget* stepWidget) { - return stepWidget->ui->textLabel; +StepTextWidget* StepWidgetTest::textWidget(StepWidget* stepWidget) { + return stepWidget->ui->textWidget; } KPushButton* StepWidgetTest::closeButton(StepWidget* stepWidget) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |