KoContextCelp.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2002, Benoit Vautrin <benoit.vautrin@free.fr>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18*/
19
20#include "KoContextCelp.h"
21
22#include <tqpainter.h>
23#include <tqregion.h>
24#include <tqfont.h>
25#include <tqlabel.h>
26#include <tqlayout.h>
27#include <tqsimplerichtext.h>
28
29#include <kpixmap.h>
30#include <tdelocale.h>
31#include <kdebug.h>
32#include <kiconloader.h>
33#include <kcursor.h>
34#include <tdeapplication.h>
35#include <tqstring.h>
36
37KoVerticalLabel::KoVerticalLabel( TQWidget* parent, const char* name )
38 : TQWidget( parent, name, TQt::WRepaintNoErase )
39{
40 TQFont f( font() );
41 f.setPointSize( f.pointSize() + 2 );
42 f.setBold( true );
43 setFont( f );
44 setBackgroundMode( PaletteLight );
45} // KoVerticalLabel::KoVerticalLabel
46
47KoVerticalLabel::~KoVerticalLabel()
48{
49} // KoVerticalLabel::~KoVerticalLabel
50
51void KoVerticalLabel::setText( const TQString& text )
52{
53 m_text = text;
54 TQFontMetrics fm( font() );
55 setMinimumSize( fm.height() + 2, fm.width( m_text ) + 4 );
56 update();
57} // KoVerticalLabel::setText
58
59void KoVerticalLabel::paintEvent( TQPaintEvent* )
60{
61 KPixmap pm;
62 pm.resize( height(), width() );
63 TQPainter p( &pm );
64 p.fillRect( 0, 0, height(), width(), colorGroup().background() );
65 p.setFont( font() );
66 p.drawText( 0, 0, height(), width(), AlignCenter, m_text );
67 p.end();
68 TQPainter ap( this );
69 ap.rotate( 270. );
70 ap.translate( -height(), 0 );
71 ap.drawPixmap( 0, 0, pm );
72} // KoVerticalLabel::paintEvent
73
74static unsigned char upbits[] = { 0xc, 0x1e, 0x3f, 0x3f };
75static unsigned char downbits[] = { 0x3f, 0x3f, 0x1e, 0xc };
76
77KoHelpNavButton::KoHelpNavButton( NavDirection d, TQWidget* parent )
78 : TQWidget( parent )
79{
80 m_pressed = false;
81 m_bitmap = TQBitmap( 8, 4, ( d == Up ? upbits : downbits ), true );
82 m_bitmap.setMask( m_bitmap );
83 setFixedSize( 8, 6 );
84 setBackgroundMode( PaletteLight );
85} // KoHelpNavButton::KoHelpNavButton
86
87void KoHelpNavButton::paintEvent( TQPaintEvent* )
88{
89 TQPainter p( this );
90 if ( isEnabled() )
91 {
92 if ( m_pressed )
93 p.setPen( colorGroup().highlight() );
94 else
95 p.setPen( colorGroup().text() );
96 p.drawPixmap( 1, 1, m_bitmap );
97 }
98} // KoHelpNavButton::paintEvent
99
100void KoHelpNavButton::enterEvent( TQEvent* )
101{
102 if ( isEnabled() )
103 emit pressed();
104 m_pressed = true;
105 update();
106} // KoHelpNavButton::enterEvent
107
108void KoHelpNavButton::leaveEvent( TQEvent* )
109{
110 if ( isEnabled() )
111 emit released();
112 m_pressed = false;
113 update();
114} // KoHelpNavButton::leaveEvent
115
116static unsigned char notstickybits[] = { 0x8, 0x1e, 0xc, 0xa, 0x1 };
117static unsigned char stickybits[] = { 0xe, 0x11, 0x15, 0x11, 0xe };
118static unsigned char closebits[] = { 0x11, 0xa, 0x4, 0xa, 0x11 };
119
120KoTinyButton::KoTinyButton( Action a, TQWidget* parent )
121 : TQWidget( parent ), m_action( a )
122{
123 m_pressed = false;
124 m_toggled = false;
125 switch ( a )
126 {
127 case Sticky:
128 m_bitmap = TQBitmap( 5, 5, notstickybits, true );
129 break;
130
131 default:
132 m_bitmap = TQBitmap( 5, 5, closebits, true );
133 }
134 m_bitmap.setMask( m_bitmap );
135 setMinimumSize( 7, 7 );
136 setBackgroundMode( PaletteBackground );
137} // KoTinyButton::KoTinyButton
138
139void KoTinyButton::paintEvent( TQPaintEvent* )
140{
141 TQPainter p( this );
142 if ( isEnabled() )
143 {
144 if ( m_pressed )
145 p.setPen( colorGroup().highlight() );
146 else
147 p.setPen( colorGroup().text() );
148 p.drawPixmap( width() / 2 - 2, 1, m_bitmap );
149 }
150} // KoTinyButton::paintEvent
151
152void KoTinyButton::mousePressEvent( TQMouseEvent* )
153{
154 if ( isEnabled() )
155 {
156 m_pressed = true;
157 update();
158 }
159} // KoTinyButton::mousePressEvent
160
161void KoTinyButton::mouseReleaseEvent( TQMouseEvent* )
162{
163 if ( isEnabled() && m_pressed )
164 {
165 m_pressed = false;
166 emit( clicked() );
167 if ( ( m_action == Sticky ) )
168 {
169 m_toggled = !m_toggled;
170 emit( toggled( m_toggled ) );
171 //switch ( m_action )
172 //{
173 // case Sticky:
174 m_bitmap = TQBitmap( 5, 5, ( m_toggled ? stickybits : notstickybits ), true );
175 //}
176 m_bitmap.setMask( m_bitmap );
177 }
178 update();
179 }
180} // KoTinyButton::mouseReleaseEvent
181
182KoHelpView::KoHelpView( TQWidget* parent )
183 : TQWidget( parent )
184{
185 currentText = 0L;
186 setBackgroundMode( PaletteLight );
187 parent->installEventFilter( this );
188 setMouseTracking( true );
189} // KoHelpView::KoHelpView
190
191KoHelpView::~KoHelpView()
192{
193 if ( currentText )
194 delete currentText;
195} // KoHelpView::~KoHelpView
196
197void KoHelpView::setText( const TQString& text )
198{
199 if ( currentText )
200 delete currentText;
201 currentText = new TQSimpleRichText( text, font() );
202 currentText->setWidth( width() );
203 setFixedHeight( currentText->height() );
204} // KoHelpView::setText
205
206void KoHelpView::mousePressEvent( TQMouseEvent* e )
207{
208 currentAnchor = currentText->anchorAt( e->pos() );
209 if ( !currentAnchor.isEmpty() )
210 e->accept();
211 else
212 e->ignore();
213} // KoHelpView::mousePressEvent
214
215void KoHelpView::mouseReleaseEvent( TQMouseEvent* e )
216{
217 if ( ( !currentAnchor.isEmpty() ) && ( currentAnchor == currentText->anchorAt( e->pos() ) ) )
218 {
219 e->accept();
220 if (currentAnchor.startsWith("help://#")) {
221 //that's not really useful, since koffice documents can be embedded
222 kapp->invokeHelp(currentAnchor.right(currentAnchor.length()-8));
223 }
224 else
225 if (currentAnchor.startsWith("help://")) {
226 // that's the useful version of a help link
227 TQString helpapp=currentAnchor.right(currentAnchor.length()-7);
228 TQString helpanchor;
229 int pos;
230 if ((pos=helpapp.find("#"))!=-1) {
231 helpanchor=helpapp.right(helpapp.length()-pos-1);
232 helpapp=helpapp.left(pos);
233 }
234 kapp->invokeHelp(helpanchor,helpapp);
235 }
236 else
237 emit linkClicked( currentAnchor );
238 currentAnchor = "";
239 }
240 else
241 e->ignore();
242} // KoHelpView::mouseReleaseEvent
243
244void KoHelpView::mouseMoveEvent( TQMouseEvent* e )
245{
246 if ( !currentText->anchorAt( e->pos() ).isEmpty() )
247 setCursor( KCursor::handCursor() );
248 else
249 setCursor( KCursor::arrowCursor() );
250} // KoHelpView::mouseMove
251
252bool KoHelpView::eventFilter( TQObject*, TQEvent* e )
253{
254 if ( ( currentText ) && ( e->type() == TQEvent::Resize ) )
255 {
256 setFixedWidth( ( (TQResizeEvent*)e )->size().width() );
257 currentText->setWidth( width() );
258 setFixedHeight( currentText->height() );
259
260 return true;
261 }
262 return false;
263} // KoHelpView::resizeEvent
264
265void KoHelpView::paintEvent( TQPaintEvent* )
266{
267 TQPainter p( this );
268 currentText->draw( &p, 0, 0, TQRect(), colorGroup() );
269} // KoHelpView::paintEvent
270
271KoHelpWidget::KoHelpWidget( TQString help, TQWidget* parent )
272 : TQWidget( parent )
273{
274 TQGridLayout* layout = new TQGridLayout( this, 3, 3 );
275 layout->setMargin( 2 );
276 layout->addWidget( m_upButton = new KoHelpNavButton( KoHelpNavButton::Up, this ), 0, 1, AlignHCenter );
277 layout->addWidget( m_helpViewport = new TQWidget( this ), 1, 1 );
278 layout->addWidget( m_downButton = new KoHelpNavButton( KoHelpNavButton::Down, this ), 2, 1, AlignHCenter );
279 layout->addColSpacing( 0, 5 );
280 layout->addColSpacing( 2, 5 );
281 layout->setColStretch( 1, 1 );
282
283 m_helpView = new KoHelpView( m_helpViewport );
284 m_helpViewport->setBackgroundMode( PaletteLight );
285 setText( help );
286
287 setBackgroundMode( PaletteLight );
288
289 connect( m_upButton, TQ_SIGNAL( pressed() ), this, TQ_SLOT( startScrollingUp() ) );
290 connect( m_downButton, TQ_SIGNAL( pressed() ), this, TQ_SLOT( startScrollingDown() ) );
291 connect( m_upButton, TQ_SIGNAL( released() ), this, TQ_SLOT( stopScrolling() ) );
292 connect( m_downButton, TQ_SIGNAL( released() ), this, TQ_SLOT( stopScrolling() ) );
293 connect( m_helpView, TQ_SIGNAL( linkClicked( const TQString& ) ), this, TQ_SIGNAL( linkClicked( const TQString& ) ) );
294} // KoHelpWidget::KoHelpWidget
295
296void KoHelpWidget::updateButtons()
297{
298 m_upButton->setEnabled( m_ypos < 0 );
299 m_downButton->setEnabled( m_helpViewport->height() - m_ypos < m_helpView->height() );
300} // KoHelpWidget::updateButtons
301
302void KoHelpWidget::setText( TQString text )
303{
304 m_helpView->setText( text );
305 m_helpView->move( 0, 0 );
306 m_ypos = 0;
307 updateButtons();
308} // KoHelpWidget::setText
309
310void KoHelpWidget::resizeEvent( TQResizeEvent* )
311{
312 updateButtons();
313} // KoHelpWidget::resizeEvent
314
315void KoHelpWidget::startScrollingUp()
316{
317 if ( !m_upButton->isEnabled() )
318 return;
319 m_scrollDown = false;
320 startTimer( 80 );
321} // KoHelpWidget::startScrollingUp
322
323void KoHelpWidget::startScrollingDown()
324{
325 if ( !m_downButton->isEnabled() )
326 return;
327 m_scrollDown = true;
328 startTimer( 80 );
329} // KoHelpWidget::startScrollingDown
330
331void KoHelpWidget::scrollUp()
332{
333 if ( m_ypos > 0 )
334 stopScrolling();
335 else
336 {
337 m_ypos += 2;
338 m_helpViewport->scroll( 0, 2 );
339 m_helpViewport->update();
340 updateButtons();
341 }
342} // KoHelpWidget::scrollUp()
343
344void KoHelpWidget::scrollDown()
345{
346 if ( m_helpViewport->height() - m_helpView->height() - m_ypos > 0 )
347 stopScrolling();
348 else
349 {
350 m_ypos -= 2;
351 m_helpViewport->scroll( 0, -2 );
352 m_helpViewport->update();
353 updateButtons();
354 }
355} // KoHelpWidget::scrollUp()
356
357void KoHelpWidget::timerEvent( TQTimerEvent* )
358{
359 if ( m_scrollDown )
360 scrollDown();
361 else
362 scrollUp();
363} // KoHelpWidget::timerEvent
364
365void KoHelpWidget::stopScrolling()
366{
367 this->killTimers();
368} // KoHelpWidget::stopScrolling
369
370KoContextHelpPopup::KoContextHelpPopup( TQWidget* parent )
371 : TQWidget( parent, "", WType_Dialog | WStyle_Customize | WStyle_NoBorder )
372{
373 TQGridLayout* layout = new TQGridLayout( this );
374 TQHBoxLayout* buttonLayout;
375 layout->addWidget( m_helpIcon = new TQLabel( this ), 0, 0 );
376 layout->addWidget( m_helpTitle = new KoVerticalLabel( this ), 1, 0 );
377 buttonLayout = new TQHBoxLayout( layout );
378 //layout->addLayout( buttonLayout, 2, 0 );
379 layout->addMultiCellWidget( m_helpViewer = new KoHelpWidget( "", this ), 0, 2, 1, 1 );
380 buttonLayout->add( m_close = new KoTinyButton( KoTinyButton::Close, this ) );
381 buttonLayout->add( m_sticky = new KoTinyButton( KoTinyButton::Sticky, this ) );
382 layout->addColSpacing( 2, 2 );
383 layout->addRowSpacing( 3, 2 );
384 layout->setMargin( 3 );
385 layout->setSpacing( 1 );
386 layout->setRowStretch( 1, 1 );
387 buttonLayout->setSpacing( 1 );
388 setMinimumSize( 180, 180 );
389
390 m_isSticky = false;
391 setFocusPolicy( TQWidget::StrongFocus );
392
393 connect( m_close, TQ_SIGNAL( clicked() ), this, TQ_SIGNAL( wantsToBeClosed() ) );
394 connect( m_sticky, TQ_SIGNAL( toggled( bool ) ), this, TQ_SLOT( setSticky( bool ) ) );
395 connect( m_helpViewer, TQ_SIGNAL( linkClicked( const TQString& ) ), this, TQ_SIGNAL( linkClicked( const TQString& ) ) );
396} // KoContextHelpPopup::KoContextHelpPopup
397
398KoContextHelpPopup::~KoContextHelpPopup()
399{
400} // KoContextHelpPopup::~KoContextHelpPopup
401
402void KoContextHelpPopup::setContextHelp( const TQString& title, const TQString& text, const TQPixmap* icon )
403{
404 m_helpIcon->setPixmap( icon ? *icon : BarIcon( "help" ) );
405 m_helpTitle->setText( title );
406 m_helpViewer->setText( text );
407} // KoContextHelpPopup::updateHelp
408
409void KoContextHelpPopup::mousePressEvent( TQMouseEvent* e )
410{
411 m_mousePos = e->globalPos() - pos();
412} // KoContextHelpPopup::mousePressEvent
413
414void KoContextHelpPopup::mouseMoveEvent( TQMouseEvent* e )
415{
416 move( e->globalPos() - m_mousePos );
417} // KoContextHelpPopup::mouseMoveEvent
418
419void KoContextHelpPopup::resizeEvent( TQResizeEvent* )
420{
421 TQBitmap mask( width(), height() );
422 TQPointArray a;
423 TQPainter p( &mask );
424 p.fillRect( 0, 0, width(), height(), color1 );
425 p.setPen( color0 );
426 p.setBrush( color0 );
427 p.drawLine( 0, 0, 0, 3 );
428 p.drawLine( 0, 0, 3, 0 );
429 p.drawPoint( 1, 1 );
430 a.setPoints( 3, 0, height() - 5, 4, height() - 1, 0, height() - 1 );
431 p.drawPolygon( a );
432 a.setPoints( 3, width() - 5, 0, width() - 1, 4, width() - 1, 0 );
433 p.drawPolygon( a );
434 p.drawLine( width() - 1, height() - 1, width() - 4, height() - 1 );
435 p.drawLine( width() - 1, height() - 1, width() - 1, height() - 4 );
436 p.drawPoint( width() - 2, height() - 2 );
437 p.drawPoint( 0, height() - 6 );
438 p.drawPoint( width() - 6, 0 );
439 p.drawPoint( width() - 5, height() - 3 );
440 p.drawPoint( width() - 3, height() - 5 );
441 p.setPen( NoPen );
442 p.setBrush( TQBrush( color0, Dense4Pattern ) );
443 p.drawRect( 0, height() - 2, width() - 1, height() - 1 );
444 p.drawRect( width() - 2, 0, width() - 1, height() - 1 );
445 p.drawRect( width() - 4, height() - 4, width() - 2, height() - 2 );
446 p.end();
447 setMask( TQRegion( mask ) );
448} // KoContextHelpPopup::resizeEvent
449
450void KoContextHelpPopup::paintEvent( TQPaintEvent* )
451{
452 TQPainter p( this );
453 p.fillRect( 0, 0, width(), height(), colorGroup().light() );
454 p.setPen( black );
455 p.drawRect( 0, 0, width(), height() );
456 p.fillRect( width() - 3, 0, width() - 1, height() - 1, black );
457 p.fillRect( 0, height() - 3, width() - 1, height() - 1, black );
458 p.drawLine( 1, 2, 1, 3 );
459 p.drawLine( 2, 1, 3, 1 );
460 p.drawLine( width() - 4, 2, width() - 4, 3 );
461 p.drawLine( width() - 5, 1, width() - 6, 1 );
462 p.drawLine( 1, height() - 5, 1, height() - 6 );
463 p.drawLine( 2, height() - 4, 3, height() - 4 );
464 p.drawLine( width() - 4, height() - 5, width() - 4, height() - 6 );
465 p.drawLine( width() - 4, height() - 4, width() - 6, height() - 4 );
466} // KoContextHelpPopup::paintEvent
467
468void KoContextHelpPopup::windowActivationChange( bool )
469{
470 if ( !isActiveWindow() && !m_isSticky )
471 emit wantsToBeClosed();
472} // KoContestHelpPopup::windowActivationChange
473
474void KoContextHelpPopup::keyPressEvent( TQKeyEvent* e )
475{
476 switch ( e->key() )
477 {
478/* case Key_Up:
479 m_helpViewer->startScrollingUp();
480 break;
481
482 case Key_Down:
483 m_helpViewer->startScrollingDown();
484 break;*/
485 case Key_Up:
486 m_helpViewer->scrollUp();
487 break;
488
489 case Key_Down:
490 m_helpViewer->scrollDown();
491 break;
492 }
493} // KoContextHelpPopup::keyPressEvent
494
495void KoContextHelpPopup::keyReleaseEvent( TQKeyEvent* e )
496{
497 switch ( e->key() )
498 {
499 /*case Key_Up:
500 case Key_Down:
501 m_helpViewer->stopScrolling();
502 break;*/
503
504 case Key_Escape:
505 emit wantsToBeClosed();
506 break;
507 }
508} // KoContextHelpPopup::keyPressEvent
509
510KoContextHelpAction::KoContextHelpAction( TDEActionCollection* parent, TQWidget* /*popupParent*/ )
511 : TDEToggleAction( i18n( "Context Help" ), BarIcon( "help" ), TDEShortcut( "CTRL+SHIFT+F1" ), 0, 0, parent, "help_context" )
512{
513 m_popup = new KoContextHelpPopup( 0L );
514 connect( m_popup, TQ_SIGNAL( wantsToBeClosed() ), this, TQ_SLOT( closePopup() ) );
515 connect( this, TQ_SIGNAL( toggled( bool ) ), m_popup, TQ_SLOT( setShown( bool ) ) );
516 connect( m_popup, TQ_SIGNAL( linkClicked( const TQString& ) ), this, TQ_SIGNAL( linkClicked( const TQString& ) ) );
517} // KoContextHelpAction::KoContextHelpAction
518
519KoContextHelpAction::~KoContextHelpAction()
520{
521 delete m_popup;
522} // KoContextHelpAction::~KoContextHelpAction
523
524void KoContextHelpAction::updateHelp( const TQString& title, const TQString& text, const TQPixmap* icon )
525{
526 m_popup->setContextHelp( title, text, icon );
527} // KoContextHelpAction::updateHelp
528
529void KoContextHelpAction::closePopup()
530{
531 activate();
532 setChecked( false ); // For a unknown reason, this is needed...
533} // KoContextHelpAction::closePopup
534
535
536KoContextHelpWidget::KoContextHelpWidget( TQWidget* parent, const char* name )
537 : TQWidget( parent, name )
538{
539 setCaption( i18n( "Context Help" ) );
540 TQGridLayout* layout = new TQGridLayout( this );
541 layout->addWidget( m_helpIcon = new TQLabel( this ), 0, 0 );
542 layout->addWidget( m_helpTitle = new KoVerticalLabel( this ), 1, 0 );
543 layout->addMultiCellWidget( m_helpViewer = new KoHelpWidget( "", this ), 0, 1, 1, 1 );
544 layout->setMargin( 2 );
545 layout->setSpacing( 1 );
546 layout->setRowStretch( 1, 1 );
547 this->setMinimumSize( 180, 120 );
548 this->show();
549 setContextHelp( i18n( "Context Help" ), i18n( "Here will be shown help according to your actions" ), 0 );
550 connect( m_helpViewer, TQ_SIGNAL( linkClicked( const TQString& ) ), this, TQ_SIGNAL( linkClicked( const TQString& ) ) );
551} // KoContextHelpWidget::KoContextHelpWidget
552
553KoContextHelpWidget::~KoContextHelpWidget()
554{
555} // KoContextHelpWidget::~KoContextHelpWidget
556
557void KoContextHelpWidget::setContextHelp( const TQString& title, const TQString& text, const TQPixmap* icon )
558{
559 m_helpIcon->setPixmap( icon ? *icon : BarIcon( "help" ) );
560 m_helpTitle->setText( title );
561 m_helpViewer->setText( text );
562} // KoContextHelpWidget::updateHelp
563
564
565KoContextHelpDocker::KoContextHelpDocker( TQWidget* parent, const char* name )
566 : TQDockWindow( parent, name )
567{
568 setCaption( i18n( "Context Help" ) );
569 TQWidget* mainWidget = new TQWidget( this );
570 TQGridLayout* layout = new TQGridLayout( mainWidget );
571 layout->addWidget( m_helpIcon = new TQLabel( mainWidget ), 0, 0 );
572 layout->addWidget( m_helpTitle = new KoVerticalLabel( mainWidget ), 1, 0 );
573 layout->addMultiCellWidget( m_helpViewer = new KoHelpWidget( "", mainWidget ), 0, 1, 1, 1 );
574 layout->setMargin( 2 );
575 layout->setSpacing( 1 );
576 layout->setRowStretch( 1, 1 );
577 mainWidget->setMinimumSize( 180, 120 );
578 mainWidget->show();
579 setWidget( mainWidget );
580 setContextHelp( i18n( "Context Help" ), i18n( "Here will be shown help according to your actions" ), 0 );
581 connect( m_helpViewer, TQ_SIGNAL( linkClicked( const TQString& ) ), this, TQ_SIGNAL( linkClicked( const TQString& ) ) );
582} // KoContextHelpDocker::KoContextHelpDocker
583
584KoContextHelpDocker::~KoContextHelpDocker()
585{
586} // KoContextHelpDocker::~KoContextHelpDocker
587
588void KoContextHelpDocker::setContextHelp( const TQString& title, const TQString& text, const TQPixmap* icon )
589{
590 m_helpIcon->setPixmap( icon ? *icon : BarIcon( "help" ) );
591 m_helpTitle->setText( title );
592 m_helpViewer->setText( text );
593} // KoContextHelpDocker::updateHelp
594
595#include "KoContextCelp.moc"
static TQCursor arrowCursor()
static TQCursor handCursor()
KoContextHelpPopup is the popup displayed by ContextHelpAction.
virtual void activate()
virtual TQString text() const
virtual void setChecked(bool)
const char * name(StdAction id)