kpresenter

KPrSideBar.cpp
1/* This file is part of the KDE project
2 Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
3 Copyright (C) 2001 Lukas Tinkl <lukas@kde.org>
4 Copyright (C) 2002 Ariya Hidayat <ariya@kde.org>
5 Copyright (C) 2005 Laurent Montel <montel@kde.org>
6 Copyright (C) 2005 Thorsten Zachmann <zachmann@kde.org>
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details.
17
18 You should have received a copy of the GNU Library General Public License
19 along with this library; see the file COPYING.LIB. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22*/
23
24#include <tqheader.h>
25#include <tqtimer.h>
26#include <tqpopupmenu.h>
27#include <tqimage.h>
28#include <tqtabwidget.h>
29#include <tqtooltip.h>
30
31#include <kwordwrap.h>
32#include <tdemessagebox.h>
33#include <tdelocale.h>
34#include <kinputdialog.h>
35#include <knotifyclient.h>
36#include <kiconview.h>
37#include <kdebug.h>
38
39#include "KPrSideBar.h"
40#include "KPrView.h"
41#include "KPrDocument.h"
42#include "KPrCanvas.h"
43#include "KPrPage.h"
44#include "KPrObject.h"
45#include <tqapplication.h>
46#include "KPrCommand.h"
47#include <tqvalidator.h>
48#include "KPrFreehandObject.h"
49#include "KPrBezierCurveObject.h"
50#include "KPrTextObject.h"
51#include "KPrPolylineObject.h"
52#include "KPrClosedLineObject.h"
53#include "KPrGroupObject.h"
54
55
56TQValidator::State KPrRenamePageValidator::validate( TQString & input, int& ) const
57{
58 TQString str = input.stripWhiteSpace();
59 if ( str.isEmpty() ) // we want to allow empty titles. Empty == automatic.
60 return Acceptable;
61
62 if ( mStringList.find( str ) == mStringList.end() )
63 return Acceptable;
64 else
65 return Intermediate;
66}
67
68class ThumbToolTip : public TQToolTip
69{
70public:
71 ThumbToolTip( KPrThumbBar *parent )
72 : TQToolTip( parent->viewport() )
73 , m_thumbBar( parent )
74 {}
75
76protected:
77 void maybeTip(const TQPoint &pos)
78 {
79 TQString title;
80 TQRect r( m_thumbBar->tip( pos, title ) );
81 if (!r.isValid())
82 return;
83
84 tip(r, title);
85 }
86private:
87 KPrThumbBar *m_thumbBar;
88};
89
90
91class OutlineSlideItem: public TDEListViewItem
92{
93public:
94 OutlineSlideItem( TDEListView * parent, KPrPage* page, bool _masterPage );
95 OutlineSlideItem( TDEListView * parent, OutlineSlideItem *after, KPrPage* page, bool _masterPage );
96
97 KPrPage* page() const { return m_page; }
98
99 void setPage( KPrPage* p );
100
101 void update();
102 void updateTitle();
103
104private:
105 KPrPage* m_page;
106 bool m_masterPage;
107};
108
109class OutlineObjectItem: public TDEListViewItem
110{
111public:
112 OutlineObjectItem( OutlineSlideItem * parent, KPrObject* object,
113 const TQString& name = TQString() );
114
115 KPrObject* object() const { return m_object; }
116
117 void setObject( KPrObject* o );
118
119private:
120 KPrObject* m_object;
121};
122
123class ThumbItem : public TQIconViewItem
124{
125public:
126 ThumbItem( TQIconView *parent, const TQString & text, const TQPixmap & icon )
127 : TQIconViewItem( parent, text, icon )
128 { uptodate = true; }
129 ThumbItem( TQIconView *parent, TQIconViewItem *after, const TQString & text, const TQPixmap & icon )
130 : TQIconViewItem( parent, after, text, icon )
131 { uptodate = true; }
132
133 virtual bool isUptodate() { return uptodate; };
134 virtual void setUptodate( bool _uptodate) { uptodate = _uptodate; };
135
136private:
137 bool uptodate;
138};
139
140KPrSideBar::KPrSideBar(TQWidget *parent, KPrDocument *d, KPrView *v)
141 :TQTabWidget(parent), m_doc(d), m_view(v)
142{
143 setTabPosition(TQTabWidget::Top);
144 setTabShape(TQTabWidget::Triangular);
145
146 m_outline = new KPrOutline(this, m_doc, m_view);
147 addTab(m_outline, i18n("Structure of the presentation", "Outline"));
148
149 m_thb = new KPrThumbBar(this, m_doc, m_view);
150 addTab(m_thb,i18n("Preview"));
151
152
153 //TODO find a better way
154 connect(m_outline, TQ_SIGNAL(showPage(int)),
155 this, TQ_SIGNAL(showPage(int)));
156
157 connect(m_thb, TQ_SIGNAL(showPage(int)),
158 this, TQ_SIGNAL(showPage(int)));
159
160 connect(m_outline, TQ_SIGNAL(movePage(int,int)),
161 this, TQ_SIGNAL(movePage(int,int)));
162
163 connect(m_outline, TQ_SIGNAL(selectPage(int,bool)),
164 this, TQ_SIGNAL(selectPage(int,bool)));
165
166 connect(this, TQ_SIGNAL(currentChanged(TQWidget *)),
167 this, TQ_SLOT(currentChanged(TQWidget *)));
168
169}
170
171void KPrSideBar::currentChanged(TQWidget *tab)
172{
173 if (tab == m_thb) {
174 if (!m_thb->uptodate && m_thb->isVisible())
175 m_thb->rebuildItems();
176 else
177 m_thb->refreshItems();
178 }
179}
180
181void KPrSideBar::addItem( int pos )
182{
183 m_outline->addItem( pos );
184 m_thb->addItem( pos );
185}
186
187void KPrSideBar::moveItem( int oldPos, int newPos )
188{
189 m_outline->moveItem( oldPos, newPos );
190 m_thb->moveItem( oldPos, newPos );
191}
192
193void KPrSideBar::removeItem( int pos )
194{
195 m_outline->removeItem( pos );
196 m_thb->removeItem( pos );
197}
198
199void KPrSideBar::updateItem( KPrPage *page )
200{
201 bool sticky = false;
202 int pos = 0;
203 if ( page == m_doc->masterPage() )
204 {
205 pos = -1;
206 sticky = true;
207 }
208 else
209 {
210 pos = m_doc->pageList().findRef( page );
211 }
212
213 m_outline->updateItem( pos, sticky );
214 m_thb->updateItem( pos, sticky );
215}
216
217void KPrSideBar::setViewMasterPage( bool _masterPage )
218{
219 m_outline->setViewMasterPage( _masterPage );
220 m_thb->setViewMasterPage( _masterPage );
221 m_outline->rebuildItems();
222 m_thb->rebuildItems();
223}
224
225KPrSideBarBase::KPrSideBarBase(KPrDocument *_doc, KPrView *_view)
226 : m_doc( _doc ), m_view( _view ), m_viewMasterPage( false )
227{
228}
229
230void KPrSideBarBase::setViewMasterPage( bool _b )
231{
232 m_viewMasterPage = _b;
233}
234
235KPrThumbBar::KPrThumbBar(TQWidget *parent, KPrDocument *d, KPrView *v)
236 :TDEIconView(parent), KPrSideBarBase( d,v)
237{
238 uptodate = false;
239 m_offsetX = 0;
240 m_offsetY = 0;
241
242 setArrangement(TQIconView::LeftToRight);
243 setAutoArrange(true);
244 setSorting(false);
245 setItemsMovable(false);
246 setResizeMode(TQIconView::Adjust);
247
248 m_thumbTip = new ThumbToolTip(this);
249
250 connect(this, TQ_SIGNAL(currentChanged(TQIconViewItem *)),
251 this, TQ_SLOT(itemClicked(TQIconViewItem *)));
252 connect(this, TQ_SIGNAL(contentsMoving(int, int)),
253 this, TQ_SLOT(slotContentsMoving(int, int)));
254}
255
256KPrThumbBar::~KPrThumbBar()
257{
258 delete m_thumbTip;
259}
260
261void KPrThumbBar::setCurrentPage( int pg )
262{
263 for ( TQIconViewItem *it = firstItem(); it; it = it->nextItem() )
264 {
265 if ( it->text().toInt() - 1 == pg ) {
266 blockSignals( true );
267 setCurrentItem( it );
268 setSelected( it, false ); // to avoid the blue "selected"-mark
269 ensureItemVisible(it);
270 refreshItems();
271 blockSignals( false );
272 return;
273 }
274 }
275}
276
277TQRect KPrThumbBar::tip(const TQPoint &pos, TQString &title)
278{
279 TQIconViewItem *item = findItem(viewportToContents(pos));
280 if (!item)
281 return TQRect(0, 0, -1, -1);
282
283 int pagenr = item->index();
284 title = m_doc->pageList().at(pagenr)->pageTitle();
285
286 TQRect r = item->pixmapRect(false);
287 r = TQRect(contentsToViewport(TQPoint(r.x(), r.y())), TQSize(r.width(), r.height()));
288 return r;
289}
290
291void KPrThumbBar::rebuildItems()
292{
293 kdDebug()<<" void KPrThumbBar::rebuildItems() beofre \n";
294 if( !isVisible())
295 return;
296 kdDebug(33001) << "KPrThumbBar::rebuildItems" << endl;
297
298 TQApplication::setOverrideCursor( TQt::waitCursor );
299
300 clear();
301 if ( m_viewMasterPage )
302 {
303 }
304 else
305 {
306 for ( unsigned int i = 0; i < m_doc->getPageNums(); i++ ) {
307 // calculate the size of the thumb
308 TQRect rect = m_doc->pageList().at(i)->getZoomPageRect( );
309
310 int w = rect.width();
311 int h = rect.height();
312 if ( w > h ) {
313 w = 130;
314 float diff = (float)rect.width() / (float)w;
315 h = (int) (rect.height() / diff);
316 if ( h > 120 ) {
317 h = 120;
318 float diff = (float)rect.height() / (float)h;
319 w = (int) (rect.width() / diff);
320 }
321 }
322 else if ( w < h ) {
323 h = 130;
324 float diff = (float)rect.height() / (float)h;
325 w = (int) (rect.width() / diff);
326 if ( w > 120 ) {
327 w = 120;
328 float diff = (float)rect.width() / (float)w;
329 h = (int) (rect.height() / diff);
330 }
331 }
332 else if ( w == h ) {
333 w = 130;
334 h = 130;
335 }
336
337 // draw an empty thumb
338 TQPixmap pix(w, h);
339 pix.fill( TQt::white );
340
341 TQPainter p(&pix);
342 p.setPen(TQt::black);
343 p.drawRect(pix.rect());
344
345 ThumbItem *item = new ThumbItem(static_cast<TQIconView *>(this), TQString::number(i+1), pix);
346 item->setUptodate( false );
347 item->setDragEnabled(false); //no dragging for now
348 }
349
350 TQTimer::singleShot( 10, this, TQ_SLOT( slotRefreshItems() ) );
351 }
352 uptodate = true;
353
354 TQApplication::restoreOverrideCursor();
355}
356
357void KPrThumbBar::refreshItems(bool offset)
358{
359 TQRect vRect = visibleRect();
360 if ( offset )
361 vRect.moveBy( m_offsetX, m_offsetY );
362 else
363 vRect.moveBy( contentsX(), contentsY() );
364
365 TQIconViewItem *it = findFirstVisibleItem( vRect );
366 while ( it )
367 {
368 kdDebug(33001) << "visible page = " << it->text().toInt() << endl;
369 if ( ! dynamic_cast<ThumbItem *>(it)->isUptodate( ) ){
370 //todo refresh picture
371 it->setPixmap( getSlideThumb( it->text().toInt() - 1 ) );
372 static_cast<ThumbItem *>(it)->setUptodate( true );
373 }
374
375 if ( it == findLastVisibleItem( vRect ) )
376 break;
377 it = it->nextItem();
378 }
379
380 m_offsetX = 0;
381 m_offsetY = 0;
382}
383
384void KPrThumbBar::updateItem( int pagenr /* 0-based */, bool sticky )
385{
386 if ( m_viewMasterPage )
387 return;
388 if ( !uptodate )
389 return;
390 int pagecnt = 0;
391 // calculate rect of visible objects
392 TQRect vRect = visibleRect();
393 vRect.moveBy( contentsX(), contentsY() );
394
395 // Find icon
396 TQIconViewItem *it = firstItem();
397 do
398 {
399 if ( it == findFirstVisibleItem( vRect ) ) {
400 do
401 {
402 if ( sticky || it->text().toInt() == pagenr + 1 ) {
403 it->setPixmap(getSlideThumb( pagecnt ));
404 static_cast<ThumbItem *>(it)->setUptodate( true );
405
406 if ( !sticky )
407 return;
408 }
409 if ( it == findLastVisibleItem( vRect ) )
410 break;
411 pagecnt++;
412 it = it->nextItem();
413 } while ( true );
414 }
415 else if ( sticky || it->text().toInt() == pagenr + 1 ) {
416 static_cast<ThumbItem *>(it)->setUptodate( false );
417 if ( !sticky )
418 return;
419 }
420 pagecnt++;
421 it = it->nextItem();
422 } while ( it );
423
424 if ( ! sticky )
425 kdWarning(33001) << "Item for page " << pagenr << " not found" << endl;
426}
427
428// add a thumb item without recreating all thumbs
429void KPrThumbBar::addItem( int pos )
430{
431 kdDebug(33001)<< "KPrThumbBar::addItem" << endl;
432 int page = 0;
433 for ( TQIconViewItem *it = firstItem(); it; it = it->nextItem() ) {
434 // find page which should move
435 // do stuff because a item can not be insert at the beginning
436 if ( pos == 0 && page == pos ){
437 ThumbItem *item = new ThumbItem(static_cast<TQIconView *>(this), it, TQString::number(2), getSlideThumb(1));
438 item->setDragEnabled(false); //no dragging for now
439 it->setPixmap(getSlideThumb( 0 ));
440 // move on to next item as we have inserted one
441 it = it->nextItem();
442 }
443 else if ( (page + 1) == pos ) {
444 ThumbItem *item = new ThumbItem(static_cast<TQIconView *>(this), it, TQString::number(pos+1), getSlideThumb(pos));
445 item->setDragEnabled(false); //no dragging for now
446 it = it->nextItem();
447 }
448 // update page numbers
449 if ( page >= pos )
450 it->setText( TQString::number(page+2) );
451 page++;
452 }
453}
454
455// moves a item without recreating all pages
456void KPrThumbBar::moveItem( int oldPos, int newPos )
457{
458 kdDebug(33001)<< "KPrThumbBar::moveItem " << oldPos << " to " << newPos << endl;
459 int page = 0;
460 TQIconViewItem *after = 0;
461 TQIconViewItem *take = 0;
462 for ( TQIconViewItem *it = firstItem(); it; it = it->nextItem() ) {
463 // find page which should move
464 if ( page == oldPos )
465 take = it;
466 // find position where page should be insert
467 // as a page can not be insert at the beginning get the first one
468 // the page to get depends on if a page is moved forward / backwards
469 if ( page == newPos )
470 after = page == 0 ? it : newPos > oldPos ? it : it->prevItem();
471 page++;
472 }
473
474 if ( ! take )
475 return;
476
477 // workaround for a bug in qt 3.1.1 insertItem dose not work.
478 // TODO remove workaround when qt 3.1.2 comes out tz
479 //takeItem( take );
480 //insertItem( take, after);
481 ThumbItem *item = new ThumbItem( static_cast<TQIconView *>(this), after, TQString::number( newPos ), *(take->pixmap()) );
482 item->setDragEnabled(false); //no dragging for now
483 delete take;
484 // update the thumbs if new pos was 0
485 // because it was insert after the first one
486 if ( newPos == 0 ) {
487 //todo do not recreate the pics
488 after->setPixmap(getSlideThumb( 0 ));
489 //take->setPixmap(getSlideThumb( 1 ));
490 item->setPixmap(getSlideThumb( 1 ));
491 }
492
493 //write the new page numbers
494 int lowPage = oldPos > newPos ? newPos : oldPos;
495 int highPage = oldPos < newPos ? newPos : oldPos;
496 page = 0;
497 for ( TQIconViewItem *it = firstItem(); it; it = it->nextItem() ) {
498 if ( page >= lowPage && page <= highPage)
499 it->setText( TQString::number(page+1) );
500 page++;
501 }
502}
503
504void KPrThumbBar::removeItem( int pos )
505{
506 kdDebug(33001)<< "KPrThumbBar::removeItem" << endl;
507 int page = 0;
508 bool change = false;
509 TQIconViewItem *itemToDelete = 0;
510
511 for ( TQIconViewItem *it = firstItem(); it; it = it->nextItem() ) {
512 if ( page == pos ) {
513 itemToDelete = it;
514 if ( it->nextItem() )
515 it = it->nextItem();
516 change = true;
517 }
518 if ( change )
519 it->setText( TQString::number( page + 1 ) );
520 page++;
521 }
522 delete itemToDelete;
523}
524
525TQPixmap KPrThumbBar::getSlideThumb(int slideNr) const
526{
527 //kdDebug(33001) << "KPrThumbBar::getSlideThumb: " << slideNr << endl;
528 TQPixmap pix( 10, 10 );
529
530 m_view->getCanvas()->drawPageInPix( pix, slideNr, 60 );
531
532 int w = pix.width();
533 int h = pix.height();
534
535 if ( w > h ) {
536 w = 130;
537 h = 120;
538 }
539 else if ( w < h ) {
540 w = 120;
541 h = 130;
542 }
543 else if ( w == h ) {
544 w = 130;
545 h = 130;
546 }
547
548 const TQImage img(pix.convertToImage().smoothScale( w, h, TQImage::ScaleMin ));
549 pix.convertFromImage(img);
550
551 // draw a frame around the thumb to show its size
552 TQPainter p(&pix);
553 p.setPen(TQt::black);
554 p.drawRect(pix.rect());
555
556 return pix;
557}
558
559void KPrThumbBar::itemClicked(TQIconViewItem *i)
560{
561 if ( !i )
562 return;
563 emit showPage( i->index() );
564}
565
566void KPrThumbBar::slotContentsMoving(int x, int y)
567{
568 m_offsetX = x;
569 m_offsetY = y;
570 kdDebug(33001) << "offset x,y = " << x << ", " << y << endl;
571 refreshItems( true );
572}
573
574void KPrThumbBar::slotRefreshItems()
575{
576 refreshItems();
577}
578
579OutlineSlideItem::OutlineSlideItem( TDEListView* parent, KPrPage* _page, bool _masterPage )
580 : TDEListViewItem( parent ), m_page( _page ), m_masterPage( _masterPage )
581{
582 setDragEnabled(true);
583 setPage( _page );
584 setPixmap( 0, KPBarIcon( "slide" ) );
585}
586
587OutlineSlideItem::OutlineSlideItem( TDEListView* parent, OutlineSlideItem * after, KPrPage* _page, bool _masterPage )
588 : TDEListViewItem( parent, after ), m_page( _page ), m_masterPage( _masterPage )
589{
590 setDragEnabled(true);
591 setPage( _page );
592 setPixmap( 0, KPBarIcon( "slide" ) );
593}
594
595void OutlineSlideItem::setPage( KPrPage* p )
596{
597 if( !p ) return;
598 m_page = p;
599 update();
600}
601
602void OutlineSlideItem::update()
603{
604 if( !m_page ) return;
605 KPrDocument *doc = m_page->kPresenterDoc();
606 updateTitle();
607
608 // add all objects
609 OutlineObjectItem *ooi = 0;
610 while ( ( ooi = dynamic_cast<OutlineObjectItem*>( this->firstChild() ) ) )
611 delete ooi;
612
613 // keep selected object
614 ooi = 0;
615
616 TQPtrListIterator<KPrObject> it( m_page->objectList() );
617
618 if ( !m_masterPage )
619 {
620 for ( ; it.current(); ++it ) {
621 OutlineObjectItem *item = new OutlineObjectItem( this, it.current() );
622 item->setDragEnabled( false );
623 if ( it.current()->isSelected() )
624 ooi = item;
625 }
626 }
627 else
628 {
629 KPrObject* header = 0;
630 KPrObject* footer = 0;
631
632 // add sticky objects, exclude header and footer
633 it = doc->masterPage()->objectList();
634 for ( ; it.current() ; ++it )
635 {
636 KPrObject* object = it.current();
637
638 if( m_page->hasHeader() && doc->isHeader( object ) )
639 header = object;
640 else if( m_page->hasFooter() && doc->isFooter( object ) )
641 footer = object;
642 else if( !doc->isHeader( object ) && !doc->isFooter( object ) ) {
643 OutlineObjectItem *item = new OutlineObjectItem( this, object );
644 if ( object->isSelected() )
645 ooi = item;
646 }
647
648 }
649
650 // add header and footer (if any)
651 if ( footer ) {
652 OutlineObjectItem *item = new OutlineObjectItem( this, footer, i18n("Footer") );
653 if ( footer->isSelected() )
654 ooi = item;
655 }
656
657 if ( header ) {
658 OutlineObjectItem *item = new OutlineObjectItem( this, header, i18n("Header") );
659 if ( header->isSelected() )
660 ooi = item;
661 }
662 }
663
664 // select selected object the page is necessary that a
665 // sticky object is selected on the active page
666 if ( ooi && doc->activePage() == m_page )
667 (ooi->listView())->setSelected( ooi, true );
668}
669
670void OutlineSlideItem::updateTitle()
671{
672 TQString title = m_page->pageTitle();
673 if ( ! m_page->isSlideSelected() )
674 title = i18n( "(%1)" ).arg( title );
675 setText( 0, title );
676}
677
678OutlineObjectItem::OutlineObjectItem( OutlineSlideItem* parent, KPrObject* _object,
679 const TQString& name )
680 : TDEListViewItem( parent ), m_object( _object )
681{
682 setObject( m_object );
683 setDragEnabled( false );
684
685 TQString objectName = name.isEmpty() ? m_object->getObjectName() : name;
686 //if( sticky ) objectName += i18n(" (Sticky)" );
687 setText( 0, objectName );
688}
689
690void OutlineObjectItem::setObject( KPrObject* object )
691{
692 if( !object ) return;
693 m_object = object;
694
695 switch ( m_object->getType() ) {
696 case OT_PICTURE:
697 setPixmap( 0, KPBarIcon( "frame_image" ) );
698 break;
699 case OT_LINE:
700 setPixmap( 0, KPBarIcon( "mini_line" ) );
701 break;
702 case OT_RECT:
703 setPixmap( 0, KPBarIcon( "mini_rect" ) );
704 break;
705 case OT_ELLIPSE:
706 setPixmap( 0, KPBarIcon( "mini_circle" ) );
707 break;
708 case OT_TEXT:
709 setPixmap( 0, KPBarIcon( "frame_text" ) );
710 break;
711 case OT_AUTOFORM:
712 setPixmap( 0, KPBarIcon( "mini_autoform" ) );
713 break;
714 case OT_CLIPART:
715 setPixmap( 0, KPBarIcon( "mini_clipart" ) );
716 break;
717 case OT_PIE:
718 setPixmap( 0, KPBarIcon( "mini_pie" ) );
719 break;
720 case OT_PART:
721 setPixmap( 0, KPBarIcon( "frame_query" ) );
722 break;
723 case OT_FREEHAND:
724 setPixmap( 0, KPBarIcon( "freehand" ) );
725 break;
726 case OT_POLYLINE:
727 setPixmap( 0, KPBarIcon( "polyline" ) );
728 break;
729 case OT_QUADRICBEZIERCURVE:
730 setPixmap( 0, KPBarIcon( "quadricbeziercurve" ) );
731 break;
732 case OT_CUBICBEZIERCURVE:
733 setPixmap( 0, KPBarIcon( "cubicbeziercurve" ) );
734 break;
735 case OT_POLYGON:
736 setPixmap( 0, KPBarIcon( "mini_polygon" ) );
737 break;
738 case OT_CLOSED_LINE: {
739 TQString name = m_object->getTypeString();
740 if ( name == i18n( "Closed Freehand" ) )
741 setPixmap( 0, KPBarIcon( "closed_freehand" ) );
742 else if ( name == i18n( "Closed Polyline" ) )
743 setPixmap( 0, KPBarIcon( "closed_polyline" ) );
744 else if ( name == i18n( "Closed Quadric Bezier Curve" ) )
745 setPixmap( 0, KPBarIcon( "closed_quadricbeziercurve" ) );
746 else if ( name == i18n( "Closed Cubic Bezier Curve" ) )
747 setPixmap( 0, KPBarIcon( "closed_cubicbeziercurve" ) );
748 } break;
749 case OT_GROUP:
750 setPixmap( 0, KPBarIcon( "group" ) );
751 break;
752 default:
753 break;
754 }
755}
756
757KPrOutline::KPrOutline( TQWidget *parent, KPrDocument *d, KPrView *v )
758 : TDEListView( parent ), KPrSideBarBase( d, v)
759{
760 rebuildItems();
761 setSorting( -1 );
762 header()->hide();
763 addColumn( i18n( "Slide" ) );
764 setSizePolicy( TQSizePolicy( TQSizePolicy::Minimum, TQSizePolicy::Expanding ) );
765
766 connect( this, TQ_SIGNAL( currentChanged( TQListViewItem * ) ), this, TQ_SLOT( itemClicked( TQListViewItem * ) ) );
767 connect( this, TQ_SIGNAL( rightButtonPressed( TQListViewItem *, const TQPoint &, int ) ),
768 this, TQ_SLOT( rightButtonPressed( TQListViewItem *, const TQPoint &, int ) ) );
769 connect( this, TQ_SIGNAL( contextMenu( TDEListView*, TQListViewItem*, const TQPoint& ) ),
770 this, TQ_SLOT( slotContextMenu( TDEListView*, TQListViewItem*, const TQPoint&) ) );
771
772 connect( this, TQ_SIGNAL( doubleClicked ( TQListViewItem * )),
773 this, TQ_SLOT(renamePageTitle()));
774 connect( this, TQ_SIGNAL( dropped( TQDropEvent*, TQListViewItem*, TQListViewItem* ) ),
775 this, TQ_SLOT( slotDropped( TQDropEvent*, TQListViewItem*, TQListViewItem* ) ));
776
777 setItemsMovable( false );
778 setDragEnabled( true );
779 setAcceptDrops( true );
780 setDropVisualizer( true );
781 setFullWidth( true );
782 this->setRootIsDecorated( true );
783}
784
785KPrOutline::~KPrOutline()
786{
787}
788
789void KPrOutline::rebuildItems()
790{
791 clear();
792 if ( m_viewMasterPage )
793 {
794 KPrPage *page=m_doc->masterPage();
795 new OutlineSlideItem( this, page, true );
796 }
797 else
798 {
799 // Rebuild all the items
800 for ( int i = m_doc->getPageNums() - 1; i >= 0; --i ) {
801 KPrPage *page=m_doc->pageList().at( i );
802 new OutlineSlideItem( this, page, false );
803 }
804 }
805}
806
807// given the page number (0-based), find associated slide item
808// returns 0 upon stupid things (e.g. invalid page number)
809OutlineSlideItem* KPrOutline::slideItem( int pageNumber )
810{
811 TQListViewItem* item = firstChild();
812 for( int index = 0; item; ++index, item = item->nextSibling() ) {
813 if( index == pageNumber )
814 return dynamic_cast<OutlineSlideItem*>( item );
815 }
816
817 return 0;
818}
819
820
821// update the KPrOutline item, the title may have changed
822void KPrOutline::updateItem( int pagenr /* 0-based */, bool sticky )
823{
824 if ( ! sticky ) {
825 OutlineSlideItem *item = slideItem( pagenr );
826 if( item ) {
827 blockSignals(true);
828 item->update();
829 blockSignals(false);
830 }
831 } else {
832 blockSignals(true);
833 for( TQListViewItem *item = this->firstChild(); item; item = item->nextSibling() )
834 dynamic_cast<OutlineSlideItem*>(item)->update();
835 blockSignals(false);
836 }
837}
838
839void KPrOutline::addItem( int pos )
840{
841 kdDebug(33001)<< "KPrOutline::addItem" << endl;
842
843 KPrPage *page=m_doc->pageList().at( pos );
844 OutlineSlideItem *item;
845 if ( pos == 0 ) {
846 item = new OutlineSlideItem( this, page,m_viewMasterPage );
847 }
848 else {
849 OutlineSlideItem *after = slideItem( pos - 1 );
850 item = new OutlineSlideItem( this, after, page,m_viewMasterPage );
851 }
852
853 item = dynamic_cast<OutlineSlideItem*>( item->nextSibling() );
854 // update title
855 for( ; item; item = dynamic_cast<OutlineSlideItem*>( item->nextSibling() ) )
856 item->updateTitle();
857}
858
859// move an KPrOutline Item so that not the hole list has to be recreated
860void KPrOutline::moveItem( int oldPos, int newPos )
861{
862 kdDebug(33001)<< "KPrOutline::moveItem " << oldPos << " to " << newPos << endl;
863
864 int lowPage = oldPos > newPos ? newPos : oldPos;
865 int highPage = oldPos < newPos ? newPos : oldPos;
866
867 OutlineSlideItem *item = dynamic_cast<OutlineSlideItem*>( firstChild() );
868 TQListViewItem *itemToMove = 0;
869 TQListViewItem *itemAfter = 0;
870
871 // moving backwards
872 if ( newPos < oldPos )
873 newPos--;
874
875 for ( int index = 0; item; ++index, item = dynamic_cast<OutlineSlideItem*>( item->nextSibling() ) )
876 {
877 if ( index == oldPos )
878 itemToMove = item;
879 if ( index == newPos )
880 itemAfter = item;
881 if ( index >= lowPage && index <= highPage )
882 item->updateTitle();
883 }
884
885 TDEListView::moveItem( itemToMove, 0, itemAfter );
886}
887
888void KPrOutline::removeItem( int pos )
889{
890 kdDebug(33001)<< "KPrOutline::removeItem" << endl;
891
892 OutlineSlideItem* item = slideItem( pos );
893 if( !item ) return;
894 OutlineSlideItem* temp = dynamic_cast<OutlineSlideItem*>(item->nextSibling());
895
896 delete item;
897
898 for ( item = temp; item; item = dynamic_cast<OutlineSlideItem*>( item->nextSibling() ) )
899 item->updateTitle();
900}
901
902void KPrOutline::itemClicked( TQListViewItem *item )
903{
904 if( !item ) return;
905
906 // check if we need to show chosen slide
907 OutlineSlideItem* slideItem = dynamic_cast<OutlineSlideItem*>(item);
908 if( slideItem )
909 {
910 KPrPage* page = slideItem->page();
911 if( !page ) return;
912 if ( !m_viewMasterPage )
913 emit showPage( m_doc->pageList().findRef( page ) );
914 }
915
916 // check if we need to show chosen object
917 OutlineObjectItem* objectItem = dynamic_cast<OutlineObjectItem*>(item);
918 if( objectItem )
919 {
920 KPrObject *object = objectItem->object();
921 if( !object ) return;
922
923 // ensure the owner slide is shown first
924 OutlineSlideItem* slideItem = dynamic_cast<OutlineSlideItem*>(objectItem->parent());
925 if( slideItem && m_doc->activePage() != slideItem->page() )
926 {
927 KPrPage* page = slideItem->page();
928 if( !page ) return;
929 if ( !m_viewMasterPage )
930 emit showPage( m_doc->pageList().findRef( page ) );
931 }
932
933 // select the object, make sure it's visible
934 m_doc->deSelectAllObj();
935 m_view->getCanvas()->selectObj( object );
936 m_view->showObjectRect( object );
937 m_doc->repaint( false );
938 }
939}
940
948void KPrOutline::slotDropped( TQDropEvent * /* e */, TQListViewItem *parent, TQListViewItem *target )
949{
950 kdDebug(33001) << "slotDropped" << endl;
951 /* slide doesn't have parent (always 0)
952 * Only slides can move at the moment, objects can't. */
953 if ( parent )
954 return;
955
956 // This code is taken from TDEListView
957 for (TQListViewItem *i = firstChild(), *iNext = 0; i != 0; i = iNext)
958 {
959 iNext = i->itemBelow();
960 if ( !i->isSelected() )
961 continue;
962
963 // don't drop an item after itself, or else
964 // it moves to the top of the list
965 if ( i == target )
966 continue;
967
968 i->setSelected( false );
969
970 // don't move the item as it is allready
971 moveItem(i, parent, target );
972
973 // Only one item can be moved
974 break;
975 }
976}
977
978// We have to overwrite this method as it checks if an item is movable
979// and we have disabled it.
980bool KPrOutline::acceptDrag( TQDropEvent* e ) const
981{
982 return acceptDrops() && (e->source()==viewport());
983}
984
985
986void KPrOutline::setCurrentPage( int pg )
987{
988 OutlineSlideItem *item = slideItem( pg );
989 if( item && ( item!=currentItem()->parent() ) )
990 {
991 blockSignals( true );
992 setCurrentItem( item );
993 setSelected( item, true );
994 ensureItemVisible( item );
995 blockSignals( false );
996 }
997}
998
999void KPrOutline::contentsDropEvent( TQDropEvent *e )
1000{
1001 disconnect( this, TQ_SIGNAL( currentChanged( TQListViewItem * ) ), this, TQ_SLOT( itemClicked( TQListViewItem * ) ) );
1002 TDEListView::contentsDropEvent( e );
1003 connect( this, TQ_SIGNAL( currentChanged( TQListViewItem * ) ), this, TQ_SLOT( itemClicked( TQListViewItem * ) ) );
1004}
1005
1006void KPrOutline::moveItem( TQListViewItem *i, TQListViewItem *, TQListViewItem *newAfter )
1007{
1008 OutlineSlideItem* srcItem = dynamic_cast<OutlineSlideItem*>( i );
1009 if ( !srcItem )
1010 return;
1011
1012 int num = m_doc->pageList().findRef( srcItem->page() );
1013
1014 int numNow = 0;
1015 if ( newAfter )
1016 {
1017 OutlineSlideItem* dstItem = dynamic_cast<OutlineSlideItem*>( newAfter );
1018 if( !dstItem )
1019 return;
1020
1021 numNow = m_doc->pageList().findRef( dstItem->page() );
1022 if ( numNow < num )
1023 numNow++;
1024 }
1025
1026 if ( num!=numNow )
1027 m_doc->movePage( num, numNow );
1028}
1029
1030void KPrOutline::rightButtonPressed( TQListViewItem *, const TQPoint &pnt, int )
1031{
1032 if ( !m_doc->isReadWrite() || m_viewMasterPage ) return;
1033
1034 TQListViewItem *item = TQListView::selectedItem();
1035 if( !item ) return;
1036
1037 OutlineSlideItem* slideItem = dynamic_cast<OutlineSlideItem*>(item);
1038
1039 if( slideItem ) {
1040 m_view->openPopupMenuSideBar(pnt);
1041 } else {
1042 OutlineObjectItem* objectItem = dynamic_cast<OutlineObjectItem*>(item);
1043 if( objectItem )
1044 {
1045 KPrObject * kpobject = objectItem->object();
1046
1047 if( !kpobject ) {
1048 return;
1049 }
1050
1051 KPrCanvas* canvas = static_cast<KPrCanvas*>(m_view->canvas());
1052 canvas->deSelectAllObj();
1053 canvas->selectObj( kpobject );
1054
1055 canvas->objectPopup( kpobject, pnt );
1056 }
1057 }
1058}
1059
1060void KPrOutline::slotContextMenu( TDEListView*, TQListViewItem* item, const TQPoint& p )
1061{
1062 rightButtonPressed( item, p, 0 );
1063}
1064
1065void KPrOutline::renamePageTitle()
1066{
1067 TQListViewItem *item = TQListView::selectedItem();
1068 if( !item || m_viewMasterPage) return;
1069
1070 OutlineSlideItem* slideItem = dynamic_cast<OutlineSlideItem*>(item);
1071 if( !slideItem ) return;
1072
1073 KPrPage* page = slideItem->page();
1074 if( !page ) return;
1075
1076 bool ok = false;
1077 TQString activeTitle = item->text( 0 );
1078
1079 TQStringList page_titles;
1080 KPrPage *it;
1081 for ( it = m_doc->pageList().first(); it; it = m_doc->pageList().next() )
1082 if ( it->pageTitle() != activeTitle )
1083 page_titles.append( it->pageTitle() );
1084
1085 KPrRenamePageValidator validator( page_titles );
1086 TQString newTitle = KInputDialog::getText( i18n("Rename Slide"),
1087 i18n("Slide title:"), activeTitle, &ok, this, 0,
1088 &validator );
1089
1090 // Have a different name ?
1091 if ( ok ) { // User pushed an OK button.
1092 if ( newTitle != activeTitle ) { // Title changed.
1093 KPrChangeTitlePageNameCommand *cmd=new KPrChangeTitlePageNameCommand( i18n("Rename Slide"),
1094 m_doc, activeTitle, newTitle.stripWhiteSpace(), page );
1095 cmd->execute();
1096 m_doc->addCommand(cmd);
1097 }
1098 }
1099}
1100
1101TQDragObject* KPrOutline::dragObject()
1102{
1103 if( !selectedItem()->dragEnabled() ) {
1104 return 0;
1105 }
1106
1107 return TDEListView::dragObject();
1108}
1109
1110#include "KPrSideBar.moc"
void objectPopup(KPrObject *object, const TQPoint &point)
Open the object popup.