You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koffice/kpresenter/KPrSideBar.cpp

1111 lines
32 KiB

/* This file is part of the KDE project
Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
Copyright (C) 2001 Lukas Tinkl <lukas@kde.org>
Copyright (C) 2002 Ariya Hidayat <ariya@kde.org>
Copyright (C) 2005 Laurent Montel <montel@kde.org>
Copyright (C) 2005 Thorsten Zachmann <zachmann@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <tqheader.h>
#include <tqtimer.h>
#include <tqpopupmenu.h>
#include <tqimage.h>
#include <tqtabwidget.h>
#include <tqtooltip.h>
#include <kwordwrap.h>
#include <tdemessagebox.h>
#include <tdelocale.h>
#include <kinputdialog.h>
#include <knotifyclient.h>
#include <kiconview.h>
#include <kdebug.h>
#include "KPrSideBar.h"
#include "KPrView.h"
#include "KPrDocument.h"
#include "KPrCanvas.h"
#include "KPrPage.h"
#include "KPrObject.h"
#include <tqapplication.h>
#include "KPrCommand.h"
#include <tqvalidator.h>
#include "KPrFreehandObject.h"
#include "KPrBezierCurveObject.h"
#include "KPrTextObject.h"
#include "KPrPolylineObject.h"
#include "KPrClosedLineObject.h"
#include "KPrGroupObject.h"
TQValidator::State KPrRenamePageValidator::validate( TQString & input, int& ) const
{
TQString str = input.stripWhiteSpace();
if ( str.isEmpty() ) // we want to allow empty titles. Empty == automatic.
return Acceptable;
if ( mStringList.find( str ) == mStringList.end() )
return Acceptable;
else
return Intermediate;
}
class ThumbToolTip : public TQToolTip
{
public:
ThumbToolTip( KPrThumbBar *parent )
: TQToolTip( parent->viewport() )
, m_thumbBar( parent )
{}
protected:
void maybeTip(const TQPoint &pos)
{
TQString title;
TQRect r( m_thumbBar->tip( pos, title ) );
if (!r.isValid())
return;
tip(r, title);
}
private:
KPrThumbBar *m_thumbBar;
};
class OutlineSlideItem: public TDEListViewItem
{
public:
OutlineSlideItem( TDEListView * parent, KPrPage* page, bool _masterPage );
OutlineSlideItem( TDEListView * parent, OutlineSlideItem *after, KPrPage* page, bool _masterPage );
KPrPage* page() const { return m_page; }
void setPage( KPrPage* p );
void update();
void updateTitle();
private:
KPrPage* m_page;
bool m_masterPage;
};
class OutlineObjectItem: public TDEListViewItem
{
public:
OutlineObjectItem( OutlineSlideItem * parent, KPrObject* object,
const TQString& name = TQString() );
KPrObject* object() const { return m_object; }
void setObject( KPrObject* o );
private:
KPrObject* m_object;
};
class ThumbItem : public TQIconViewItem
{
public:
ThumbItem( TQIconView *parent, const TQString & text, const TQPixmap & icon )
: TQIconViewItem( parent, text, icon )
{ uptodate = true; }
ThumbItem( TQIconView *parent, TQIconViewItem *after, const TQString & text, const TQPixmap & icon )
: TQIconViewItem( parent, after, text, icon )
{ uptodate = true; }
virtual bool isUptodate() { return uptodate; };
virtual void setUptodate( bool _uptodate) { uptodate = _uptodate; };
private:
bool uptodate;
};
KPrSideBar::KPrSideBar(TQWidget *parent, KPrDocument *d, KPrView *v)
:TQTabWidget(parent), m_doc(d), m_view(v)
{
setTabPosition(TQTabWidget::Top);
setTabShape(TQTabWidget::Triangular);
m_outline = new KPrOutline(this, m_doc, m_view);
addTab(m_outline, i18n("Structure of the presentation", "Outline"));
m_thb = new KPrThumbBar(this, m_doc, m_view);
addTab(m_thb,i18n("Preview"));
//TODO find a better way
connect(m_outline, TQT_SIGNAL(showPage(int)),
this, TQT_SIGNAL(showPage(int)));
connect(m_thb, TQT_SIGNAL(showPage(int)),
this, TQT_SIGNAL(showPage(int)));
connect(m_outline, TQT_SIGNAL(movePage(int,int)),
this, TQT_SIGNAL(movePage(int,int)));
connect(m_outline, TQT_SIGNAL(selectPage(int,bool)),
this, TQT_SIGNAL(selectPage(int,bool)));
connect(this, TQT_SIGNAL(currentChanged(TQWidget *)),
this, TQT_SLOT(currentChanged(TQWidget *)));
}
void KPrSideBar::currentChanged(TQWidget *tab)
{
if (tab == m_thb) {
if (!m_thb->uptodate && m_thb->isVisible())
m_thb->rebuildItems();
else
m_thb->refreshItems();
}
}
void KPrSideBar::addItem( int pos )
{
m_outline->addItem( pos );
m_thb->addItem( pos );
}
void KPrSideBar::moveItem( int oldPos, int newPos )
{
m_outline->moveItem( oldPos, newPos );
m_thb->moveItem( oldPos, newPos );
}
void KPrSideBar::removeItem( int pos )
{
m_outline->removeItem( pos );
m_thb->removeItem( pos );
}
void KPrSideBar::updateItem( KPrPage *page )
{
bool sticky = false;
int pos = 0;
if ( page == m_doc->masterPage() )
{
pos = -1;
sticky = true;
}
else
{
pos = m_doc->pageList().findRef( page );
}
m_outline->updateItem( pos, sticky );
m_thb->updateItem( pos, sticky );
}
void KPrSideBar::setViewMasterPage( bool _masterPage )
{
m_outline->setViewMasterPage( _masterPage );
m_thb->setViewMasterPage( _masterPage );
m_outline->rebuildItems();
m_thb->rebuildItems();
}
KPrSideBarBase::KPrSideBarBase(KPrDocument *_doc, KPrView *_view)
: m_doc( _doc ), m_view( _view ), m_viewMasterPage( false )
{
}
void KPrSideBarBase::setViewMasterPage( bool _b )
{
m_viewMasterPage = _b;
}
KPrThumbBar::KPrThumbBar(TQWidget *parent, KPrDocument *d, KPrView *v)
:TDEIconView(parent), KPrSideBarBase( d,v)
{
uptodate = false;
m_offsetX = 0;
m_offsetY = 0;
setArrangement(TQIconView::LeftToRight);
setAutoArrange(true);
setSorting(false);
setItemsMovable(false);
setResizeMode(TQIconView::Adjust);
m_thumbTip = new ThumbToolTip(this);
connect(this, TQT_SIGNAL(currentChanged(TQIconViewItem *)),
this, TQT_SLOT(itemClicked(TQIconViewItem *)));
connect(this, TQT_SIGNAL(contentsMoving(int, int)),
this, TQT_SLOT(slotContentsMoving(int, int)));
}
KPrThumbBar::~KPrThumbBar()
{
delete m_thumbTip;
}
void KPrThumbBar::setCurrentPage( int pg )
{
for ( TQIconViewItem *it = firstItem(); it; it = it->nextItem() )
{
if ( it->text().toInt() - 1 == pg ) {
blockSignals( true );
setCurrentItem( it );
setSelected( it, FALSE ); // to avoid the blue "selected"-mark
ensureItemVisible(it);
refreshItems();
blockSignals( false );
return;
}
}
}
TQRect KPrThumbBar::tip(const TQPoint &pos, TQString &title)
{
TQIconViewItem *item = findItem(viewportToContents(pos));
if (!item)
return TQRect(0, 0, -1, -1);
int pagenr = item->index();
title = m_doc->pageList().at(pagenr)->pageTitle();
TQRect r = item->pixmapRect(FALSE);
r = TQRect(contentsToViewport(TQPoint(r.x(), r.y())), TQSize(r.width(), r.height()));
return r;
}
void KPrThumbBar::rebuildItems()
{
kdDebug()<<" void KPrThumbBar::rebuildItems() beofre \n";
if( !isVisible())
return;
kdDebug(33001) << "KPrThumbBar::rebuildItems" << endl;
TQApplication::setOverrideCursor( TQt::waitCursor );
clear();
if ( m_viewMasterPage )
{
}
else
{
for ( unsigned int i = 0; i < m_doc->getPageNums(); i++ ) {
// calculate the size of the thumb
TQRect rect = m_doc->pageList().at(i)->getZoomPageRect( );
int w = rect.width();
int h = rect.height();
if ( w > h ) {
w = 130;
float diff = (float)rect.width() / (float)w;
h = (int) (rect.height() / diff);
if ( h > 120 ) {
h = 120;
float diff = (float)rect.height() / (float)h;
w = (int) (rect.width() / diff);
}
}
else if ( w < h ) {
h = 130;
float diff = (float)rect.height() / (float)h;
w = (int) (rect.width() / diff);
if ( w > 120 ) {
w = 120;
float diff = (float)rect.width() / (float)w;
h = (int) (rect.height() / diff);
}
}
else if ( w == h ) {
w = 130;
h = 130;
}
// draw an empty thumb
TQPixmap pix(w, h);
pix.fill( TQt::white );
TQPainter p(&pix);
p.setPen(TQt::black);
p.drawRect(pix.rect());
ThumbItem *item = new ThumbItem(static_cast<TQIconView *>(this), TQString::number(i+1), pix);
item->setUptodate( false );
item->setDragEnabled(false); //no dragging for now
}
TQTimer::singleShot( 10, this, TQT_SLOT( slotRefreshItems() ) );
}
uptodate = true;
TQApplication::restoreOverrideCursor();
}
void KPrThumbBar::refreshItems(bool offset)
{
TQRect vRect = visibleRect();
if ( offset )
vRect.moveBy( m_offsetX, m_offsetY );
else
vRect.moveBy( contentsX(), contentsY() );
TQIconViewItem *it = findFirstVisibleItem( vRect );
while ( it )
{
kdDebug(33001) << "visible page = " << it->text().toInt() << endl;
if ( ! dynamic_cast<ThumbItem *>(it)->isUptodate( ) ){
//todo refresh picture
it->setPixmap( getSlideThumb( it->text().toInt() - 1 ) );
static_cast<ThumbItem *>(it)->setUptodate( true );
}
if ( it == findLastVisibleItem( vRect ) )
break;
it = it->nextItem();
}
m_offsetX = 0;
m_offsetY = 0;
}
void KPrThumbBar::updateItem( int pagenr /* 0-based */, bool sticky )
{
if ( m_viewMasterPage )
return;
if ( !uptodate )
return;
int pagecnt = 0;
// calculate rect of visible objects
TQRect vRect = visibleRect();
vRect.moveBy( contentsX(), contentsY() );
// Find icon
TQIconViewItem *it = firstItem();
do
{
if ( it == findFirstVisibleItem( vRect ) ) {
do
{
if ( sticky || it->text().toInt() == pagenr + 1 ) {
it->setPixmap(getSlideThumb( pagecnt ));
static_cast<ThumbItem *>(it)->setUptodate( true );
if ( !sticky )
return;
}
if ( it == findLastVisibleItem( vRect ) )
break;
pagecnt++;
it = it->nextItem();
} while ( true );
}
else if ( sticky || it->text().toInt() == pagenr + 1 ) {
static_cast<ThumbItem *>(it)->setUptodate( false );
if ( !sticky )
return;
}
pagecnt++;
it = it->nextItem();
} while ( it );
if ( ! sticky )
kdWarning(33001) << "Item for page " << pagenr << " not found" << endl;
}
// add a thumb item without recreating all thumbs
void KPrThumbBar::addItem( int pos )
{
kdDebug(33001)<< "KPrThumbBar::addItem" << endl;
int page = 0;
for ( TQIconViewItem *it = firstItem(); it; it = it->nextItem() ) {
// find page which should move
// do stuff because a item can not be insert at the beginning
if ( pos == 0 && page == pos ){
ThumbItem *item = new ThumbItem(static_cast<TQIconView *>(this), it, TQString::number(2), getSlideThumb(1));
item->setDragEnabled(false); //no dragging for now
it->setPixmap(getSlideThumb( 0 ));
// move on to next item as we have inserted one
it = it->nextItem();
}
else if ( (page + 1) == pos ) {
ThumbItem *item = new ThumbItem(static_cast<TQIconView *>(this), it, TQString::number(pos+1), getSlideThumb(pos));
item->setDragEnabled(false); //no dragging for now
it = it->nextItem();
}
// update page numbers
if ( page >= pos )
it->setText( TQString::number(page+2) );
page++;
}
}
// moves a item without recreating all pages
void KPrThumbBar::moveItem( int oldPos, int newPos )
{
kdDebug(33001)<< "KPrThumbBar::moveItem " << oldPos << " to " << newPos << endl;
int page = 0;
TQIconViewItem *after = 0;
TQIconViewItem *take = 0;
for ( TQIconViewItem *it = firstItem(); it; it = it->nextItem() ) {
// find page which should move
if ( page == oldPos )
take = it;
// find position where page should be insert
// as a page can not be insert at the beginning get the first one
// the page to get depends on if a page is moved forward / backwards
if ( page == newPos )
after = page == 0 ? it : newPos > oldPos ? it : it->prevItem();
page++;
}
if ( ! take )
return;
// workaround for a bug in qt 3.1.1 insertItem dose not work.
// TODO remove workaround when qt 3.1.2 comes out tz
//takeItem( take );
//insertItem( take, after);
ThumbItem *item = new ThumbItem( static_cast<TQIconView *>(this), after, TQString::number( newPos ), *(take->pixmap()) );
item->setDragEnabled(false); //no dragging for now
delete take;
// update the thumbs if new pos was 0
// because it was insert after the first one
if ( newPos == 0 ) {
//todo do not recreate the pics
after->setPixmap(getSlideThumb( 0 ));
//take->setPixmap(getSlideThumb( 1 ));
item->setPixmap(getSlideThumb( 1 ));
}
//write the new page numbers
int lowPage = oldPos > newPos ? newPos : oldPos;
int highPage = oldPos < newPos ? newPos : oldPos;
page = 0;
for ( TQIconViewItem *it = firstItem(); it; it = it->nextItem() ) {
if ( page >= lowPage && page <= highPage)
it->setText( TQString::number(page+1) );
page++;
}
}
void KPrThumbBar::removeItem( int pos )
{
kdDebug(33001)<< "KPrThumbBar::removeItem" << endl;
int page = 0;
bool change = false;
TQIconViewItem *itemToDelete = 0;
for ( TQIconViewItem *it = firstItem(); it; it = it->nextItem() ) {
if ( page == pos ) {
itemToDelete = it;
if ( it->nextItem() )
it = it->nextItem();
change = true;
}
if ( change )
it->setText( TQString::number( page + 1 ) );
page++;
}
delete itemToDelete;
}
TQPixmap KPrThumbBar::getSlideThumb(int slideNr) const
{
//kdDebug(33001) << "KPrThumbBar::getSlideThumb: " << slideNr << endl;
TQPixmap pix( 10, 10 );
m_view->getCanvas()->drawPageInPix( pix, slideNr, 60 );
int w = pix.width();
int h = pix.height();
if ( w > h ) {
w = 130;
h = 120;
}
else if ( w < h ) {
w = 120;
h = 130;
}
else if ( w == h ) {
w = 130;
h = 130;
}
const TQImage img(pix.convertToImage().smoothScale( w, h, TQImage::ScaleMin ));
pix.convertFromImage(img);
// draw a frame around the thumb to show its size
TQPainter p(&pix);
p.setPen(TQt::black);
p.drawRect(pix.rect());
return pix;
}
void KPrThumbBar::itemClicked(TQIconViewItem *i)
{
if ( !i )
return;
emit showPage( i->index() );
}
void KPrThumbBar::slotContentsMoving(int x, int y)
{
m_offsetX = x;
m_offsetY = y;
kdDebug(33001) << "offset x,y = " << x << ", " << y << endl;
refreshItems( true );
}
void KPrThumbBar::slotRefreshItems()
{
refreshItems();
}
OutlineSlideItem::OutlineSlideItem( TDEListView* parent, KPrPage* _page, bool _masterPage )
: TDEListViewItem( parent ), m_page( _page ), m_masterPage( _masterPage )
{
setDragEnabled(true);
setPage( _page );
setPixmap( 0, KPBarIcon( "slide" ) );
}
OutlineSlideItem::OutlineSlideItem( TDEListView* parent, OutlineSlideItem * after, KPrPage* _page, bool _masterPage )
: TDEListViewItem( parent, after ), m_page( _page ), m_masterPage( _masterPage )
{
setDragEnabled(true);
setPage( _page );
setPixmap( 0, KPBarIcon( "slide" ) );
}
void OutlineSlideItem::setPage( KPrPage* p )
{
if( !p ) return;
m_page = p;
update();
}
void OutlineSlideItem::update()
{
if( !m_page ) return;
KPrDocument *doc = m_page->kPresenterDoc();
updateTitle();
// add all objects
OutlineObjectItem *ooi = 0;
while ( ( ooi = dynamic_cast<OutlineObjectItem*>( this->firstChild() ) ) )
delete ooi;
// keep selected object
ooi = 0;
TQPtrListIterator<KPrObject> it( m_page->objectList() );
if ( !m_masterPage )
{
for ( ; it.current(); ++it ) {
OutlineObjectItem *item = new OutlineObjectItem( this, it.current() );
item->setDragEnabled( false );
if ( it.current()->isSelected() )
ooi = item;
}
}
else
{
KPrObject* header = 0;
KPrObject* footer = 0;
// add sticky objects, exclude header and footer
it = doc->masterPage()->objectList();
for ( ; it.current() ; ++it )
{
KPrObject* object = it.current();
if( m_page->hasHeader() && doc->isHeader( object ) )
header = object;
else if( m_page->hasFooter() && doc->isFooter( object ) )
footer = object;
else if( !doc->isHeader( object ) && !doc->isFooter( object ) ) {
OutlineObjectItem *item = new OutlineObjectItem( this, object );
if ( object->isSelected() )
ooi = item;
}
}
// add header and footer (if any)
if ( footer ) {
OutlineObjectItem *item = new OutlineObjectItem( this, footer, i18n("Footer") );
if ( footer->isSelected() )
ooi = item;
}
if ( header ) {
OutlineObjectItem *item = new OutlineObjectItem( this, header, i18n("Header") );
if ( header->isSelected() )
ooi = item;
}
}
// select selected object the page is necessary that a
// sticky object is selected on the active page
if ( ooi && doc->activePage() == m_page )
(ooi->listView())->setSelected( ooi, true );
}
void OutlineSlideItem::updateTitle()
{
TQString title = m_page->pageTitle();
if ( ! m_page->isSlideSelected() )
title = i18n( "(%1)" ).arg( title );
setText( 0, title );
}
OutlineObjectItem::OutlineObjectItem( OutlineSlideItem* parent, KPrObject* _object,
const TQString& name )
: TDEListViewItem( parent ), m_object( _object )
{
setObject( m_object );
setDragEnabled( false );
TQString objectName = name.isEmpty() ? m_object->getObjectName() : name;
//if( sticky ) objectName += i18n(" (Sticky)" );
setText( 0, objectName );
}
void OutlineObjectItem::setObject( KPrObject* object )
{
if( !object ) return;
m_object = object;
switch ( m_object->getType() ) {
case OT_PICTURE:
setPixmap( 0, KPBarIcon( "frame_image" ) );
break;
case OT_LINE:
setPixmap( 0, KPBarIcon( "mini_line" ) );
break;
case OT_RECT:
setPixmap( 0, KPBarIcon( "mini_rect" ) );
break;
case OT_ELLIPSE:
setPixmap( 0, KPBarIcon( "mini_circle" ) );
break;
case OT_TEXT:
setPixmap( 0, KPBarIcon( "frame_text" ) );
break;
case OT_AUTOFORM:
setPixmap( 0, KPBarIcon( "mini_autoform" ) );
break;
case OT_CLIPART:
setPixmap( 0, KPBarIcon( "mini_clipart" ) );
break;
case OT_PIE:
setPixmap( 0, KPBarIcon( "mini_pie" ) );
break;
case OT_PART:
setPixmap( 0, KPBarIcon( "frame_query" ) );
break;
case OT_FREEHAND:
setPixmap( 0, KPBarIcon( "freehand" ) );
break;
case OT_POLYLINE:
setPixmap( 0, KPBarIcon( "polyline" ) );
break;
case OT_QUADRICBEZIERCURVE:
setPixmap( 0, KPBarIcon( "quadricbeziercurve" ) );
break;
case OT_CUBICBEZIERCURVE:
setPixmap( 0, KPBarIcon( "cubicbeziercurve" ) );
break;
case OT_POLYGON:
setPixmap( 0, KPBarIcon( "mini_polygon" ) );
break;
case OT_CLOSED_LINE: {
TQString name = m_object->getTypeString();
if ( name == i18n( "Closed Freehand" ) )
setPixmap( 0, KPBarIcon( "closed_freehand" ) );
else if ( name == i18n( "Closed Polyline" ) )
setPixmap( 0, KPBarIcon( "closed_polyline" ) );
else if ( name == i18n( "Closed Quadric Bezier Curve" ) )
setPixmap( 0, KPBarIcon( "closed_quadricbeziercurve" ) );
else if ( name == i18n( "Closed Cubic Bezier Curve" ) )
setPixmap( 0, KPBarIcon( "closed_cubicbeziercurve" ) );
} break;
case OT_GROUP:
setPixmap( 0, KPBarIcon( "group" ) );
break;
default:
break;
}
}
KPrOutline::KPrOutline( TQWidget *parent, KPrDocument *d, KPrView *v )
: TDEListView( parent ), KPrSideBarBase( d, v)
{
rebuildItems();
setSorting( -1 );
header()->hide();
addColumn( i18n( "Slide" ) );
setSizePolicy( TQSizePolicy( TQSizePolicy::Minimum, TQSizePolicy::Expanding ) );
connect( this, TQT_SIGNAL( currentChanged( TQListViewItem * ) ), this, TQT_SLOT( itemClicked( TQListViewItem * ) ) );
connect( this, TQT_SIGNAL( rightButtonPressed( TQListViewItem *, const TQPoint &, int ) ),
this, TQT_SLOT( rightButtonPressed( TQListViewItem *, const TQPoint &, int ) ) );
connect( this, TQT_SIGNAL( contextMenu( TDEListView*, TQListViewItem*, const TQPoint& ) ),
this, TQT_SLOT( slotContextMenu( TDEListView*, TQListViewItem*, const TQPoint&) ) );
connect( this, TQT_SIGNAL( doubleClicked ( TQListViewItem * )),
this, TQT_SLOT(renamePageTitle()));
connect( this, TQT_SIGNAL( dropped( TQDropEvent*, TQListViewItem*, TQListViewItem* ) ),
this, TQT_SLOT( slotDropped( TQDropEvent*, TQListViewItem*, TQListViewItem* ) ));
setItemsMovable( false );
setDragEnabled( true );
setAcceptDrops( true );
setDropVisualizer( true );
setFullWidth( true );
this->setRootIsDecorated( true );
}
KPrOutline::~KPrOutline()
{
}
void KPrOutline::rebuildItems()
{
clear();
if ( m_viewMasterPage )
{
KPrPage *page=m_doc->masterPage();
new OutlineSlideItem( this, page, true );
}
else
{
// Rebuild all the items
for ( int i = m_doc->getPageNums() - 1; i >= 0; --i ) {
KPrPage *page=m_doc->pageList().at( i );
new OutlineSlideItem( this, page, false );
}
}
}
// given the page number (0-based), find associated slide item
// returns 0 upon stupid things (e.g. invalid page number)
OutlineSlideItem* KPrOutline::slideItem( int pageNumber )
{
TQListViewItem* item = firstChild();
for( int index = 0; item; ++index, item = item->nextSibling() ) {
if( index == pageNumber )
return dynamic_cast<OutlineSlideItem*>( item );
}
return 0;
}
// update the KPrOutline item, the title may have changed
void KPrOutline::updateItem( int pagenr /* 0-based */, bool sticky )
{
if ( ! sticky ) {
OutlineSlideItem *item = slideItem( pagenr );
if( item ) {
blockSignals(true);
item->update();
blockSignals(false);
}
} else {
blockSignals(true);
for( TQListViewItem *item = this->firstChild(); item; item = item->nextSibling() )
dynamic_cast<OutlineSlideItem*>(item)->update();
blockSignals(false);
}
}
void KPrOutline::addItem( int pos )
{
kdDebug(33001)<< "KPrOutline::addItem" << endl;
KPrPage *page=m_doc->pageList().at( pos );
OutlineSlideItem *item;
if ( pos == 0 ) {
item = new OutlineSlideItem( this, page,m_viewMasterPage );
}
else {
OutlineSlideItem *after = slideItem( pos - 1 );
item = new OutlineSlideItem( this, after, page,m_viewMasterPage );
}
item = dynamic_cast<OutlineSlideItem*>( item->nextSibling() );
// update title
for( ; item; item = dynamic_cast<OutlineSlideItem*>( item->nextSibling() ) )
item->updateTitle();
}
// move an KPrOutline Item so that not the hole list has to be recreated
void KPrOutline::moveItem( int oldPos, int newPos )
{
kdDebug(33001)<< "KPrOutline::moveItem " << oldPos << " to " << newPos << endl;
int lowPage = oldPos > newPos ? newPos : oldPos;
int highPage = oldPos < newPos ? newPos : oldPos;
OutlineSlideItem *item = dynamic_cast<OutlineSlideItem*>( firstChild() );
TQListViewItem *itemToMove = 0;
TQListViewItem *itemAfter = 0;
// moving backwards
if ( newPos < oldPos )
newPos--;
for ( int index = 0; item; ++index, item = dynamic_cast<OutlineSlideItem*>( item->nextSibling() ) )
{
if ( index == oldPos )
itemToMove = item;
if ( index == newPos )
itemAfter = item;
if ( index >= lowPage && index <= highPage )
item->updateTitle();
}
TDEListView::moveItem( itemToMove, 0, itemAfter );
}
void KPrOutline::removeItem( int pos )
{
kdDebug(33001)<< "KPrOutline::removeItem" << endl;
OutlineSlideItem* item = slideItem( pos );
if( !item ) return;
OutlineSlideItem* temp = dynamic_cast<OutlineSlideItem*>(item->nextSibling());
delete item;
for ( item = temp; item; item = dynamic_cast<OutlineSlideItem*>( item->nextSibling() ) )
item->updateTitle();
}
void KPrOutline::itemClicked( TQListViewItem *item )
{
if( !item ) return;
// check if we need to show chosen slide
OutlineSlideItem* slideItem = dynamic_cast<OutlineSlideItem*>(item);
if( slideItem )
{
KPrPage* page = slideItem->page();
if( !page ) return;
if ( !m_viewMasterPage )
emit showPage( m_doc->pageList().findRef( page ) );
}
// check if we need to show chosen object
OutlineObjectItem* objectItem = dynamic_cast<OutlineObjectItem*>(item);
if( objectItem )
{
KPrObject *object = objectItem->object();
if( !object ) return;
// ensure the owner slide is shown first
OutlineSlideItem* slideItem = dynamic_cast<OutlineSlideItem*>(objectItem->parent());
if( slideItem && m_doc->activePage() != slideItem->page() )
{
KPrPage* page = slideItem->page();
if( !page ) return;
if ( !m_viewMasterPage )
emit showPage( m_doc->pageList().findRef( page ) );
}
// select the object, make sure it's visible
m_doc->deSelectAllObj();
m_view->getCanvas()->selectObj( object );
m_view->showObjectRect( object );
m_doc->repaint( false );
}
}
/**
* The listview no longer moves the item by itself. It just calls m_doc->movePage
* which then moves the item. At the moment the method only works as long as
* only one object is moves.
* When an item is about to move (using drag-and-drop), it makes shure that
* it's not moved right after an object.
*/
void KPrOutline::slotDropped( TQDropEvent * /* e */, TQListViewItem *parent, TQListViewItem *target )
{
kdDebug(33001) << "slotDropped" << endl;
/* slide doesn't have parent (always 0)
* Only slides can move at the moment, objects can't. */
if ( parent )
return;
// This code is taken from TDEListView
for (TQListViewItem *i = firstChild(), *iNext = 0; i != 0; i = iNext)
{
iNext = i->itemBelow();
if ( !i->isSelected() )
continue;
// don't drop an item after itself, or else
// it moves to the top of the list
if ( i == target )
continue;
i->setSelected( false );
// don't move the item as it is allready
moveItem(i, parent, target );
// Only one item can be moved
break;
}
}
// We have to overwrite this method as it checks if an item is movable
// and we have disabled it.
bool KPrOutline::acceptDrag( TQDropEvent* e ) const
{
return acceptDrops() && (e->source()==viewport());
}
void KPrOutline::setCurrentPage( int pg )
{
OutlineSlideItem *item = slideItem( pg );
if( item && ( item!=currentItem()->parent() ) )
{
blockSignals( true );
setCurrentItem( item );
setSelected( item, true );
ensureItemVisible( item );
blockSignals( false );
}
}
void KPrOutline::contentsDropEvent( TQDropEvent *e )
{
disconnect( this, TQT_SIGNAL( currentChanged( TQListViewItem * ) ), this, TQT_SLOT( itemClicked( TQListViewItem * ) ) );
TDEListView::contentsDropEvent( e );
connect( this, TQT_SIGNAL( currentChanged( TQListViewItem * ) ), this, TQT_SLOT( itemClicked( TQListViewItem * ) ) );
}
void KPrOutline::moveItem( TQListViewItem *i, TQListViewItem *, TQListViewItem *newAfter )
{
OutlineSlideItem* srcItem = dynamic_cast<OutlineSlideItem*>( i );
if ( !srcItem )
return;
int num = m_doc->pageList().findRef( srcItem->page() );
int numNow = 0;
if ( newAfter )
{
OutlineSlideItem* dstItem = dynamic_cast<OutlineSlideItem*>( newAfter );
if( !dstItem )
return;
numNow = m_doc->pageList().findRef( dstItem->page() );
if ( numNow < num )
numNow++;
}
if ( num!=numNow )
m_doc->movePage( num, numNow );
}
void KPrOutline::rightButtonPressed( TQListViewItem *, const TQPoint &pnt, int )
{
if ( !m_doc->isReadWrite() || m_viewMasterPage ) return;
TQListViewItem *item = TQListView::selectedItem();
if( !item ) return;
OutlineSlideItem* slideItem = dynamic_cast<OutlineSlideItem*>(item);
if( slideItem ) {
m_view->openPopupMenuSideBar(pnt);
} else {
OutlineObjectItem* objectItem = dynamic_cast<OutlineObjectItem*>(item);
if( objectItem )
{
KPrObject * kpobject = objectItem->object();
if( !kpobject ) {
return;
}
KPrCanvas* canvas = static_cast<KPrCanvas*>(m_view->canvas());
canvas->deSelectAllObj();
canvas->selectObj( kpobject );
canvas->objectPopup( kpobject, pnt );
}
}
}
void KPrOutline::slotContextMenu( TDEListView*, TQListViewItem* item, const TQPoint& p )
{
rightButtonPressed( item, p, 0 );
}
void KPrOutline::renamePageTitle()
{
TQListViewItem *item = TQListView::selectedItem();
if( !item || m_viewMasterPage) return;
OutlineSlideItem* slideItem = dynamic_cast<OutlineSlideItem*>(item);
if( !slideItem ) return;
KPrPage* page = slideItem->page();
if( !page ) return;
bool ok = false;
TQString activeTitle = item->text( 0 );
TQStringList page_titles;
KPrPage *it;
for ( it = m_doc->pageList().first(); it; it = m_doc->pageList().next() )
if ( it->pageTitle() != activeTitle )
page_titles.append( it->pageTitle() );
KPrRenamePageValidator validator( page_titles );
TQString newTitle = KInputDialog::getText( i18n("Rename Slide"),
i18n("Slide title:"), activeTitle, &ok, this, 0,
&validator );
// Have a different name ?
if ( ok ) { // User pushed an OK button.
if ( newTitle != activeTitle ) { // Title changed.
KPrChangeTitlePageNameCommand *cmd=new KPrChangeTitlePageNameCommand( i18n("Rename Slide"),
m_doc, activeTitle, newTitle.stripWhiteSpace(), page );
cmd->execute();
m_doc->addCommand(cmd);
}
}
}
TQDragObject* KPrOutline::dragObject()
{
if( !selectedItem()->dragEnabled() ) {
return 0;
}
return TDEListView::dragObject();
}
#include "KPrSideBar.moc"