KTutorial  0.5.1
StepTextWidget.cpp
00001 /***************************************************************************
00002  *   Copyright (C) 2010 by Daniel Calviño Sánchez <danxuliu@gmail.com>     *
00003  *   Copyright (C) 2011 by Daniel Calviño Sánchez <danxuliu@gmail.com>     *
00004  *   Copyright (C) 2012 by Daniel Calviño Sánchez <danxuliu@gmail.com>     *
00005  *                                                                         *
00006  *   This program is free software; you can redistribute it and/or modify  *
00007  *   it under the terms of the GNU General Public License as published by  *
00008  *   the Free Software Foundation; either version 2 of the License, or     *
00009  *   (at your option) any later version.                                   *
00010  *                                                                         *
00011  *   This program is distributed in the hope that it will be useful,       *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00014  *   GNU General Public License for more details.                          *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU General Public License     *
00017  *   along with this program; If not, see <http://www.gnu.org/licenses/>.  *
00018  ***************************************************************************/
00019 
00020 #include "StepTextWidget.h"
00021 
00022 #include <QContextMenuEvent>
00023 #include <QMenu>
00024 
00025 #include <KDebug>
00026 #include <KLocalizedString>
00027 
00028 #include "../KTutorial.h"
00029 #include "../extendedinformation/WidgetHighlighterManager.h"
00030 
00031 using ktutorial::extendedinformation::WidgetHighlighterManager;
00032 
00033 namespace ktutorial {
00034 extern int debugArea();
00035 }
00036 
00037 namespace ktutorial {
00038 namespace view {
00039 
00040 //public:
00041 
00042 StepTextWidget::StepTextWidget(QWidget* parent /*= 0*/):
00043         KTextEdit(parent),
00044     mLastReferencedWidget(0),
00045     mWidgetBeingHighlighted(0) {
00046     setReadOnly(true);
00047     setFrameShape(QFrame::NoFrame);
00048     setFrameShadow(QFrame::Plain);
00049     setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
00050     setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
00051 
00052     viewport()->setCursor(Qt::ArrowCursor);
00053 
00054     QPalette palette = this->palette();
00055     palette.setColor(QPalette::Base, Qt::transparent);
00056     setPalette(palette);
00057 
00058     setAlignment(Qt::AlignJustify | Qt::AlignVCenter);
00059 
00060     //Set a explicit text width to avoid some strange behavior: if the text
00061     //width is set to QWIDGETSIZE_MAX without a previous text width set, the
00062     //size returned by the document has weird values. Anyway, sizeHint is
00063     //usually called before minimumSizeHint, so a text width will be already set
00064     //when minimumSizeHint is called, but just in case.
00065     document()->setTextWidth(0);
00066 
00067     connect(this, SIGNAL(textChanged()), this, SLOT(updateText()));
00068 }
00069 
00070 StepTextWidget::~StepTextWidget() {
00071     if (mWidgetBeingHighlighted) {
00072         stopHighlightingCurrentWidget();
00073     }
00074 }
00075 
00076 bool StepTextWidget::eventFilter(QObject* watched, QEvent* event) {
00077     if (watched != mWidgetBeingHighlighted) {
00078         return false;
00079     }
00080 
00081     if (event->type() != QEvent::FocusIn) {
00082         return false;
00083     }
00084 
00085     stopHighlightingCurrentWidget();
00086 
00087     return false;
00088 }
00089 
00090 int StepTextWidget::heightForWidth(int width) const {
00091     return sizeForWidth(width).height();
00092 }
00093 
00094 QSize StepTextWidget::minimumSizeHint() const {
00095     QSize size;
00096     size.setHeight(sizeForWidth(QWIDGETSIZE_MAX).height());
00097     size.setWidth(sizeForWidth(0).width());
00098 
00099     return size;
00100 }
00101 
00102 QSize StepTextWidget::sizeHint() const {
00103     return sizeForWidth(-1);
00104 }
00105 
00106 //protected:
00107 
00108 void StepTextWidget::contextMenuEvent(QContextMenuEvent* event) {
00109     QString anchor = anchorAt(event->pos());
00110     if (!anchor.startsWith(QLatin1String("widget:"))) {
00111         KTextEdit::contextMenuEvent(event);
00112         return;
00113     }
00114 
00115     QMenu* menu = new QMenu(this);
00116 
00117     mLastReferencedWidget = widgetForAnchor(anchor);
00118     if (mLastReferencedWidget != mWidgetBeingHighlighted) {
00119         menu->addAction(i18nc("@item:inmenu", "Highlight"),
00120                         this, SLOT(highlightLastReferencedWidget()));
00121     } else {
00122         menu->addAction(i18nc("@item:inmenu", "Stop highlighting"),
00123                         this, SLOT(stopHighlightingCurrentWidget()));
00124     }
00125 
00126     menu->exec(event->globalPos());
00127     delete menu;
00128 }
00129 
00130 void StepTextWidget::mouseMoveEvent(QMouseEvent* event) {
00131     KTextEdit::mouseMoveEvent(event);
00132 
00133     if (anchorAt(event->pos()).startsWith(QLatin1String("widget:"))) {
00134         viewport()->setCursor(Qt::PointingHandCursor);
00135     } else {
00136         viewport()->setCursor(Qt::ArrowCursor);
00137     }
00138 }
00139 
00140 void StepTextWidget::mousePressEvent(QMouseEvent* event) {
00141     QString anchor = anchorAt(event->pos());
00142     if (event->button() != Qt::LeftButton ||
00143             !anchor.startsWith(QLatin1String("widget:"))) {
00144         KTextEdit::mousePressEvent(event);
00145         return;
00146     }
00147 
00148     mLastReferencedWidget = widgetForAnchor(anchor);
00149     if (mLastReferencedWidget != mWidgetBeingHighlighted) {
00150         highlightLastReferencedWidget();
00151     } else {
00152         stopHighlightingCurrentWidget();
00153     }
00154 }
00155 
00156 //private:
00157 
00158 QSize StepTextWidget::sizeForWidth(int width) const {
00159     const qreal oldTextWidth = document()->textWidth();
00160 
00161     if (width >= 0) {
00162         document()->setTextWidth(width);
00163     } else {
00164         document()->adjustSize();
00165     }
00166 
00167     QSize size = document()->size().toSize();
00168 
00169     document()->setTextWidth(oldTextWidth);
00170 
00171     return size;
00172 }
00173 
00174 QWidget* StepTextWidget::widgetForAnchor(const QString& anchor) {
00175     QString widgetName = anchor.mid(QString("widget:").length());
00176     return KTutorial::self()->findObject<QWidget*>(widgetName);
00177 }
00178 
00179 //private slots:
00180 
00181 void StepTextWidget::updateText() {
00182     updateGeometry();
00183 
00184     if (mWidgetBeingHighlighted) {
00185         stopHighlightingCurrentWidget();
00186     }
00187 }
00188 
00189 void StepTextWidget::highlightLastReferencedWidget() {
00190     if (!mLastReferencedWidget) {
00191         kWarning(debugArea()) << "The widget to highlight was not found!";
00192         return;
00193     }
00194 
00195     if (mWidgetBeingHighlighted) {
00196         stopHighlightingCurrentWidget();
00197     }
00198 
00199     WidgetHighlighterManager::self()->highlight(mLastReferencedWidget);
00200 
00201     mLastReferencedWidget->installEventFilter(this);
00202     mWidgetBeingHighlighted = mLastReferencedWidget;
00203 }
00204 
00205 void StepTextWidget::stopHighlightingCurrentWidget() {
00206     if (!mWidgetBeingHighlighted) {
00207         kWarning(debugArea()) << "The widget to stop highlighting was not"
00208                               << "found!";
00209         return;
00210     }
00211 
00212     WidgetHighlighterManager::self()->stopHighlighting(mWidgetBeingHighlighted);
00213 
00214     mWidgetBeingHighlighted->removeEventFilter(this);
00215     mWidgetBeingHighlighted = 0;
00216 }
00217 
00218 }
00219 }