diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
commit | 8362bf63dea22bbf6736609b0f49c152f975eb63 (patch) | |
tree | 0eea3928e39e50fae91d4e68b21b1e6cbae25604 /koshell | |
download | koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip |
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'koshell')
-rw-r--r-- | koshell/AUTHORS | 3 | ||||
-rw-r--r-- | koshell/Makefile.am | 25 | ||||
-rw-r--r-- | koshell/TODO | 17 | ||||
-rw-r--r-- | koshell/hi128-app-koshell.png | bin | 0 -> 10870 bytes | |||
-rw-r--r-- | koshell/hi16-app-koshell.png | bin | 0 -> 844 bytes | |||
-rw-r--r-- | koshell/hi22-app-koshell.png | bin | 0 -> 1212 bytes | |||
-rw-r--r-- | koshell/hi32-app-koshell.png | bin | 0 -> 1940 bytes | |||
-rw-r--r-- | koshell/hi48-app-koshell.png | bin | 0 -> 3160 bytes | |||
-rw-r--r-- | koshell/hi64-app-koshell.png | bin | 0 -> 4498 bytes | |||
-rw-r--r-- | koshell/hisc-app-koshell.svgz | bin | 0 -> 2402 bytes | |||
-rw-r--r-- | koshell/iconsidepane.cpp | 595 | ||||
-rw-r--r-- | koshell/iconsidepane.h | 213 | ||||
-rw-r--r-- | koshell/koshell.desktop | 135 | ||||
-rw-r--r-- | koshell/koshell.kcfg | 18 | ||||
-rw-r--r-- | koshell/koshell_main.cc | 90 | ||||
-rw-r--r-- | koshell/koshell_shell.cc | 739 | ||||
-rw-r--r-- | koshell/koshell_shell.h | 148 | ||||
-rw-r--r-- | koshell/koshellsettings.kcfgc | 4 | ||||
-rw-r--r-- | koshell/koshellui.rc | 14 |
19 files changed, 2001 insertions, 0 deletions
diff --git a/koshell/AUTHORS b/koshell/AUTHORS new file mode 100644 index 00000000..1c38cf54 --- /dev/null +++ b/koshell/AUTHORS @@ -0,0 +1,3 @@ +Torben Weis <weis@kde.org> +Simon Hausmann <hausmann@kde.org> +David Faure <faure@kde.org> diff --git a/koshell/Makefile.am b/koshell/Makefile.am new file mode 100644 index 00000000..e6dceac4 --- /dev/null +++ b/koshell/Makefile.am @@ -0,0 +1,25 @@ + +INCLUDES = $(KOFFICE_INCLUDES) $(all_includes) + +## The kdeinit loadable module and executable +lib_LTLIBRARIES = +kdeinit_LTLIBRARIES = koshell.la +bin_PROGRAMS = +koshell_la_SOURCES = koshell_main.cc koshell_shell.cc iconsidepane.cpp koshellsettings.kcfgc +koshell_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) +koshell_la_LIBADD = $(LIB_KOFFICEUI) +kde_kcfg_DATA = koshell.kcfg + +METASOURCES = AUTO + +KDE_ICON=AUTO + +rcdir = $(kde_datadir)/koshell +rc_DATA = koshellui.rc + +xdg_apps_DATA = koshell.desktop + +messages: rc.cpp + $(XGETTEXT) rc.cpp *.cc *.cpp -o $(podir)/koshell.pot + +include $(top_srcdir)/admin/Doxyfile.am diff --git a/koshell/TODO b/koshell/TODO new file mode 100644 index 00000000..4ddc8c80 --- /dev/null +++ b/koshell/TODO @@ -0,0 +1,17 @@ +Plans for KoKoolBar : splitter mode + +KoKoolBarGroup : + Change = Button always at the top, in splitter mode + +KoKoolBarBox : widget containing the items + (previously: 'of the active group'). + +KoKoolBar : holds a QSplitter and two instances of KoKoolBarBox instead of one. + + It should have +>an indicator which document is the current one, it should make keypresses +>visible like QIconView does, it should allow renaming of documents and it +>should allow Drag and Drop :) + +-> use QIconView + diff --git a/koshell/hi128-app-koshell.png b/koshell/hi128-app-koshell.png Binary files differnew file mode 100644 index 00000000..c920262f --- /dev/null +++ b/koshell/hi128-app-koshell.png diff --git a/koshell/hi16-app-koshell.png b/koshell/hi16-app-koshell.png Binary files differnew file mode 100644 index 00000000..381e6305 --- /dev/null +++ b/koshell/hi16-app-koshell.png diff --git a/koshell/hi22-app-koshell.png b/koshell/hi22-app-koshell.png Binary files differnew file mode 100644 index 00000000..499a69a7 --- /dev/null +++ b/koshell/hi22-app-koshell.png diff --git a/koshell/hi32-app-koshell.png b/koshell/hi32-app-koshell.png Binary files differnew file mode 100644 index 00000000..47d0eb3e --- /dev/null +++ b/koshell/hi32-app-koshell.png diff --git a/koshell/hi48-app-koshell.png b/koshell/hi48-app-koshell.png Binary files differnew file mode 100644 index 00000000..9735c565 --- /dev/null +++ b/koshell/hi48-app-koshell.png diff --git a/koshell/hi64-app-koshell.png b/koshell/hi64-app-koshell.png Binary files differnew file mode 100644 index 00000000..f9e90d88 --- /dev/null +++ b/koshell/hi64-app-koshell.png diff --git a/koshell/hisc-app-koshell.svgz b/koshell/hisc-app-koshell.svgz Binary files differnew file mode 100644 index 00000000..4a2240cb --- /dev/null +++ b/koshell/hisc-app-koshell.svgz diff --git a/koshell/iconsidepane.cpp b/koshell/iconsidepane.cpp new file mode 100644 index 00000000..8698f9a0 --- /dev/null +++ b/koshell/iconsidepane.cpp @@ -0,0 +1,595 @@ +/* + This file is part of KDE KOffice project. + + Copyright (C) 2003 Cornelius Schumacher <schumacher@kde.org> + Copyright (C) 2005 Fredrik Edemar <f_edemar@linux.se> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include <qbitmap.h> +#include <qcursor.h> +#include <qdrawutil.h> +#include <qfontmetrics.h> +#include <qframe.h> +#include <qlabel.h> +#include <qobjectlist.h> +#include <qpainter.h> +#include <qptrlist.h> +#include <qstyle.h> +#include <qtooltip.h> +#include <qwidgetstack.h> + + +#include <kapplication.h> +#include <kdebug.h> +#include <kdialog.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kpopupmenu.h> +#include <kpushbutton.h> + +#include "iconsidepane.h" + +EntryItem::EntryItem( Navigator *parent, int _id, const QString &_text, const QString & _pix ) + : QListBoxItem( parent ), + mPixmapName(_pix), + mId(_id), + mHasHover( false ), + mPaintActive( false ) +{ + reloadPixmap(); + setCustomHighlighting( true ); + setText( _text ); +} + +EntryItem::~EntryItem() +{ +} + +void EntryItem::setNewText(const QString &_text) +{ + setText( _text ); +} + +void EntryItem::reloadPixmap() +{ + int size = (int)navigator()->viewMode(); + if ( size != 0 ) + mPixmap = KGlobal::iconLoader()->loadIcon( mPixmapName, KIcon::Desktop, size ); + else + mPixmap = QPixmap(); +} + +Navigator* EntryItem::navigator() const +{ + return static_cast<Navigator*>( listBox() ); +} + +int EntryItem::width( const QListBox *listbox ) const +{ + int w = 0; + if( navigator()->showIcons() ) { + w = navigator()->viewMode(); + if ( navigator()->viewMode() == SmallIcons ) + w += 4; + } + if( navigator()->showText() ) { + if ( navigator()->viewMode() == SmallIcons ) + w += listbox->fontMetrics().width( text() ); + else + w = QMAX( w, listbox->fontMetrics().width( text() ) ); + } + return w + ( KDialog::marginHint() * 2 ); +} + +int EntryItem::height( const QListBox *listbox ) const +{ + int h = 0; + if ( navigator()->showIcons() ) + h = (int)navigator()->viewMode() + 4; + if ( navigator()->showText() ) { + if ( navigator()->viewMode() == SmallIcons || !navigator()->showIcons() ) + h = QMAX( h, listbox->fontMetrics().lineSpacing() ) + KDialog::spacingHint() * 2; + else + h = (int)navigator()->viewMode() + listbox->fontMetrics().lineSpacing() + 4; + } + return h; +} + +void EntryItem::paint( QPainter *p ) +{ + reloadPixmap(); + + QListBox *box = listBox(); + bool iconAboveText = ( navigator()->viewMode() > SmallIcons ) + && navigator()->showIcons(); + int w = box->viewport()->width(); + int y = 2; + + // draw selected + if ( isCurrent() || isSelected() || mHasHover || mPaintActive ) { + int h = height( box ); + + QBrush brush; + if ( isCurrent() || isSelected() || mPaintActive ) + brush = box->colorGroup().brush( QColorGroup::Highlight ); + else + brush = box->colorGroup().highlight().light( 115 ); + p->fillRect( 1, 0, w - 2, h - 1, brush ); + QPen pen = p->pen(); + QPen oldPen = pen; + pen.setColor( box->colorGroup().mid() ); + p->setPen( pen ); + + p->drawPoint( 1, 0 ); + p->drawPoint( 1, h - 2 ); + p->drawPoint( w - 2, 0 ); + p->drawPoint( w - 2, h - 2 ); + + p->setPen( oldPen ); + } + + if ( !mPixmap.isNull() && navigator()->showIcons() ) { + int x = iconAboveText ? ( ( w - mPixmap.width() ) / 2 ) : + KDialog::marginHint(); + p->drawPixmap( x, y, mPixmap ); + } + + QColor shadowColor = listBox()->colorGroup().background().dark(115); + if ( isCurrent() || isSelected() ) { + p->setPen( box->colorGroup().highlightedText() ); + } + + if ( !text().isEmpty() && navigator()->showText() ) { + QFontMetrics fm = p->fontMetrics(); + + int x = 0; + if ( iconAboveText ) { + x = ( w - fm.width( text() ) ) / 2; + y += fm.height() - fm.descent(); + if ( navigator()->showIcons() ) + y += mPixmap.height(); + } else { + x = KDialog::marginHint() + 4; + if( navigator()->showIcons() ) { + x += mPixmap.width(); + } + + if ( !navigator()->showIcons() || mPixmap.height() < fm.height() ) + y += fm.ascent() + fm.leading()/2; + else + y += mPixmap.height()/2 - fm.height()/2 + fm.ascent(); + } + + if ( isCurrent() || isSelected() || mHasHover ) { + p->setPen( box->colorGroup().highlight().dark(115) ); + p->drawText( x + ( QApplication::reverseLayout() ? -1 : 1), + y + 1, text() ); + p->setPen( box->colorGroup().highlightedText() ); + } + else + p->setPen( box->colorGroup().text() ); + + p->drawText( x, y, text() ); + } + + // ensure that we don't have a stale flag around + if ( isCurrent() || isSelected() ) mHasHover = false; +} + +void EntryItem::setHover( bool hasHover ) +{ + mHasHover = hasHover; +} + +void EntryItem::setPaintActive( bool paintActive ) +{ + mPaintActive = paintActive; +} + +// ************************************************ + +Navigator::Navigator(bool _selectable, KPopupMenu * menu, IconSidePane *_iconsidepane, QWidget *parent, const char *name ) + : KListBox( parent, name ), mSidePane( _iconsidepane ), mPopupMenu( menu ) +{ + setSelectionMode( KListBox::Single ); + viewport()->setBackgroundMode( PaletteBackground ); + setFrameStyle( QFrame::NoFrame ); + setHScrollBarMode( QScrollView::AlwaysOff ); + //setAcceptDrops( true ); + mMinWidth = 0; + mSelectable = _selectable; + executedItem = 0; + mMouseOn = 0; + + setFocusPolicy( NoFocus ); + + connect( this, SIGNAL( clicked( QListBoxItem* ) ), + SLOT( slotExecuted( QListBoxItem* ) ) ); + connect( this, SIGNAL( onItem( QListBoxItem * ) ), + SLOT( slotMouseOn( QListBoxItem * ) ) ); + connect( this, SIGNAL( onViewport() ), SLOT( slotMouseOff() ) ); + + QToolTip::remove( this ); + if ( !mSidePane->showText() ) + new EntryItemToolTip( this ); +} + +IconViewMode Navigator::viewMode() +{ + return mSidePane->viewMode(); +} + +bool Navigator::showText() +{ + return mSidePane->showText(); +} + +bool Navigator::showIcons() +{ + return mSidePane->showIcons(); +} + +void Navigator::mouseReleaseEvent(QMouseEvent *e) +{ + KListBox::mouseReleaseEvent(e); + if ( e->button() != LeftButton || !mLeftMouseButtonPressed ) + return; + if ( itemAt( e->pos() ) && executedItem == selectedItem() ) + emit itemSelected( currentItem() ); + if ( !mSelectable ) + clearSelection(); +} + +void Navigator::mousePressEvent(QMouseEvent *e) +{ + if ( e->button() != LeftButton || itemAt( e->pos() ) == 0 ) + { + mLeftMouseButtonPressed = false; + if (e->button() == RightButton) + slotShowRMBMenu( 0,mapToGlobal( e->pos() ) ); + return; + } + else + mLeftMouseButtonPressed = true; + KListBox::mousePressEvent(e); +} + +void Navigator::enterEvent( QEvent *event ) +{ + // work around Qt behaviour: onItem is not emmitted in enterEvent() + KListBox::enterEvent( event ); + emit onItem( itemAt( mapFromGlobal( QCursor::pos() ) ) ); +} + +void Navigator::slotExecuted( QListBoxItem *item ) +{ + if ( !item ) + return; + executedItem = item; +} + +QSize Navigator::sizeHint() const +{ + return QSize( mMinWidth, 100 ); +} + +void Navigator::calculateMinWidth() +{ + mMinWidth = mSidePane->minWidth(); + + for (EntryItem *item = static_cast<EntryItem *>(firstItem()) ; item; item = static_cast<EntryItem *>(item->next())) + { + if (item->width( this ) > mMinWidth) + mMinWidth = item->width( this ); + } + //kdDebug() << "minWidth:" << mMinWidth << endl; + parentWidget()->setFixedWidth( mMinWidth ); + triggerUpdate(true); +} + +int Navigator::insertItem(const QString &_text, const QString & _pix) +{ + EntryItem *item = new EntryItem( this, count(), _text, _pix ); + if (item->width( this ) > mSidePane->minWidth() ) + { + mMinWidth = item->width( this ); + parentWidget()->setMinimumWidth( mMinWidth ); + //kdDebug() << "minWidth:" << mMinWidth << endl; + } + return item->id(); +} + +void Navigator::setHoverItem( QListBoxItem* item, bool hover ) +{ + static_cast<EntryItem*>( item )->setHover( hover ); + updateItem( item ); +} + +void Navigator::setPaintActiveItem( QListBoxItem* item, bool paintActive ) +{ + static_cast<EntryItem*>( item )->setPaintActive( paintActive ); + updateItem( item ); +} + +void Navigator::slotMouseOn( QListBoxItem* newItem ) +{ + QListBoxItem* oldItem = mMouseOn; + if ( oldItem == newItem ) + return; + + if ( oldItem && !oldItem->isCurrent() && !oldItem->isSelected() ) + setHoverItem( oldItem, false ); + + if ( newItem && !newItem->isCurrent() && !newItem->isSelected() ) + setHoverItem( newItem, true ); + mMouseOn = newItem; +} + +void Navigator::slotMouseOff() +{ + slotMouseOn( 0 ); +} + +void Navigator::resizeEvent( QResizeEvent *event ) +{ + QListBox::resizeEvent( event ); + triggerUpdate( true ); +} + +void Navigator::slotShowRMBMenu( QListBoxItem *, const QPoint &pos ) +{ + int choice = mPopupMenu->exec( pos ); + + if ( choice == -1 ) + return; + + mSidePane->resetWidth(); + if ( choice >= SmallIcons ) { + mSidePane->setViewMode( mSidePane->sizeIntToEnum( choice ) ); + mPopupMenu->setItemChecked( (int)SmallIcons, false); + mPopupMenu->setItemChecked( (int)NormalIcons, false); + mPopupMenu->setItemChecked( (int)LargeIcons, false); + mPopupMenu->setItemChecked( mSidePane->viewMode(), true); + KoShellSettings::setSidePaneIconSize( choice ); + } + else + { + // either icons or text were toggled + if ( choice == ShowIcons ) { + mSidePane->toogleIcons(); + mPopupMenu->setItemChecked( (int)ShowIcons, mSidePane->showIcons() ); + mPopupMenu->setItemEnabled( (int)ShowText, mSidePane->showIcons() ); + mPopupMenu->setItemEnabled( (int)SmallIcons, mSidePane->showIcons()); + mPopupMenu->setItemEnabled( (int)NormalIcons, mSidePane->showIcons()); + mPopupMenu->setItemEnabled( (int)LargeIcons, mSidePane->showIcons()); + KoShellSettings::setSidePaneShowIcons( mSidePane->showIcons() ); + + QToolTip::remove( this ); + } else { + mSidePane->toogleText(); + mSidePane->resetWidth(); + mPopupMenu->setItemChecked( (int)ShowText, mSidePane->showText() ); + mPopupMenu->setItemEnabled( (int)ShowIcons, mSidePane->showText() ); + mPopupMenu->setItemEnabled( (int)SmallIcons, true); + mPopupMenu->setItemEnabled( (int)NormalIcons, true); + mPopupMenu->setItemEnabled( (int)LargeIcons, true); + KoShellSettings::setSidePaneShowText( mSidePane->showText() ); + new EntryItemToolTip( this ); +// if ( !mSidePane->showText() ) +// mSidePane->buttonGroup()->hide(); +// else +// mSidePane->buttonGroup()->show(); + } + } + calculateMinWidth(); + emit updateAllWidgets(); +} + +// ************************************************ + +IconSidePane::IconSidePane(QWidget *parent, const char *name ) + : QVBox( parent, name ) +{ + m_buttongroup = new QButtonGroup(1, QGroupBox::Horizontal, this); + m_buttongroup->setExclusive(true); + m_buttongroup->hide(); + mWidgetstack = new QWidgetStack(this); + mWidgetstack->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); + + // setup the popup menu + mShowIcons = KoShellSettings::sidePaneShowIcons(); + mShowText = KoShellSettings::sidePaneShowText(); + mViewMode = sizeIntToEnum( KoShellSettings::sidePaneIconSize() ); + mPopupMenu = new KPopupMenu(0); + mPopupMenu->insertTitle( i18n( "Icon Size" ) ); + mPopupMenu->insertItem( i18n( "Large" ), (int)LargeIcons ); + mPopupMenu->setItemEnabled( (int)LargeIcons, mShowIcons ); + mPopupMenu->insertItem( i18n( "Normal" ), (int)NormalIcons ); + mPopupMenu->setItemEnabled( (int)NormalIcons, mShowIcons ); + mPopupMenu->insertItem( i18n( "Small" ), (int)SmallIcons ); + mPopupMenu->setItemEnabled( (int)SmallIcons, mShowIcons ); + mPopupMenu->setItemChecked( (int)mViewMode, true ); + mPopupMenu->insertSeparator(); + mPopupMenu->insertItem( i18n( "Show Icons" ), (int)ShowIcons ); + mPopupMenu->setItemChecked( (int)ShowIcons, mShowIcons ); + mPopupMenu->setItemEnabled( (int)ShowIcons, mShowText ); + mPopupMenu->insertItem( i18n( "Show Text" ), (int)ShowText ); + mPopupMenu->setItemChecked( (int)ShowText, mShowText ); + mPopupMenu->setItemEnabled( (int)ShowText, mShowIcons ); + if ( !mShowText ) + m_buttongroup->hide(); +} + +IconSidePane::~IconSidePane() +{ +} + +int IconSidePane::insertItem(int _grp, const QString & _pix, const QString &_text) +{ + return static_cast<Navigator*>( mWidgetstack->widget(_grp))->insertItem( _text, _pix ); +} + +int IconSidePane::insertItem(const QString & _pix, const QString &_text) +{ + return mCurrentNavigator->insertItem(_text, _pix); +} + +void IconSidePane::renameItem( int _grp, int _id, const QString & _text ) +{ + Navigator *navigator = static_cast<Navigator*>(mWidgetstack->widget(_grp)); + if (!navigator) + return; + EntryItem *item = 0; + for (uint i=0; i< navigator->count(); i++) + { + item = static_cast<EntryItem *>(navigator->item(i)); + if (_id == item->id()) + { + item->setNewText(_text); + navigator->triggerUpdate(false); + break; + } + } +} + +void IconSidePane::removeItem( int _grp, int _id ) +{ + Navigator *navigator = static_cast<Navigator*>(mWidgetstack->widget(_grp)); + if (!navigator) + return; + for (uint i=0; i< navigator->count(); i++) + { + if (_id == static_cast<EntryItem *>(navigator->item(i))->id()) + { + navigator->removeItem(i); + break; + } + } +} + +int IconSidePane::insertGroup(const QString &_text, bool _selectable, QObject *_obj, const char *_slot) +{ + mCurrentNavigator = new Navigator(_selectable, mPopupMenu, this, mWidgetstack ); + //connect( mCurrentNavigator, SIGNAL( itemSelected( int ) ), this, SLOT( itemSelected( int ) ) ); + if ( _obj != 0L && _slot != 0L ) + connect( mCurrentNavigator, SIGNAL( itemSelected(int ) ), _obj, _slot ); + connect( mCurrentNavigator, SIGNAL( updateAllWidgets() ), this, SLOT(updateAllWidgets()) ); + int const id = mWidgetstack->addWidget(mCurrentNavigator); + mWidgetStackIds.append( id ); + KPushButton *b = new KPushButton( _text, m_buttongroup ); + m_buttongroup->insert( b, id ); + connect( b, SIGNAL( clicked() ), this, SLOT( buttonClicked() ) ); + b->setToggleButton( true ); + b->setFocusPolicy( NoFocus ); + if (m_buttongroup->count()==1) + { + mCurrentNavigator->calculateMinWidth(); + m_buttongroup->setButton(m_buttongroup->id(b)); + mWidgetstack->raiseWidget(id); + } + if ( b->width() > minimumWidth() ) + setMinimumWidth( b->width() ); + return id; +} + +void IconSidePane::buttonClicked() +{ + mWidgetstack->raiseWidget( m_buttongroup->selectedId() ); +} + +void IconSidePane::selectGroup(int group_id) +{ + mWidgetstack->raiseWidget(group_id); +} + +void IconSidePane::itemSelected(int item) +{ + kdDebug() << "Item selected:" << item << endl; +} + +Navigator * IconSidePane::group(int _grp) +{ + return static_cast<Navigator*>(mWidgetstack->widget(_grp)); +} + +void IconSidePane::updateAllWidgets() +{ + QValueList<int>::iterator it; + for ( it = mWidgetStackIds.begin(); it != mWidgetStackIds.end(); ++it ) + static_cast<Navigator*>(mWidgetstack->widget(*it))->triggerUpdate( true ); +} + +int IconSidePane::minWidth() +{ + int width = 0; + QValueList<int>::iterator it; + Navigator *n; + for ( it = mWidgetStackIds.begin(); it != mWidgetStackIds.end(); ++it ) + { + n = static_cast<Navigator*>(mWidgetstack->widget(*it)); + if ( n->minWidth() > width ) + width = n->minWidth(); + } + return width; +} + +void IconSidePane::resetWidth() +{ + QValueList<int>::iterator it; + Navigator *n; + for ( it = mWidgetStackIds.begin(); it != mWidgetStackIds.end(); ++it ) + { + n = static_cast<Navigator*>(mWidgetstack->widget(*it)); + n->resetWidth(); + n->triggerUpdate(true); + } +} + +IconViewMode IconSidePane::sizeIntToEnum(int size) const +{ + switch ( size ) { + case int(LargeIcons): + return LargeIcons; + break; + case int(NormalIcons): + return NormalIcons; + break; + case int(SmallIcons): + return SmallIcons; + break; + default: + // Stick with sane values + return NormalIcons; + kdDebug() << "View mode not implemented!" << endl; + break; + } +} + +void IconSidePane::setActionCollection( KActionCollection *actionCollection ) +{ + mActionCollection = actionCollection; +} + +KActionCollection *IconSidePane::actionCollection() const +{ + return mActionCollection; +} + +#include "iconsidepane.moc" + +// vim: sw=2 sts=2 et tw=80 diff --git a/koshell/iconsidepane.h b/koshell/iconsidepane.h new file mode 100644 index 00000000..2382547a --- /dev/null +++ b/koshell/iconsidepane.h @@ -0,0 +1,213 @@ +/* + This file is part of the KDE KOffice project. + + Copyright (C) 2003 Cornelius Schumacher <schumacher@kde.org> + Copyright (C) 2005 Fredrik Edemar <f_edemar@linux.se> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ +#ifndef KOFFICE_ICONSIDEPANEBASE_H +#define KOFFICE_ICONSIDEPANEBASE_H + +#include <kactioncollection.h> +#include <klistbox.h> + +#include <qbuttongroup.h> +#include <qlayout.h> +#include <qtooltip.h> +#include <qvbox.h> +#include <qwidgetstack.h> + +#include "koshellsettings.h" + + +class Navigator; +class IconSidePane; + +enum IconViewMode { LargeIcons = 48, NormalIcons = 32, SmallIcons = 22, ShowText = 3, ShowIcons = 5 }; + +/** + A @see QListBoxPixmap Square Box with an optional icon and a text + underneath. +*/ +class EntryItem : public QListBoxItem +{ + public: + EntryItem( Navigator *, int _id, const QString &_text, const QString & _pix ); + ~EntryItem(); + + + const QPixmap *pixmap() const { return &mPixmap; } + + int id() { return mId; } + + void setNewText( const QString &_text ); + + void setHover( bool ); + void setPaintActive( bool ); + bool paintActive() const { return mPaintActive; } + + /** + returns the width of this item. + */ + virtual int width( const QListBox * ) const; + /** + returns the height of this item. + */ + virtual int height( const QListBox * ) const; + + protected: + void reloadPixmap(); + + virtual void paint( QPainter *p ); + + private: + QPixmap mPixmap; + QString mPixmapName; + int const mId; + Navigator* navigator() const; + bool mHasHover; + bool mPaintActive; +}; + +/** + * Tooltip that changes text depending on the item it is above. + * Compliments of "Practical Qt" by Dalheimer, Petersen et al. + */ +class EntryItemToolTip : public QToolTip +{ + public: + EntryItemToolTip( QListBox* parent ) + : QToolTip( parent->viewport() ), mListBox( parent ) + {} + protected: + void maybeTip( const QPoint& p ) { + // We only show tooltips when there are no texts shown + if ( KoShellSettings::sidePaneShowText() ) return; + if ( !mListBox ) return; + QListBoxItem* item = mListBox->itemAt( p ); + if ( !item ) return; + const QRect itemRect = mListBox->itemRect( item ); + if ( !itemRect.isValid() ) return; + + const EntryItem *entryItem = static_cast<EntryItem*>( item ); + QString tipStr = entryItem->text(); + tip( itemRect, tipStr ); + } + private: + QListBox* mListBox; +}; + +/** + Navigation pane showing all parts relevant to the user +*/ +class Navigator : public KListBox +{ + Q_OBJECT + public: + Navigator(bool _selectable, KPopupMenu*, IconSidePane *, QWidget *parent = 0, const char *name = 0 ); + + int insertItem(const QString &_text, const QString &_pix); + + QSize sizeHint() const; + IconViewMode viewMode(); + bool showText(); + bool showIcons(); + void calculateMinWidth(); + bool leftMouseButtonPressed(){return mLeftMouseButtonPressed;} + int minWidth() { return mMinWidth; } + void resetWidth() { mMinWidth = 0; } + + signals: + void itemSelected( int ); + void updateAllWidgets(); + + protected: + void resizeEvent( QResizeEvent * ); + void enterEvent( QEvent* ); + void mouseReleaseEvent(QMouseEvent *e); + void mousePressEvent(QMouseEvent *e); + + void setHoverItem( QListBoxItem*, bool ); + void setPaintActiveItem( QListBoxItem*, bool ); + + protected slots: + void slotExecuted( QListBoxItem * ); + void slotMouseOn( QListBoxItem *item ); + void slotMouseOff(); + void slotShowRMBMenu( QListBoxItem *, const QPoint& ); + + private: + IconSidePane *mSidePane; + int mMinWidth; + QListBoxItem *executedItem; + bool mLeftMouseButtonPressed; + KPopupMenu *mPopupMenu; + bool mSelectable; + QListBoxItem* mMouseOn; +}; + +class IconSidePane :public QVBox +{ + Q_OBJECT + public: + IconSidePane( QWidget *parent, const char *name = 0 ); + ~IconSidePane(); + + void setActionCollection( KActionCollection *actionCollection ); + KActionCollection *actionCollection() const; + + int insertItem(const QString & _pix, const QString &_text); + int insertItem(int _grp, const QString & _pix, const QString &_text); + int insertGroup(const QString &_text, bool _selectable, QObject *_obj = 0L, const char *_slot = 0L); + void renameItem( int _grp, int _id, const QString & _text ); + void removeItem( int _grp, int _id ); + void selectGroup(int); + Navigator *group(int); + + IconViewMode sizeIntToEnum(int size) const; + IconViewMode viewMode() { return mViewMode; } + void setViewMode(int choice){mViewMode = sizeIntToEnum(choice);} + bool showText() { return mShowText; } + void toogleText(){mShowText=!mShowText;} + bool showIcons() { return mShowIcons; } + void toogleIcons(){mShowIcons=!mShowIcons;} + QButtonGroup *buttonGroup() { return m_buttongroup; } + int minWidth(); + void resetWidth(); + + public slots: + void itemSelected(int); + void updateAllWidgets(); + + private slots: + void buttonClicked(); + + private: + QWidgetStack *mWidgetstack; + QValueList<int> mWidgetStackIds; + Navigator *mCurrentNavigator; + QButtonGroup *m_buttongroup; + KActionCollection *mActionCollection; + KPopupMenu *mPopupMenu; + + IconViewMode mViewMode; + bool mShowIcons; + bool mShowText; +}; + + +#endif diff --git a/koshell/koshell.desktop b/koshell/koshell.desktop new file mode 100644 index 00000000..37b5e8a7 --- /dev/null +++ b/koshell/koshell.desktop @@ -0,0 +1,135 @@ +[Desktop Entry] +Name=KOffice Workspace +Name[af]=Koffice Werkspasie +Name[ar]=حيِّز العمل لدى KOffice +Name[az]=KOffice İş Sahəsi +Name[bg]=Работна среда за KOffice +Name[br]=Egor labour KOffice +Name[bs]=KOffice radna okolina +Name[ca]=Àrea de treball de KOffice +Name[cs]=Pracovní plocha KOffice +Name[cy]=Gweithle KOffice +Name[da]=KOffice-arbejdsplads +Name[de]=KOffice-Arbeitsbereich +Name[el]=Χώρος εργασίας του KOffice +Name[eo]=KOffice-Laborkadro +Name[es]=Área de trabajo de KOffice +Name[et]=KOffice'i töölaud +Name[eu]=KOffice-en laneko area +Name[fa]=کاربرگ KOffice +Name[fi]=KOffice työtila +Name[fr]=Espace de travail KOffice +Name[fy]=KOffice Workromte +Name[ga]=Spás Oibre KOffice +Name[gl]=Espazo de Traballo de KOffice +Name[he]=סביבת העבודה של KOffice +Name[hi]=के-ऑफ़िस कार्यस्थल +Name[hr]=KOffice radni prostor +Name[hu]=KOffice +Name[id]=Ruang kerja KOffice +Name[is]=KOffice vinnubekkur +Name[it]=Spazio di lavoro di KOffice +Name[ja]=KOffice ワークスペース +Name[km]=តំបន់ការងាររបស់ KOffice +Name[lo]=ພື້ນທີ່ໂປຣແກຣມຊຸດສຳນັກງານ +Name[lt]=KOffice darbo aplinka +Name[lv]=KOffice darbavieta +Name[mk]=Работен простор за KOffice +Name[ms]=Ruang Kerja KOffice +Name[mt]=Spazju tax-Xogħol KOffice +Name[nb]=KOffice-arbeidsområde +Name[nds]=KOffice-Arbeitrebeet +Name[ne]=केडीई कार्यालय कार्यस्थान +Name[nl]=KOffice-werkplek +Name[nn]=KOffice-arbeidsområde +Name[pl]=Pracownia KOffice +Name[pt]=Espaço de Trabalho do KOffice +Name[pt_BR]=Espaço de Trabalho do KOffice +Name[ro]=Spaţiu de lucru KOffice +Name[ru]=Рабочая среда KOffice +Name[se]=KOffice-bargobáiki +Name[sk]=Pracovný priestor KOffice +Name[sl]=Delovni prostor KOffice +Name[sr]=KOffice-ов радни простор +Name[sr@Latn]=KOffice-ov radni prostor +Name[sv]=Koffice-arbetsyta +Name[ta]=KOffice பணிக்கணினி +Name[tg]=Фазои Кории KOffice +Name[th]=พื้นที่โปรแกรมชุดสำนักงาน +Name[tr]=KOffice Çalışma Alanı +Name[uk]=Робочій простір KOffice +Name[uz]=KOffice ish muhiti +Name[uz@cyrillic]=KOffice иш муҳити +Name[ven]=Tshikhala tshau shuma tsha ofisi ya K +Name[xh]=Isithuba somsebenzi se KOffice +Name[zh_CN]=KOffice 工作空间 +Name[zh_TW]=KOffice 工作空間 +Name[zu]=Isikhala somsebenzi se KOffice +DocPath=koshell/index.html +Exec=koshell +GenericName=Office Suite +GenericName[af]=Kantoor Paket +GenericName[ar]=باقة Office +GenericName[bg]=Офис пакет +GenericName[bs]=KOffice okoliš +GenericName[ca]=Programes d'oficina +GenericName[cs]=Kancelářská sada +GenericName[cy]=Casgliad Sywddfa +GenericName[da]=Kontorpakke +GenericName[de]=Büroprogramme +GenericName[el]=Σουίτα γραφείου +GenericName[eo]=Oficejoprogramaro +GenericName[es]=Suite ofimática +GenericName[et]=Kontoritöö komplekt +GenericName[eu]=Bulegorako suitea +GenericName[fa]=مجموعۀ دفتری +GenericName[fi]=Toimisto-ohjelma +GenericName[fo]=Skrivstovuforrit +GenericName[fr]=Suite bureautique +GenericName[fy]=Officepakket +GenericName[ga]=Sraith Feidhmchlár Oifige +GenericName[gl]=Paquete de Escritorio +GenericName[he]=חבילת יישומים משרדיים +GenericName[hi]=ऑफिस सूट +GenericName[hr]=Uredski paket +GenericName[hu]=Dokumentumkezelő +GenericName[is]=Skrifstofuvöndull +GenericName[it]=Programmi per l'ufficio +GenericName[ja]=オフィススイート +GenericName[km]=ឈុតកម្មវិធីការិយាល័យ +GenericName[lo]=ໂປຣແກຣມຊຸດສຳນັກງານ +GenericName[lt]=Ofiso rinkinys +GenericName[lv]=Ofisa komplekts +GenericName[ms]=Set Pejabat +GenericName[mt]=Sett tal-uffiċċju +GenericName[nb]=Kontorpakke +GenericName[nds]=Kontoorprogrammen +GenericName[ne]=कार्यालय अनुगामी +GenericName[nl]=Officepakket +GenericName[nn]=Kontorpakke +GenericName[nso]=Suthu ya Ofisi +GenericName[pl]=Pakiet biurowy +GenericName[pt]=Pacote de Escritório +GenericName[pt_BR]=Suíte de Escritório +GenericName[ro]=Suită de aplicaţii de birou +GenericName[ru]=Офисный пакет +GenericName[se]=Kántuvrapáhkka +GenericName[sk]=Office balík +GenericName[sl]=Pisarniška zbirka +GenericName[sr]=Канцеларијски пакет +GenericName[sr@Latn]=Kancelarijski paket +GenericName[sv]=Office-paket +GenericName[ta]=KOffice தொகுப்பு +GenericName[th]=โปรแกรมชุดสำนักงาน +GenericName[tr]=Ofis Yazılımı +GenericName[uk]=Офісний комплект +GenericName[uz]=Idora uchun dasturlar toʻplami +GenericName[uz@cyrillic]=Идора учун дастурлар тўплами +GenericName[ven]=Sutu ya Ofisini +GenericName[zh_CN]=办公套件 +GenericName[zh_TW]=辦公軟體程式集 +Type=Application +Icon=koshell +X-KDE-StartupNotify=true +X-DCOP-ServiceType=Multi +Categories=Qt;KDE;Office; diff --git a/koshell/koshell.kcfg b/koshell/koshell.kcfg new file mode 100644 index 00000000..ee5c5615 --- /dev/null +++ b/koshell/koshell.kcfg @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE kcfg SYSTEM "http://www.kde.org/standards/kcfg/1.0/kcfg.dtd"> +<kcfg> +<kcfgfile name="koshellrc"/> + <group name="koshell"> + <entry name="SidebarWidth" type="Int"> + <label>Defines the width of the sidebar.</label> + <default>80</default> + </entry> + </group> + <group name="sidepane"> + <entry type="Int" name="SidePaneIconSize"> + <default>32</default> + </entry> + <entry type="Bool" name="SidePaneShowIcons"><default>true</default></entry> + <entry type="Bool" name="SidePaneShowText"><default>true</default></entry> + </group> +</kcfg>
\ No newline at end of file diff --git a/koshell/koshell_main.cc b/koshell/koshell_main.cc new file mode 100644 index 00000000..ac57a7cb --- /dev/null +++ b/koshell/koshell_main.cc @@ -0,0 +1,90 @@ +/* This file is part of the KDE project + Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> + Copyright (C) 2000, 2001 David Faure <faure@kde.org> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include <kofficeversion.h> +#include <kaboutdata.h> +#include <kcmdlineargs.h> +#include <kdebug.h> +#include <klocale.h> +#include <kuniqueapplication.h> +#include <kwin.h> + +#include <KoGlobal.h> + +#include "koshell_shell.h" + +static const char* description = I18N_NOOP("KOffice Workspace"); +static const char* version = KOFFICE_VERSION_STRING; + +class KoShellApp : public KUniqueApplication { + public: + KoShellApp() : mMainWindow( 0 ) {} + ~KoShellApp() {} + + int newInstance(); + + private: + KoShellWindow *mMainWindow; +}; + + +int KoShellApp::newInstance() +{ + if ( isRestored() ) { + // There can only be one main window + if ( KMainWindow::canBeRestored( 1 ) ) { + mMainWindow = new KoShellWindow(); + setMainWidget( mMainWindow ); + mMainWindow->show(); + mMainWindow->restore( 1 ); + } + } else { + if ( !mMainWindow ) { + mMainWindow = new KoShellWindow(); + mMainWindow->show(); + setMainWidget( mMainWindow ); + } + } + // Handle startup notification and window activation + // (The first time it will do nothing except note that it was called) + return KUniqueApplication::newInstance(); +} + +extern "C" KOSHELL_EXPORT int kdemain( int argc, char **argv ) +{ + KAboutData * aboutData = new KAboutData( "koshell", I18N_NOOP("KOffice Workspace"), + version, description, KAboutData::License_GPL, + "(c) 1998-2006, Torben Weis\n(c) 2002-2005, David Faure\n(c) 2005, Sven Lüppken"); + aboutData->addAuthor("Sven Lüppken", I18N_NOOP("Current Maintainer"), "sven@kde.org"); + aboutData->addAuthor("Torben Weis", 0, "weis@kde.org"); + aboutData->addAuthor("David Faure", 0, "faure@kde.org"); + KCmdLineArgs::init( argc, argv, aboutData ); + + if ( !KoShellApp::start() ) { + // Already running, brought to the foreground. + return 0; + } + KoShellApp app; + // Initialize stuff (like KoApplication does) + KoGlobal::initialize(); + + return app.exec(); +} + diff --git a/koshell/koshell_shell.cc b/koshell/koshell_shell.cc new file mode 100644 index 00000000..0160f1e1 --- /dev/null +++ b/koshell/koshell_shell.cc @@ -0,0 +1,739 @@ +/* This file is part of the KDE project + Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> + Copyright (C) 1999 Simon Hausmann <hausmann@kde.org> + Copyright (C) 2000-2005 David Faure <faure@kde.org> + Copyright (C) 2005, 2006 Sven Lüppken <sven@kde.org> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include <qcursor.h> +#include <qsplitter.h> +#include <qiconview.h> +#include <qlabel.h> +#include <qvbox.h> + +#include <assert.h> + +#include "koshell_shell.h" +#include "koshellsettings.h" + +#include <kapplication.h> +#include <ktempfile.h> +#include <kfiledialog.h> +#include <klocale.h> +#include <kdebug.h> +#include <kiconloader.h> +#include <kkeydialog.h> +#include <kstandarddirs.h> +#include <klibloader.h> +#include <kpopupmenu.h> +#include <kservice.h> +#include <kmessagebox.h> +#include <krecentdocument.h> +#include <kparts/partmanager.h> +#include <kaction.h> +#include <kdeversion.h> +#include <kaboutdata.h> + +#include <KoQueryTrader.h> +#include <KoDocumentInfo.h> +#include <KoDocument.h> +#include <KoView.h> +#include <KoPartSelectDia.h> +#include <KoFilterManager.h> +#include <kiconloader.h> + +KoShellWindow::KoShellWindow() + : KoMainWindow( KGlobal::instance() ) +{ + m_activePage = m_lstPages.end(); + + m_pLayout = new QSplitter( centralWidget() ); + + // Setup the sidebar + m_pSidebar = new IconSidePane( m_pLayout ); + m_pSidebar->setSizePolicy( QSizePolicy( QSizePolicy::Maximum, + QSizePolicy::Preferred ) ); + m_pSidebar->setActionCollection( actionCollection() ); + m_grpFile = m_pSidebar->insertGroup(i18n("Components"), false, this, SLOT( slotSidebar_Part(int ))); + m_grpDocuments = m_pSidebar->insertGroup(i18n("Documents"), true, this, SLOT(slotSidebar_Document(int))); + m_pLayout->setResizeMode(m_pSidebar,QSplitter::FollowSizeHint); + + // Setup the tabbar + m_pFrame = new KTabWidget( m_pLayout ); + m_pFrame->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, + QSizePolicy::Preferred ) ); + m_pFrame->setTabPosition( KTabWidget::Bottom ); + + m_tabCloseButton = new QToolButton( m_pFrame ); + connect( m_tabCloseButton, SIGNAL( clicked() ), + this, SLOT( slotFileClose() ) ); + m_tabCloseButton->setIconSet( SmallIconSet( "tab_remove" ) ); + m_tabCloseButton->adjustSize(); + QToolTip::add(m_tabCloseButton, i18n("Close")); + m_pFrame->setCornerWidget( m_tabCloseButton, BottomRight ); + m_tabCloseButton->hide(); + + QValueList<KoDocumentEntry> lstComponents = KoDocumentEntry::query(false,QString()); + QValueList<KoDocumentEntry>::Iterator it = lstComponents.begin(); + int id = 0; + // Get all available components + for( ; it != lstComponents.end(); ++it ) + { + KService* service = (*it).service(); + if ( !service->genericName().isEmpty() ) + { + id = m_pSidebar->insertItem(m_grpFile, service->icon(), service->genericName()); + } + else + { + continue; + } + + m_mapComponents[ id++ ] = *it; + } + + QValueList<int> list; + list.append( KoShellSettings::sidebarWidth() ); + list.append( this->width() - KoShellSettings::sidebarWidth() ); + m_pLayout->setSizes( list ); + + connect( this, SIGNAL( documentSaved() ), + this, SLOT( slotNewDocumentName() ) ); + + connect( m_pFrame, SIGNAL( currentChanged( QWidget* ) ), + this, SLOT( slotUpdatePart( QWidget* ) ) ); + connect( m_pFrame, SIGNAL( contextMenu(QWidget * ,const QPoint &)), this, SLOT( tab_contextMenu(QWidget * ,const QPoint &)) ); + + m_client = new KoShellGUIClient( this ); + createShellGUI(); +} + +KoShellWindow::~KoShellWindow() +{ + //kdDebug() << "KoShellWindow::~KoShellWindow()" << endl; + + // Set the active part to 0 (as we do in ~KoMainWindow, but this is too + // late for KoShell, it gets activePartChanged signals delivered to a dead + // KoShellWindow object). + partManager()->setActivePart(0); + + // Destroy all documents - queryClose has made sure we saved them first + QValueList<Page>::ConstIterator it = m_lstPages.begin(); + for (; it != m_lstPages.end(); ++it ) + { + (*it).m_pDoc->removeShell( this ); + delete (*it).m_pView; + if ( (*it).m_pDoc->viewCount() == 0 ) + delete (*it).m_pDoc; + } + m_lstPages.clear(); + + setRootDocumentDirect( 0L, QPtrList<KoView>() ); // prevent our parent destructor from doing stupid things + saveSettings(); // Now save our settings before exiting +} + +bool KoShellWindow::openDocumentInternal( const KURL &url, KoDocument* ) +{ + // Here we have to distinguish two cases: The passed URL has a native + // KOffice mimetype. Then we query the trader and create the document. + // The file is loaded and everyone's happy. + // The second case is a non-native file. Here we have to create a + // filter manager, ask it to convert the file to the "closest" available + // KOffice part and open the temporary file. + + /*if (!KIO::NetAccess::exists(url,true,0) ) + { + KMessageBox::error(0L, i18n("The file %1 doesn't exist.").arg(url.url()) ); + recentAction()->removeURL(url); //remove the file from the recent-opened-file-list + saveRecentFiles(); + return false; + }*/ + + KMimeType::Ptr mimeType = KMimeType::findByURL( url ); + m_documentEntry = KoDocumentEntry::queryByMimeType( mimeType->name().latin1() ); + + KTempFile* tmpFile = 0; + KURL tmpUrl( url ); // we might have to load a converted temp. file + + if ( m_documentEntry.isEmpty() ) { // non-native + tmpFile = new KTempFile; + + KoFilterManager *manager = new KoFilterManager( url.path() ); + QCString mimetype; // an empty mimetype means, that the "nearest" + KoFilter::ConversionStatus status = manager->exp0rt( tmpFile->name(), mimetype ); // KOffice part will be chosen + delete manager; + + if ( status != KoFilter::OK || mimetype.isEmpty() ) { + tmpFile->unlink(); + delete tmpFile; + return false; + } + + // If the conversion was successful we get the mimetype of the + // chosen KOffice part back. + m_documentEntry = KoDocumentEntry::queryByMimeType( mimetype ); + if ( m_documentEntry.isEmpty() ) { + tmpFile->unlink(); + delete tmpFile; + return false; + } + + // Open the temporary file + tmpUrl.setPath( tmpFile->name() ); + } + + recentAction()->addURL( url ); + + KoDocument* newdoc = m_documentEntry.createDoc(); + if ( !newdoc ) { + if ( tmpFile ) { + tmpFile->unlink(); + delete tmpFile; + } + return false; + } + + connect(newdoc, SIGNAL(sigProgress(int)), this, SLOT(slotProgress(int))); + connect(newdoc, SIGNAL(completed()), this, SLOT(slotKSLoadCompleted())); + connect(newdoc, SIGNAL(canceled( const QString & )), this, SLOT(slotKSLoadCanceled( const QString & ))); + newdoc->addShell( this ); // used by openURL + bool openRet = (!isImporting ()) ? newdoc->openURL(tmpUrl) : newdoc->import(tmpUrl); + if ( !openRet ) + { + newdoc->removeShell(this); + delete newdoc; + if ( tmpFile ) { + tmpFile->unlink(); + delete tmpFile; + } + return false; + } + + if ( tmpFile ) { + //if the loaded file has been a temporary file + //we need to correct a few document settings + //see description of bug #77574 for additional information + + //correct (output) mime type: we need to set it to the non-native format + //to make sure the user knows about saving to a non-native mime type + //setConfirmNonNativeSave is set to true below + newdoc->setMimeType( mimeType->name().latin1() ); + newdoc->setOutputMimeType( mimeType->name().latin1() ); + + //the next time the user saves the document he should be warned + //because of mime type settings done above; + newdoc->setConfirmNonNativeSave(true,true); //exporting,warn_on + newdoc->setConfirmNonNativeSave(false,true); //save/save as,warn_on + + //correct document file (should point to URL) + newdoc->setFile( url.path() ); + + //correct document URL + newdoc->setURL( url ); + + //update caption to represent the correct URL in the window titlebar + updateCaption(); + + tmpFile->unlink(); + delete tmpFile; + } + return true; +} + +void KoShellWindow::slotSidebarItemClicked( QIconViewItem *item ) +{ + //kdDebug() << "slotSidebarItemClicked called!" << endl; + if( item != 0 ) + { + int index = item->index(); + + // Create new document from a KoDocumentEntry + m_documentEntry = m_mapComponents[ index ]; + KoDocument *doc = m_documentEntry.createDoc(); + if (doc) + { + // koshell isn't starting, but this is like starting a new app: + // offer both "open existing file" and "open new file". + if ( doc->showEmbedInitDialog( this ) ) + { + partManager()->addPart( doc, false ); + setRootDocument( doc ); + } + else + delete doc; + } + } +} + +// Separate from openDocument to handle async loading (remote URLs) +void KoShellWindow::slotKSLoadCompleted() +{ + KoDocument* newdoc = (KoDocument *)(sender()); + + // KoDocument::import() calls resetURL() too late... + // ...setRootDocument will show the URL... + // So let's stop this from happening and the user will never know :) + if (isImporting()) newdoc->resetURL (); + + partManager()->addPart( newdoc, false ); + setRootDocument( newdoc ); + disconnect(newdoc, SIGNAL(sigProgress(int)), this, SLOT(slotProgress(int))); + disconnect(newdoc, SIGNAL(completed()), this, SLOT(slotKSLoadCompleted())); + disconnect(newdoc, SIGNAL(canceled( const QString & )), this, SLOT(slotKSLoadCanceled( const QString & ))); +} + +void KoShellWindow::slotKSLoadCanceled( const QString & errMsg ) +{ + KMessageBox::error( this, errMsg ); + // ... can't delete the document, it's the one who emitted the signal... + // ###### FIXME: This can be done in 3.0 with deleteLater, I assume (Werner) + + KoDocument* newdoc = (KoDocument *)(sender()); + disconnect(newdoc, SIGNAL(sigProgress(int)), this, SLOT(slotProgress(int))); + disconnect(newdoc, SIGNAL(completed()), this, SLOT(slotKSLoadCompleted())); + disconnect(newdoc, SIGNAL(canceled( const QString & )), this, SLOT(slotKSLoadCanceled( const QString & ))); +} + +void KoShellWindow::saveAll() +{ + KoView *currentView = (*m_activePage).m_pView; + for (QValueList<Page>::iterator it=m_lstPages.begin(); it != m_lstPages.end(); ++it) + { + if ( (*it).m_pDoc->isModified() ) + { + m_pFrame->showPage( (*it).m_pView ); + (*it).m_pView->shell()->slotFileSave(); + if ( (*it).m_pDoc->isModified() ) + break; + } + } + m_pFrame->showPage( currentView ); +} + +void KoShellWindow::setRootDocument( KoDocument * doc ) +{ + kdDebug() << "KoShellWindow::setRootDocument this=" << this << " doc=" << doc << endl; + // We do things quite differently from KoMainWindow::setRootDocument + // This one is called with doc != 0 when a new doc is created + // and with 0L after they have all been removed. + // We use setRootDocumentDirect to switch the 'root doc' known by KoMainWindow. + + if ( doc ) + { + if ( !doc->shells().contains( this ) ) + doc->addShell( this ); + + KoView *v = doc->createView(this); + QPtrList<KoView> views; + views.append(v); + setRootDocumentDirect( doc, views ); + + v->setGeometry( 0, 0, m_pFrame->width(), m_pFrame->height() ); + v->setPartManager( partManager() ); + m_pFrame->addTab( v, KGlobal::iconLoader()->loadIcon( m_documentEntry.service()->icon(), KIcon::Small ), i18n("Untitled") ); + + // Create a new page for this doc + Page page; + page.m_pDoc = doc; + page.m_pView = v; + // insert the new document in the sidebar + page.m_id = m_pSidebar->insertItem( m_grpDocuments, + m_documentEntry.service()->icon(), + i18n("Untitled")); + m_lstPages.append( page ); + v->show(); + + switchToPage( m_lstPages.fromLast() ); + mnuSaveAll->setEnabled(true); + } else + { + setRootDocumentDirect( 0L, QPtrList<KoView>() ); + m_activePage = m_lstPages.end(); + KoMainWindow::updateCaption(); + } +} + +void KoShellWindow::slotNewDocumentName() +{ + updateCaption(); +} + +void KoShellWindow::updateCaption() +{ + //kdDebug() << "KoShellWindow::updateCaption() rootDoc=" << rootDocument() << endl; + KoMainWindow::updateCaption(); + // Let's take this opportunity for setting a correct name for the icon + // in koolbar + QValueList<Page>::Iterator it = m_lstPages.begin(); + for( ; it != m_lstPages.end() ; ++it ) + { + if ( (*it).m_pDoc == rootDocument() ) + { + //kdDebug() << "updateCaption called for " << rootDocument() << endl; + // Get caption from document info (title(), in about page) + QString name; + if ( rootDocument()->documentInfo() ) + { + name = rootDocument()->documentInfo()->title(); + } + if ( name.isEmpty() ) + // Fall back to document URL + name = rootDocument()->url().fileName(); + + if ( !name.isEmpty() ) // else keep Untitled + { + if ( name.length() > 20 ) + { + name.truncate( 17 ); + name += "..."; + } + m_pFrame->changeTab( m_pFrame->currentPage(), name ); + m_pSidebar->renameItem(m_grpDocuments, (*m_activePage).m_id, name); //remove the document from the sidebar + } + + return; + } + } +} + + +void KoShellWindow::slotSidebar_Part(int _item) +{ + //kdDebug() << "Component part choosed:" << _item << endl; + kapp->setOverrideCursor( QCursor(Qt::WaitCursor) ); + m_documentEntry = m_mapComponents[ _item ]; + kdDebug() << m_documentEntry.service() << endl; + kdDebug() << m_documentEntry.name() << endl; + KoDocument *doc = m_documentEntry.createDoc(); + kapp->restoreOverrideCursor(); + if (doc) + { + if ( doc->showEmbedInitDialog( this ) ) + { + partManager()->addPart( doc, false ); + setRootDocument( doc ); + m_tabCloseButton->show(); + } + else + delete doc; + } +} + +void KoShellWindow::slotSidebar_Document(int _item) +{ + // Switch to an existing document + if ( m_activePage != m_lstPages.end() && + (*m_activePage).m_id == _item ) + return; + + QValueList<Page>::Iterator it = m_lstPages.begin(); + while( it != m_lstPages.end() ) + { + if ( (*it).m_id == _item ) + { + switchToPage( it ); + return; + } + ++it; + } +} + +void KoShellWindow::slotShowSidebar() +{ + if( m_pSidebar->isShown() ) + { + m_pSidebar->hide(); + m_pComponentsLabel->hide(); + } + else + { + m_pSidebar->show(); + m_pComponentsLabel->show(); + } +} + +void KoShellWindow::slotUpdatePart( QWidget* widget ) +{ + KoView* v = dynamic_cast<KoView*>(widget); + if ( v != 0 ) + { + QValueList<Page>::Iterator it = m_lstPages.begin(); + for( ; it != m_lstPages.end(); ++it ) + { + if( (*it).m_pView == v ) + switchToPage(it); + } + } +} + +void KoShellWindow::switchToPage( QValueList<Page>::Iterator it ) +{ + // Select new active page (view) + m_activePage = it; + KoView *v = (*m_activePage).m_pView; + + kdDebug() << " setting active part to " << (*m_activePage).m_pDoc << endl; + // Make it active (GUI etc.) + partManager()->setActivePart( (*m_activePage).m_pDoc, v ); + // Change current document + QPtrList<KoView> views; + views.append(v); + setRootDocumentDirect( (*m_activePage).m_pDoc, views ); + // Select the item in the sidebar + m_pSidebar->group(m_grpDocuments)->setSelected((*m_activePage).m_id,true); + // Raise the new page + m_pFrame->showPage( v ); + // Fix caption and set focus to the new view + updateCaption(); + v->setFocus(); + + partSpecificHelpAction->setEnabled(true); + partSpecificHelpAction->setText(i18n("%1 Handbook").arg((*m_activePage).m_pDoc->instance()->aboutData()->programName())); +} + +void KoShellWindow::slotFileNew() +{ + m_documentEntry = KoPartSelectDia::selectPart( this ); + if ( m_documentEntry.isEmpty() ) + return; + KoDocument* newdoc = m_documentEntry.createDoc(); + if ( !newdoc ) + return; + if ( !newdoc->showEmbedInitDialog( this ) ) + { + delete newdoc; + return; + } + + partManager()->addPart( newdoc, false ); + setRootDocument( newdoc ); + m_tabCloseButton->show(); +} + +void KoShellWindow::slotFileOpen() +{ + KFileDialog *dialog=new KFileDialog(QString::null, QString::null, 0L, "file dialog", true); + if (!isImporting()) + dialog->setCaption( i18n("Open Document") ); + else + dialog->setCaption( i18n("Import Document") ); + dialog->setMimeFilter( KoFilterManager::mimeFilter() ); + + KURL url; + if(dialog->exec()==QDialog::Accepted) { + url=dialog->selectedURL(); + recentAction()->addURL( url ); + if ( url.isLocalFile() ) + KRecentDocument::add(url.path(-1)); + else + KRecentDocument::add(url.url(-1), true); + } + else + return; + + delete dialog; + if ( url.isEmpty() ) + return; + + (void) openDocumentInternal( url ); + m_tabCloseButton->show(); +} + +void KoShellWindow::slotFileClose() +{ + // reimplemented to avoid closing the window when we have docs opened + + // No docs at all ? + if ( m_lstPages.count() == 0 ) + close(); // close window + else + closeDocument(); // close only doc + + if ( m_pFrame->count() == 0 ) + m_tabCloseButton->hide(); +} + +void KoShellWindow::closeDocument() +{ + // Set the root document to the current one - so that queryClose acts on it + assert( m_activePage != m_lstPages.end() ); + assert( rootDocument() == (*m_activePage).m_pDoc ); + + // First do the standard queryClose + kdDebug() << "KoShellWindow::closeDocument calling standard queryClose" << endl; + if ( KoMainWindow::queryClose() ) + { + kdDebug() << "Ok for closing document" << endl; + m_pSidebar->removeItem(m_grpDocuments, (*m_activePage).m_id ); //remove the document from the sidebar + (*m_activePage).m_pDoc->removeShell(this); + Page oldPage = (*m_activePage); // make a copy of the struct + m_lstPages.remove( m_activePage ); + m_activePage = m_lstPages.end(); // no active page right now + m_pSidebar->group(m_grpDocuments)->setSelected((*m_activePage).m_id, true); //select the new document in the sidebar + + kdDebug() << "m_lstPages has " << m_lstPages.count() << " documents" << endl; + if ( m_lstPages.count() > 0 ) + { + kdDebug() << "Activate the document behind" << endl; + switchToPage( m_lstPages.fromLast() ); + } + else + { + kdDebug() << "Revert to initial state (no docs)" << endl; + setRootDocument( 0L ); + partManager()->setActivePart( 0L, 0L ); + mnuSaveAll->setEnabled(false); + partSpecificHelpAction->setEnabled(false); + partSpecificHelpAction->setText(i18n("Part Handbook")); + } + + // Now delete the old view and page + // Don't do it before, because setActivePart will call slotActivePartChanged, + // which needs the old view (to unplug it and its plugins) + delete oldPage.m_pView; + if ( oldPage.m_pDoc->viewCount() <= 1 ) + delete oldPage.m_pDoc; + + } + kdDebug() << "m_lstPages has " << m_lstPages.count() << " documents" << endl; +} + +bool KoShellWindow::queryClose() +{ + // Save current doc and views + QPtrList<KoView> currentViews; + KoDocument * currentDoc = 0L; + bool ok = true; + if (m_activePage != m_lstPages.end()) + { + currentDoc = (*m_activePage).m_pDoc; + currentViews.append((*m_activePage).m_pView); + + // This one is called by slotFileQuit and by the X button. + // We have to check for unsaved docs... + QValueList<Page>::Iterator it = m_lstPages.begin(); + for( ; it != m_lstPages.end(); ++it ) + { + // This is quite a HACK + // We should ask ourselves, to get a better dialog box + setRootDocumentDirect( (*it).m_pDoc, QPtrList<KoView>() ); + // Test if we can close this doc + if ( !KoMainWindow::queryClose() ) + { + ok = false; // No + break; // abort + } + } + + // Restore current doc and views + setRootDocumentDirect( currentDoc, currentViews ); + } + return ok; +} + +/* +// Should this be an additional action in the File menu ? +bool KoShellWindow::saveAllPages() +{ + // TODO + return false; +} +*/ + +void KoShellWindow::saveSettings() +{ + KoShellSettings::setSidebarWidth( m_pLayout->sizes().first() ); + KoShellSettings::writeConfig(); +} + +QString KoShellWindow::configFile() const +{ + //return readConfigFile( locate( "data", "koshell/koshell_shell.rc" ) ); + return QString::null; // use UI standards only for now +} + +void KoShellWindow::tab_contextMenu(QWidget * w,const QPoint &p) +{ + KPopupMenu menu; + KIconLoader il; + int const mnuSave = menu.insertItem( il.loadIconSet( "filesave", KIcon::Small ), i18n("Save") ); + int const mnuClose = menu.insertItem( il.loadIcon( "fileclose", KIcon::Small ), i18n("Close") ); + + int tabnr = m_pFrame->indexOf( w ); + Page page = m_lstPages[tabnr]; + // disable save if there's nothing to save + if ( !page.m_pDoc->isModified() ) + menu.setItemEnabled( mnuSave, false ); + + // show menu + int const choice = menu.exec(p); + + if( choice == mnuClose ) + { + const int index = m_pFrame->currentPageIndex(); + m_pFrame->setCurrentPage( tabnr ); + slotFileClose(); + if ( index > m_pFrame->currentPageIndex() ) + m_pFrame->setCurrentPage(index-1); + else + m_pFrame->setCurrentPage(index); + } + else if ( choice == mnuSave ) + { + page.m_pView->shell()->slotFileSave(); + } +} + +void KoShellWindow::slotConfigureKeys() +{ + KoView *view = rootView(); + KKeyDialog dlg( this ); + dlg.insert( actionCollection() ); + if ( view ) + dlg.insert( view->actionCollection() ); + if ( rootDocument() ) + dlg.insert( rootDocument()->actionCollection() ); + dlg.configure(); +} + +void KoShellWindow::createShellGUI( bool ) +{ + guiFactory()->addClient( m_client ); +} + +void KoShellWindow::showPartSpecificHelp() +{ + if((m_activePage == m_lstPages.end()) || ((*m_activePage).m_pDoc == 0)) + return; + + kapp->invokeHelp("", (*m_activePage).m_pDoc->instance()->aboutData()->appName(), ""); +} + + +/////////////////// +KoShellGUIClient::KoShellGUIClient( KoShellWindow *window ) : KXMLGUIClient() +{ + setXMLFile( "koshellui.rc", true, true ); + window->mnuSaveAll = new KAction( i18n("Save All"), 0, window, SLOT( saveAll() ), actionCollection(), "save_all" ); + window->mnuSaveAll->setEnabled(false); + window->partSpecificHelpAction = new KAction(i18n("Part Handbook"), "contents", 0, window, SLOT(showPartSpecificHelp()), + actionCollection(), "partSpecificHelp"); + window->partSpecificHelpAction->setEnabled(false); +} + +#include "koshell_shell.moc" diff --git a/koshell/koshell_shell.h b/koshell/koshell_shell.h new file mode 100644 index 00000000..dd0f4c7c --- /dev/null +++ b/koshell/koshell_shell.h @@ -0,0 +1,148 @@ +/* This file is part of the KDE project + Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> + Copyright (C) 1999 Simon Hausmann <hausmann@kde.org> + Copyright (C) 2000-2005 David Faure <faure@kde.org> + Copyright (C) 2005 Sven Lppken <sven@kde.org> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ +#ifndef __koshell_window_h__ +#define __koshell_window_h__ + +#include <KoMainWindow.h> +#include <KoQueryTrader.h> +#include <ktabwidget.h> +#include <qptrlist.h> +#include <qmap.h> +#include <qtoolbutton.h> +#include <qvaluelist.h> + +#include "iconsidepane.h" + +class QVBox; +class QIconView; +class QIconViewItem; +class QSplitter; +class KoDocumentEntry; +class KoView; +class KoShellGUIClient; + +/////// class KoShellWindow //////// + +class KoShellWindow : public KoMainWindow +{ + Q_OBJECT + +public: + + KoShellWindow(); + virtual ~KoShellWindow(); + + virtual void setRootDocument( KoDocument *doc ); + /** + * Update caption from document info - call when document info + * (title in the about page) changes. + */ + virtual void updateCaption(); + + virtual QString configFile() const; + + KAction *mnuSaveAll; + KAction* partSpecificHelpAction; + +protected slots: + + virtual void slotFileNew(); + virtual void slotFileClose(); + virtual void slotFileOpen(); + void saveAll(); + + void showPartSpecificHelp(); + + void slotSidebar_Part(int); + void slotSidebar_Document(int); + void tab_contextMenu(QWidget * ,const QPoint &); + + /** + Used for showing or hiding the sidebar and the components-label. + */ + void slotShowSidebar(); + /** + This slot is called whenever the user clicks on a "component" in the sidebar. It loads a new + document which can be edited with the chosen component. + @param item The component the user clicked on + */ + void slotSidebarItemClicked( QIconViewItem *item ); + void slotKSLoadCompleted(); + void slotKSLoadCanceled (const QString &); + void slotNewDocumentName(); + /** + This slot is called whenever the user clicks on a tab to change the document. It looks for the + changed widget in the list of all pages and calls switchToPage with the iterator which points + to the page corresponding to the widget. + @param widget The current widget + */ + void slotUpdatePart( QWidget* widget ); + +private: + + struct Page + { + KoDocument *m_pDoc; + KoView *m_pView; + int m_id; + }; + + virtual bool queryClose(); + virtual bool openDocumentInternal( const KURL & url, KoDocument * newdoc = 0L ); + virtual void slotConfigureKeys(); + void closeDocument(); + void saveSettings(); + void switchToPage( QValueList<Page>::Iterator it ); + + + QValueList<Page> m_lstPages; + QValueList<Page>::Iterator m_activePage; + + IconSidePane *m_pSidebar; + QLabel *m_pComponentsLabel; + QSplitter *m_pLayout; + KTabWidget *m_pFrame; + QToolButton *m_tabCloseButton; + + // Map of available parts (the int is the koolbar item id) + QMap<int,KoDocumentEntry> m_mapComponents; + + // Saved between openDocument and setRootDocument + KoDocumentEntry m_documentEntry; + + KoShellGUIClient *m_client; + void createShellGUI( bool create = true ); + + int m_grpFile; //the ID number for the component group in the side bar + int m_grpDocuments; //the ID number for the docuemnt group in the side bar +}; + +//////// class KoShellGUIClient ////////// + +class KoShellGUIClient : public KXMLGUIClient +{ +public: + KoShellGUIClient( KoShellWindow *window ); +}; + +#endif // __koshell_window_h__ + diff --git a/koshell/koshellsettings.kcfgc b/koshell/koshellsettings.kcfgc new file mode 100644 index 00000000..9125acbf --- /dev/null +++ b/koshell/koshellsettings.kcfgc @@ -0,0 +1,4 @@ +File=koshell.kcfg +ClassName=KoShellSettings +Singleton=true +Mutators=true
\ No newline at end of file diff --git a/koshell/koshellui.rc b/koshell/koshellui.rc new file mode 100644 index 00000000..429d8fc1 --- /dev/null +++ b/koshell/koshellui.rc @@ -0,0 +1,14 @@ +<!DOCTYPE kpartgui> +<kpartgui name="koshell" version="1"> +<MenuBar> + <Menu name="file"><text>&File</text> + <Action name="save_all"/> + </Menu> + <Menu name="settings"><Text>&Settings</Text> + <Action name="show_sidebar"/> + </Menu> + <Menu name="help"> + <Action name="partSpecificHelp"/> + </Menu> +</MenuBar> +</kpartgui> |