~ubuntu-branches/ubuntu/wily/psi/wily-proposed

« back to all changes in this revision

Viewing changes to src/widgets/psitiplabel.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2008-08-28 18:46:52 UTC
  • mfrom: (1.2.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20080828184652-iiik12dl91nq7cdi
Tags: 0.12-2
Uploading to unstable (Closes: Bug#494352)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "psitiplabel.h"
 
2
 
 
3
#include <QApplication>
 
4
#include <QAbstractTextDocumentLayout>
 
5
#include <QTextFrame>
 
6
#include <QStyle>
 
7
#include <QStyleOption>
 
8
#include <QStylePainter>
 
9
#include <QTimer>
 
10
#include <QToolTip>
 
11
#include <QTextEdit>
 
12
 
 
13
#include "psirichtext.h"
 
14
 
 
15
PsiTipLabel *PsiTipLabel::instance_ = 0;
 
16
 
 
17
PsiTipLabel* PsiTipLabel::instance()
 
18
{
 
19
        return instance_;
 
20
}
 
21
 
 
22
PsiTipLabel::PsiTipLabel(QWidget* parent)
 
23
        : QFrame(parent, Qt::ToolTip)
 
24
        , doc(0)
 
25
{
 
26
        delete instance_;
 
27
        instance_ = this;
 
28
}
 
29
 
 
30
void PsiTipLabel::init(const QString& text)
 
31
{
 
32
        setText(text);
 
33
        initUi();
 
34
        resize(sizeHint());
 
35
        qApp->installEventFilter(this);
 
36
        startHideTimer();
 
37
        setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, 0, this) / 255.0);
 
38
        setPalette(QToolTip::palette());
 
39
}
 
40
 
 
41
void PsiTipLabel::setText(const QString& text)
 
42
{
 
43
        theText_ = text;
 
44
        isRichText = false;
 
45
        if (doc) {
 
46
                if (Qt::mightBeRichText(theText_)) {
 
47
                        isRichText = true;
 
48
                        PsiRichText::install(doc);
 
49
                        PsiRichText::setText(doc, theText_);
 
50
                }
 
51
                else {
 
52
                        doc->setPlainText(theText_);
 
53
                }
 
54
        }
 
55
}
 
56
 
 
57
void PsiTipLabel::initUi()
 
58
{
 
59
        margin = 1 + style()->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth, 0, this);
 
60
        setFrameStyle(QFrame::NoFrame);
 
61
 
 
62
        // doc = new QTextDocument(this);
 
63
        // QTextDocumentLayout is private in Qt4
 
64
        // and it's impossible to set wrapping mode directly.
 
65
        // So we create this QTextEdit instance and use its QTextDocument,
 
66
        // just because QTextEdit can set the wrapping mode.
 
67
        // Yes, this is crazy...
 
68
        QTextEdit *edit = new QTextEdit(this);
 
69
        edit->hide();
 
70
        edit->setWordWrapMode(QTextOption::WordWrap);
 
71
        doc = edit->document();
 
72
        doc->setUndoRedoEnabled(false);
 
73
        doc->setDefaultFont(font());
 
74
 
 
75
        ensurePolished();
 
76
        setText(theText_);
 
77
}
 
78
 
 
79
void PsiTipLabel::startHideTimer()
 
80
{
 
81
        hideTimer.start(10000, this);
 
82
}
 
83
 
 
84
QString PsiTipLabel::theText() const
 
85
{
 
86
        return theText_;
 
87
}
 
88
/*
 
89
QSize PsiTipLabel::sizeForWidth(int w) const
 
90
{
 
91
        QRect br;
 
92
 
 
93
        int hextra = 2 * margin;
 
94
        int vextra = hextra;
 
95
 
 
96
        if (isRichText) {
 
97
                hextra = 1;
 
98
                vextra = 1;
 
99
        }
 
100
 
 
101
        PsiRichText::ensureTextLayouted(doc, w);
 
102
        const qreal oldTextWidth = doc->textWidth();
 
103
 
 
104
        doc->adjustSize();
 
105
        br = QRect(QPoint(0, 0), doc->size().toSize());
 
106
        doc->setTextWidth(oldTextWidth);
 
107
 
 
108
        QFontMetrics fm(font());
 
109
        QSize extra(hextra + 1, vextra);
 
110
 
 
111
        // Make it look good with the default ToolTip font on Mac, which has a small descent.
 
112
        if (fm.descent() == 2 && fm.ascent() >= 11)
 
113
                vextra++;
 
114
 
 
115
        const QSize contentsSize(br.width() + hextra, br.height() + vextra);
 
116
        return contentsSize;
 
117
}
 
118
*/
 
119
QSize PsiTipLabel::sizeHint() const
 
120
{
 
121
        QTextFrameFormat fmt = doc->rootFrame()->frameFormat();
 
122
        fmt.setMargin(0);
 
123
        doc->rootFrame()->setFrameFormat(fmt);
 
124
        // PsiRichText::ensureTextLayouted(doc, -1);
 
125
 
 
126
        doc->adjustSize();
 
127
        // br = QRect(QPoint(0, 0), doc->size().toSize());
 
128
        // this way helps to fight empty space on the right:
 
129
        QSize docSize = QSize(doc->idealWidth(), doc->size().toSize().height());
 
130
 
 
131
        QFontMetrics fm(font());
 
132
        QSize extra(2*margin + 2, 2*margin + 1);        // "+" for tip's frame
 
133
        // Make it look good with the default ToolTip font on Mac, which has a small descent.
 
134
        if (fm.descent() == 2 && fm.ascent() >= 11)
 
135
                ++extra.rheight();
 
136
 
 
137
        return docSize + extra;
 
138
}
 
139
 
 
140
QSize PsiTipLabel::minimumSizeHint() const
 
141
{
 
142
        return sizeHint();
 
143
        // qWarning("PsiTipLabel::minimumSizeHint");
 
144
        // ensurePolished();
 
145
        // QSize sh = sizeForWidth(-1);
 
146
        // QSize msh(-1, -1);
 
147
        //
 
148
        // msh.rheight() = sizeForWidth(QWIDGETSIZE_MAX).height(); // height for one line
 
149
        // msh.rwidth()  = sizeForWidth(0).width(); // wrap ? size of biggest word : min doc size
 
150
        // if (sh.height() < msh.height())
 
151
        //      msh.rheight() = sh.height();
 
152
        //
 
153
        // return msh;
 
154
}
 
155
 
 
156
void PsiTipLabel::paintEvent(QPaintEvent *)
 
157
{
 
158
        QStylePainter p(this);
 
159
        QStyleOptionFrame opt;
 
160
        opt.init(this);
 
161
        p.drawPrimitive(QStyle::PE_PanelTipLabel, opt);
 
162
        p.end();
 
163
 
 
164
        // stolen from QLabel::paintEvent
 
165
        QPainter painter(this);
 
166
        drawFrame(&painter);
 
167
        QRect cr = contentsRect();
 
168
        cr.adjust(margin, margin, -margin, -margin);
 
169
 
 
170
        PsiRichText::ensureTextLayouted(doc, width() - 2*margin);
 
171
        QAbstractTextDocumentLayout *layout = doc->documentLayout();
 
172
        // QRect lr = rect();
 
173
        QRect lr = cr;
 
174
 
 
175
        QAbstractTextDocumentLayout::PaintContext context;
 
176
 
 
177
        // Adjust the palette
 
178
        context.palette = palette();
 
179
        if (foregroundRole() != QPalette::Text && isEnabled())
 
180
                context.palette.setColor(QPalette::Text, context.palette.color(foregroundRole()));
 
181
 
 
182
        painter.save();
 
183
        painter.translate(lr.x() + 1, lr.y() + 1);
 
184
        painter.setClipRect(lr.translated(-lr.x() - 1, -lr.y() - 1));
 
185
        layout->draw(&painter, context);
 
186
        painter.restore();
 
187
}
 
188
 
 
189
PsiTipLabel::~PsiTipLabel()
 
190
{
 
191
        instance_ = 0;
 
192
}
 
193
 
 
194
void PsiTipLabel::hideTip()
 
195
{
 
196
        hide();
 
197
        // timer based deletion to prevent animation
 
198
        deleteTimer.start(250, this);
 
199
}
 
200
 
 
201
void PsiTipLabel::enterEvent(QEvent*)
 
202
{
 
203
        hideTip();
 
204
}
 
205
 
 
206
void PsiTipLabel::timerEvent(QTimerEvent *e)
 
207
{
 
208
        if (e->timerId() == hideTimer.timerId())
 
209
                hideTip();
 
210
        else if (e->timerId() == deleteTimer.timerId())
 
211
                deleteLater();
 
212
}
 
213
 
 
214
bool PsiTipLabel::eventFilter(QObject *, QEvent *e)
 
215
{
 
216
        switch (e->type()) {
 
217
        case QEvent::KeyPress:
 
218
        case QEvent::KeyRelease: {
 
219
                int key = static_cast<QKeyEvent *>(e)->key();
 
220
                Qt::KeyboardModifiers mody = static_cast<QKeyEvent *>(e)->modifiers();
 
221
 
 
222
                if ((mody & Qt::KeyboardModifierMask)
 
223
                    || (key == Qt::Key_Shift || key == Qt::Key_Control
 
224
                    || key == Qt::Key_Alt || key == Qt::Key_Meta))
 
225
                        break;
 
226
        }
 
227
        case QEvent::Leave:
 
228
        case QEvent::WindowActivate:
 
229
        case QEvent::WindowDeactivate:
 
230
        case QEvent::MouseButtonPress:
 
231
        case QEvent::MouseButtonRelease:
 
232
        case QEvent::MouseButtonDblClick:
 
233
        case QEvent::FocusIn:
 
234
        case QEvent::FocusOut:
 
235
        case QEvent::Wheel:
 
236
                hideTip();
 
237
        default:
 
238
                ;
 
239
        }
 
240
        return false;
 
241
}