diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | e9ae80694875f869892f13f4fcaf1170a00dea41 (patch) | |
tree | aa2f8d8a217e2d376224c8d46b7397b68d35de2d /lib | |
download | tdewebdev-e9ae80694875f869892f13f4fcaf1170a00dea41.tar.gz tdewebdev-e9ae80694875f869892f13f4fcaf1170a00dea41.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdewebdev@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'lib')
96 files changed, 26299 insertions, 0 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am new file mode 100644 index 00000000..e024a39e --- /dev/null +++ b/lib/Makefile.am @@ -0,0 +1,10 @@ +SUBDIRS = compatibility + + +noinst_LTLIBRARIES = libquantamodule.la + +METASOURCES = AUTO + +libquantamodule_la_SOURCES = qextfileinfo.cpp ksavealldialog.cpp + +INCLUDES = $(all_includes) diff --git a/lib/compatibility/Makefile.am b/lib/compatibility/Makefile.am new file mode 100644 index 00000000..63242e4b --- /dev/null +++ b/lib/compatibility/Makefile.am @@ -0,0 +1,17 @@ +if include_qextmdi +KMDI_SUBDIR = kmdi +endif + +if include_knewstuff +KNEWSTUFF_SUBDIR = knewstuff +endif + + +SUBDIRS = $(KMDI_SUBDIR) $(KNEWSTUFF_SUBDIR) + +#enable the below when there is something in the compatibility lib +#noinst_LTLIBRARIES = libcompat.la +#libcompat_la_SOURCES = + +#AM_CPPFLAGS = $(all_includes) +METASOURCES = AUTO diff --git a/lib/compatibility/kmdi/Makefile.am b/lib/compatibility/kmdi/Makefile.am new file mode 100644 index 00000000..3fdc0cfb --- /dev/null +++ b/lib/compatibility/kmdi/Makefile.am @@ -0,0 +1,21 @@ +# Here resides the library of general KDevelop-related utilities, +# which may be linked by any plugin or part. This is installed +# as a shared library, including header files + + +INCLUDES = $(all_includes) + +noinst_LTLIBRARIES = libquantakmdi.la +libquantakmdi_la_LDFLAGS = $(all_libraries) -no-undefined +libquantakmdi_la_LIBADD = $(top_builddir)/lib/compatibility/kmdi/qextmdi/libquantaqextmdi.la -lktexteditor $(LIB_KPARTS) $(LIB_KIO) +libquantakmdi_la_SOURCES = dummy.cpp + + +SUBDIRS = qextmdi + +AM_CFLAGS = +AM_CXXFLAGS = +AM_FFLAGS = +#lib_LIBRARIES = libquanta_la +#libquanta_la_SOURCES = +#libquanta_la_LDFLAGS = diff --git a/lib/compatibility/kmdi/dummy.cpp b/lib/compatibility/kmdi/dummy.cpp new file mode 100644 index 00000000..8d1c8b69 --- /dev/null +++ b/lib/compatibility/kmdi/dummy.cpp @@ -0,0 +1 @@ + diff --git a/lib/compatibility/kmdi/qextmdi/Makefile.am b/lib/compatibility/kmdi/qextmdi/Makefile.am new file mode 100644 index 00000000..9c683679 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/Makefile.am @@ -0,0 +1,18 @@ +# Here resides the qextmdi library. + +INCLUDES = -I$(top_srcdir)/lib/compatibility/kmdi/qextmdi/res -I$(top_builddir)/lib/compatibility/kmdi/qextmdi $(all_includes) + +noinst_LTLIBRARIES = libquantaqextmdi.la +libquantaqextmdi_la_LDFLAGS = $(all_libraries) +libquantaqextmdi_la_LIBADD = $(LIB_KPARTS) + +libquantaqextmdi_la_SOURCES = kmdichildarea.cpp kmdichildfrm.cpp kmdichildfrmcaption.cpp \ + kmdichildview.cpp kmdimainfrm.cpp kmditaskbar.cpp \ + kmultitabbar.cpp \ + kmditoolviewaccessor.cpp kmdidocumentviewtabwidget.cpp kmdifocuslist.cpp \ + kmdiguiclient.cpp \ + ktabwidget.cpp ktabbar.cpp kdockwidget.cpp kdockwidget_private.cpp kmdidockcontainer.cpp + +METASOURCES = AUTO + +#AM_CXXFLAGS = -DNO_INCLUDE_MOCFILES diff --git a/lib/compatibility/kmdi/qextmdi/kdelibs_export.h b/lib/compatibility/kmdi/qextmdi/kdelibs_export.h new file mode 100644 index 00000000..d6244357 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kdelibs_export.h @@ -0,0 +1,87 @@ +/* + This file is part of the KDE libraries + Copyright (C) 2004 Jaroslaw Staniek <js@iidea.pl> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + 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. +*/ + +#ifndef _KDELIBS_EXPORT_H +#define _KDELIBS_EXPORT_H + +/* needed for KDE_EXPORT macros */ +#include <kdemacros.h> + +/* needed, because e.g. Q_OS_UNIX is so frequently used */ +#include <qglobal.h> + +#ifdef Q_WS_WIN +#include <kdelibs_export_win.h> + +#else /* Q_OS_UNIX */ + +#undef KDE_EXPORT +#define KDE_EXPORT + +/* export statements for unix */ +#define KDECORE_EXPORT KDE_EXPORT +#define KDEUI_EXPORT KDE_EXPORT +#define KDEFX_EXPORT KDE_EXPORT +#define KDEPRINT_EXPORT KDE_EXPORT +#define KDNSSD_EXPORT KDE_EXPORT +#define KIO_EXPORT KDE_EXPORT +#define DCOP_EXPORT KDE_EXPORT +#define KPARTS_EXPORT KDE_EXPORT +#define KTEXTEDITOR_EXPORT KDE_EXPORT +#define KABC_EXPORT KDE_EXPORT +#define KDESU_EXPORT KDE_EXPORT +#define KVCARD_EXPORT KDE_EXPORT +#define KRESOURCES_EXPORT KDE_EXPORT +#define KSTYLE_EXPORT KDE_EXPORT +#define KHTML_EXPORT KDE_EXPORT +#define KMDI_EXPORT KDE_EXPORT +#define KUTILS_EXPORT KDE_EXPORT +#define KATEPARTINTERFACES_EXPORT KDE_EXPORT +#define KATEPART_EXPORT KDE_EXPORT +#define KMID_EXPORT KDE_EXPORT +#define KIMPROXY_EXPORT KDE_EXPORT +#define KDE_ARTS_EXPORT KDE_EXPORT + +#define KPATH_SEPARATOR ':' + +#ifndef O_BINARY +#define O_BINARY 0 /* for open() */ +#endif + +#endif + +#endif /*_KDELIBS_EXPORT_H*/ + +/* workaround for kdecore: stupid moc's grammar doesn't accept two macros + between 'class' keyword and <classname>: */ +#ifdef KDE_DEPRECATED +# ifndef KDECORE_EXPORT_DEPRECATED +# define KDECORE_EXPORT_DEPRECATED KDE_DEPRECATED KDECORE_EXPORT +# endif +# ifndef KIO_EXPORT_DEPRECATED +# define KIO_EXPORT_DEPRECATED KDE_DEPRECATED KIO_EXPORT +# endif +# ifndef KDEUI_EXPORT_DEPRECATED +# define KDEUI_EXPORT_DEPRECATED KDE_DEPRECATED KDEUI_EXPORT +# endif +# ifndef KABC_EXPORT_DEPRECATED +# define KABC_EXPORT_DEPRECATED KDE_DEPRECATED KABC_EXPORT +# endif +#endif +/* (let's add KDE****_EXPORT_DEPRECATED for other libraries if it's needed) */ diff --git a/lib/compatibility/kmdi/qextmdi/kdemacros.h.in b/lib/compatibility/kmdi/qextmdi/kdemacros.h.in new file mode 100644 index 00000000..95ac5d8e --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kdemacros.h.in @@ -0,0 +1,208 @@ +/* This file is part of the KDE libraries + Copyright (c) 2002-2003 KDE Team + + 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. +*/ + +#ifndef _KDE_MACROS_H_ +#define _KDE_MACROS_H_ + +/* Set by configure */ +#undef __KDE_HAVE_GCC_VISIBILITY + +/** + * The KDE_NO_EXPORT macro marks the symbol of the given variable + * to be hidden. A hidden symbol is stripped during the linking step, + * so it can't be used from outside the resulting library, which is similar + * to static. However, static limits the visibility to the current + * compilation unit. hidden symbols can still be used in multiple compilation + * units. + * + * \code + * int KDE_NO_EXPORT foo; + * int KDE_EXPORT bar; + * \end + */ + +#ifdef __KDE_HAVE_GCC_VISIBILITY +#define KDE_NO_EXPORT __attribute__ ((visibility("hidden"))) +#define KDE_EXPORT __attribute__ ((visibility("default"))) +#elif defined(Q_WS_WIN) +#define KDE_NO_EXPORT +#define KDE_EXPORT __declspec(dllexport) +#else +#define KDE_NO_EXPORT +#define KDE_EXPORT +#endif + +/** + * KDE_Q_EXPORT_PLUGIN is a workaround for Qt not being able to + * cope with symbol visibility. + */ +#define KDE_Q_EXPORT_PLUGIN(PLUGIN) \ + Q_EXTERN_C KDE_EXPORT const char* qt_ucm_query_verification_data(); \ + Q_EXTERN_C KDE_EXPORT QUnknownInterface* ucm_instantiate(); \ + Q_EXPORT_PLUGIN(PLUGIN) + +/** + * The KDE_PACKED can be used to hint the compiler that a particular + * structure or class should not contain unnecessary paddings. + */ + +#ifdef __GNUC__ +#define KDE_PACKED __attribute__((__packed__)) +#else +#define KDE_PACKED +#endif + +/** + * The KDE_DEPRECATED macro can be used to trigger compile-time warnings + * with newer compilers when deprecated functions are used. + * + * For non-inline functions, the macro gets inserted at the very end of the + * function declaration, right before the semicolon: + * + * \code + * DeprecatedConstructor() KDE_DEPRECATED; + * void deprecatedFunctionA() KDE_DEPRECATED; + * int deprecatedFunctionB() const KDE_DEPRECATED; + * \endcode + * + * Functions which are implemented inline are handled differently: for them, + * the KDE_DEPRECATED macro is inserted at the front, right before the return + * type, but after "static" or "virtual": + * + * \code + * KDE_DEPRECATED void deprecatedInlineFunctionA() { .. } + * virtual KDE_DEPRECATED int deprecatedInlineFunctionB() { .. } + * static KDE_DEPRECATED bool deprecatedInlineFunctionC() { .. } + * \end + * + * You can also mark whole structs or classes as deprecated, by inserting the + * KDE_DEPRECATED macro after the struct/class keyword, but before the + * name of the struct/class: + * + * \code + * class KDE_DEPRECATED DeprecatedClass { }; + * struct KDE_DEPRECATED DeprecatedStruct { }; + * \endcode + * + * \note + * It does not make much sense to use the KDE_DEPRECATED keyword for a Qt signal; + * this is because usually get called by the class which they belong to, + * and one'd assume that a class author doesn't use deprecated methods of his + * own class. The only exception to this are signals which are connected to + * other signals; they get invoked from moc-generated code. In any case, + * printing a warning message in either case is not useful. + * For slots, it can make sense (since slots can be invoked directly) but be + * aware that if the slots get triggered by a signal, the will get called from + * moc code as well and thus the warnings are useless. + * + * \par + * Also note that it is not possible to use KDE_DEPRECATED for classes which + * use the k_dcop keyword (to indicate a DCOP interface declaration); this is + * because the dcopidl program would choke on the unexpected declaration + * syntax. + */ + +#ifndef KDE_DEPRECATED +#if __GNUC__ - 0 > 3 || (__GNUC__ - 0 == 3 && __GNUC_MINOR__ - 0 >= 2) + /* gcc >= 3.2 */ +# define KDE_DEPRECATED __attribute__ ((deprecated)) +#elif defined(_MSC_VER) && (_MSC_VER >= 1300) + /* msvc >= 7 */ +# define KDE_DEPRECATED __declspec(deprecated) +#else +# define KDE_DEPRECATED +#endif +#endif + +/** + * The KDE_ISLIKELY macro tags a boolean expression as likely to evaluate to + * 'true'. When used in an if ( ) statement, it gives a hint to the compiler + * that the following codeblock is likely to get executed. Providing this + * information helps the compiler to optimize the code for better performance. + * Using the macro has an insignificant code size or runtime memory footprint impact. + * The code semantics is not affected. + * + * \note + * Providing wrong information ( like marking a condition that almost never + * passes as 'likely' ) will cause a significant runtime slowdown. Therefore only + * use it for cases where you can be sure about the odds of the expression to pass + * in all cases ( independent from e.g. user configuration ). + * + * \par + * The KDE_ISUNLIKELY macro tags an expression as unlikely evaluating to 'true'. + * + * \note + * Do NOT use ( !KDE_ISLIKELY(foo) ) as an replacement for KDE_ISUNLIKELY ! + * + * \code + * if ( KDE_ISUNLIKELY( testsomething() ) ) + * abort(); // assume its unlikely that the application aborts + * \endcode + */ +#if __GNUC__ - 0 >= 3 +# define KDE_ISLIKELY( x ) __builtin_expect(!!(x),1) +# define KDE_ISUNLIKELY( x ) __builtin_expect(!!(x),0) +#else +# define KDE_ISLIKELY( x ) ( x ) +# define KDE_ISUNLIKELY( x ) ( x ) +#endif + +/** + * This macro, and it's friends going up to 10 reserve a fixed number of virtual + * functions in a class. Because adding virtual functions to a class changes the + * size of the vtable, adding virtual functions to a class breaks binary + * compatibility. However, by using this macro, and decrementing it as new + * virtual methods are added, binary compatibility can still be preserved. + * + * \note The added functions must be added to the header at the same location + * as the macro; changing the order of virtual functions in a header is also + * binary incompatible as it breaks the layout of the vtable. + */ + +#define RESERVE_VIRTUAL_1 \ + virtual void reservedVirtual1() {} +#define RESERVE_VIRTUAL_2 \ + virtual void reservedVirtual2() {} \ + RESERVE_VIRTUAL_1 +#define RESERVE_VIRTUAL_3 \ + virtual void reservedVirtual3() {} \ + RESERVE_VIRTUAL_2 +#define RESERVE_VIRTUAL_4 \ + virtual void reservedVirtual4() {} \ + RESERVE_VIRTUAL_3 +#define RESERVE_VIRTUAL_5 \ + virtual void reservedVirtual5() {} \ + RESERVE_VIRTUAL_4 +#define RESERVE_VIRTUAL_6 \ + virtual void reservedVirtual6() {} \ + RESERVE_VIRTUAL_5 +#define RESERVE_VIRTUAL_7 \ + virtual void reservedVirtual7() {} \ + RESERVE_VIRTUAL_6 +#define RESERVE_VIRTUAL_8 \ + virtual void reservedVirtual8() {} \ + RESERVE_VIRTUAL_7 +#define RESERVE_VIRTUAL_9 \ + virtual void reservedVirtual9() {} \ + RESERVE_VIRTUAL_8 +#define RESERVE_VIRTUAL_10 \ + virtual void reservedVirtual10() {} \ + RESERVE_VIRTUAL_9 + +#endif /* _KDE_MACROS_H_ */ diff --git a/lib/compatibility/kmdi/qextmdi/kdockwidget.cpp b/lib/compatibility/kmdi/qextmdi/kdockwidget.cpp new file mode 100644 index 00000000..1a1e56ae --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kdockwidget.cpp @@ -0,0 +1,3273 @@ + +/* This file is part of the KDE libraries + Copyright (C) 2000 Max Judin <novaprint@mtu-net.ru> + Copyright (C) 2002,2003 Joseph Wenninger <jowenn@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 version 2 as published by the Free Software Foundation. + + 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 "kdockwidget.h" +#include "kdockwidget_private.h" +#include "kdockwidget_p.h" + +#include <qapplication.h> +#include <qlayout.h> +#include <qpainter.h> +#include <qobjectlist.h> +#include <qstrlist.h> +#include <qcursor.h> +#include <qwidgetlist.h> +#include <qtabwidget.h> +#include <qtooltip.h> +#include <qstyle.h> + +#ifndef NO_KDE2 +#include <kconfig.h> +#include <kglobal.h> +#include <klocale.h> +#include <ktoolbar.h> +#include <kpopupmenu.h> +#include <kwin.h> +#include <kdebug.h> +#include <kglobalsettings.h> + +#include "config.h" +#ifdef Q_WS_X11 +#include <X11/X.h> +#include <X11/Xlib.h> +#endif + +#else +#include <qtoolbar.h> +#include <qpopupmenu.h> +#endif + +#include <stdlib.h> + +#undef BORDERLESS_WINDOWS + +#define DOCK_CONFIG_VERSION "0.0.5" + +static const char* const dockback_xpm[]={ +"6 6 2 1", +"# c black", +". c None", +"......", +".#....", +"..#..#", +"...#.#", +"....##", +"..####"}; + +static const char* const todesktop_xpm[]={ +"5 5 2 1", +"# c black", +". c None", +"####.", +"##...", +"#.#..", +"#..#.", +"....#"}; + +static const char* const not_close_xpm[]={ +"5 5 2 1", +"# c black", +". c None", +"#####", +"#...#", +"#...#", +"#...#", +"#####"}; + +/** + * A special kind of KMainWindow that is able to have dockwidget child widgets. + * + * The main widget should be a dockwidget where other dockwidgets can be docked to + * the left, right, top, bottom or to the middle. + * Furthermore, the KDockMainWindow has got the KDocManager and some data about the dock states. + * + * @author Max Judin. +*/ +KDockMainWindow::KDockMainWindow( QWidget* parent, const char *name, WFlags f) +:KMainWindow( parent, name, f ) +{ + QString new_name = QString(name) + QString("_DockManager"); + dockManager = new KDockManager( this, new_name.latin1() ); + mainDockWidget = 0L; +} + +KDockMainWindow::~KDockMainWindow() +{ + delete dockManager; +} + +void KDockMainWindow::setMainDockWidget( KDockWidget* mdw ) +{ + if ( mainDockWidget == mdw ) return; + mainDockWidget = mdw; + dockManager->setMainDockWidget2(mdw); +} + +void KDockMainWindow::setView( QWidget *view ) +{ + if ( view->isA("KDockWidget") ){ + if ( view->parent() != this ) ((KDockWidget*)view)->applyToWidget( this ); + } + +#ifndef NO_KDE2 + KMainWindow::setCentralWidget(view); +#else + QMainWindow::setCentralWidget(view); +#endif +} + +KDockWidget* KDockMainWindow::createDockWidget( const QString& name, const QPixmap &pixmap, QWidget* parent, const QString& strCaption, const QString& strTabPageLabel) +{ + return new KDockWidget( dockManager, name.latin1(), pixmap, parent, strCaption, strTabPageLabel ); +} + +void KDockMainWindow::makeDockVisible( KDockWidget* dock ) +{ + if ( dock ) + dock->makeDockVisible(); +} + +void KDockMainWindow::makeDockInvisible( KDockWidget* dock ) +{ + if ( dock ) + dock->undock(); +} + +void KDockMainWindow::makeWidgetDockVisible( QWidget* widget ) +{ + makeDockVisible( dockManager->findWidgetParentDock(widget) ); +} + +void KDockMainWindow::writeDockConfig(QDomElement &base) +{ + dockManager->writeConfig(base); +} + +void KDockMainWindow::readDockConfig(QDomElement &base) +{ + dockManager->readConfig(base); +} + +#ifndef NO_KDE2 +void KDockMainWindow::writeDockConfig( KConfig* c, QString group ) +{ + dockManager->writeConfig( c, group ); +} + +void KDockMainWindow::readDockConfig( KConfig* c, QString group ) +{ + dockManager->readConfig( c, group ); +} +#endif + +void KDockMainWindow::slotDockWidgetUndocked() +{ + QObject* pSender = (QObject*) sender(); + if (!pSender->inherits("KDockWidget")) return; + KDockWidget* pDW = (KDockWidget*) pSender; + emit dockWidgetHasUndocked( pDW); +} + +/*************************************************************************/ +KDockWidgetAbstractHeaderDrag::KDockWidgetAbstractHeaderDrag( KDockWidgetAbstractHeader* parent, KDockWidget* dock, const char* name ) +:QFrame( parent, name ) +{ + dw = dock; + installEventFilter( dock->dockManager() ); +} +/*************************************************************************/ +KDockWidgetHeaderDrag::KDockWidgetHeaderDrag( KDockWidgetAbstractHeader* parent, KDockWidget* dock, const char* name ) +:KDockWidgetAbstractHeaderDrag( parent, dock, name ) +{ +} + +void KDockWidgetHeaderDrag::paintEvent( QPaintEvent* ) +{ + QPainter paint; + + paint.begin( this ); + + style().drawPrimitive (QStyle::PE_DockWindowHandle, &paint, QRect(0,0,width(), height()), colorGroup()); + + paint.end(); +} +/*************************************************************************/ +KDockWidgetAbstractHeader::KDockWidgetAbstractHeader( KDockWidget* parent, const char* name ) +:QFrame( parent, name ) +{ +} +/*************************************************************************/ +KDockWidgetHeader::KDockWidgetHeader( KDockWidget* parent, const char* name ) +:KDockWidgetAbstractHeader( parent, name ) +{ +#ifdef BORDERLESS_WINDOWS + setCursor(QCursor(ArrowCursor)); +#endif + d = new KDockWidgetHeaderPrivate( this ); + + layout = new QHBoxLayout( this ); + layout->setResizeMode( QLayout::Minimum ); + + drag = new KDockWidgetHeaderDrag( this, parent ); + + closeButton = new KDockButton_Private( this, "DockCloseButton" ); + QToolTip::add( closeButton, i18n("Close") ); + closeButton->setPixmap( style().stylePixmap (QStyle::SP_TitleBarCloseButton , this)); + closeButton->setFixedSize(closeButton->pixmap()->width(),closeButton->pixmap()->height()); + connect( closeButton, SIGNAL(clicked()), parent, SIGNAL(headerCloseButtonClicked())); + connect( closeButton, SIGNAL(clicked()), parent, SLOT(undock())); + + stayButton = new KDockButton_Private( this, "DockStayButton" ); + QToolTip::add( stayButton, i18n("Freeze the window geometry", "Freeze") ); + stayButton->setToggleButton( true ); + stayButton->setPixmap( const_cast< const char** >(not_close_xpm) ); + stayButton->setFixedSize(closeButton->pixmap()->width(),closeButton->pixmap()->height()); + connect( stayButton, SIGNAL(clicked()), this, SLOT(slotStayClicked())); + + dockbackButton = new KDockButton_Private( this, "DockbackButton" ); + QToolTip::add( dockbackButton, i18n("Dock this window", "Dock") ); + dockbackButton->setPixmap( const_cast< const char** >(dockback_xpm)); + dockbackButton->setFixedSize(closeButton->pixmap()->width(),closeButton->pixmap()->height()); + connect( dockbackButton, SIGNAL(clicked()), parent, SIGNAL(headerDockbackButtonClicked())); + connect( dockbackButton, SIGNAL(clicked()), parent, SLOT(dockBack())); + + d->toDesktopButton = new KDockButton_Private( this, "ToDesktopButton" ); + QToolTip::add( d->toDesktopButton, i18n("Detach") ); + d->toDesktopButton->setPixmap( const_cast< const char** >(todesktop_xpm)); + d->toDesktopButton->setFixedSize(closeButton->pixmap()->width(),closeButton->pixmap()->height()); + connect( d->toDesktopButton, SIGNAL(clicked()), parent, SLOT(toDesktop())); + stayButton->hide(); + + d->dummy = new QWidget( this ); + d->dummy->setFixedSize( 1,closeButton->pixmap()->height() ); + + + layout->addWidget( drag ); + layout->addWidget( dockbackButton ); + layout->addWidget( d->toDesktopButton ); + layout->addWidget( d->dummy); + layout->addWidget( stayButton ); + layout->addWidget( closeButton ); + layout->activate(); + d->dummy->hide(); + drag->setFixedHeight( layout->minimumSize().height() ); +} + +void KDockWidgetHeader::setTopLevel( bool isTopLevel ) +{ + d->topLevel = isTopLevel; + if ( isTopLevel ){ + KDockWidget* par = (KDockWidget*)parent(); + if( par) { + if( par->isDockBackPossible()) + dockbackButton->show(); + else + dockbackButton->hide(); + } + stayButton->hide(); + closeButton->hide(); + d->toDesktopButton->hide(); + drag->setEnabled( true ); + } else { + dockbackButton->hide(); + stayButton->hide(); + if (!d->forceCloseButtonHidden) closeButton->show(); + if( d->showToDesktopButton ) + d->toDesktopButton->show(); + } + layout->activate(); + + bool dontShowDummy=drag->isVisibleTo(this) || dockbackButton->isVisibleTo(this) || + d->toDesktopButton->isVisibleTo(this) || stayButton->isVisibleTo(this) || + closeButton->isVisibleTo(this); + for (QPtrListIterator<KDockButton_Private> it( d->btns );it.current();++it) { + dontShowDummy=dontShowDummy || (it.current()->isVisibleTo(this)); + } + if (dontShowDummy) d->dummy->hide(); else d->dummy->show(); + + updateGeometry(); +} + +void KDockWidgetHeader::forceCloseButtonHidden(bool hidden) { + d->forceCloseButtonHidden=hidden; + if (hidden) closeButton->hide(); + else closeButton->show(); +} + +KDockWidgetHeaderDrag *KDockWidgetHeader::dragPanel() { + return drag; +} + +void KDockWidgetHeader::setDragPanel( KDockWidgetHeaderDrag* nd ) +{ + if ( !nd ) return; + + delete layout; + layout = new QHBoxLayout( this ); + layout->setResizeMode( QLayout::Minimum ); + + delete drag; + drag = nd; + if (drag->parentWidget()!=this) { + drag->reparent(this,QPoint(0,0)); + } + + + layout->addWidget( drag ); + layout->addWidget( dockbackButton ); + layout->addWidget( d->dummy ); + layout->addWidget( d->toDesktopButton ); + layout->addWidget( stayButton ); + bool dontShowDummy=drag->isVisibleTo(this) || dockbackButton->isVisibleTo(this) || + d->toDesktopButton->isVisibleTo(this) || stayButton->isVisibleTo(this) || + closeButton->isVisibleTo(this); + for (QPtrListIterator<KDockButton_Private> it( d->btns );it.current();++it) { + layout->addWidget(it.current()); + dontShowDummy=dontShowDummy || (it.current()->isVisibleTo(this)); + } + if (dontShowDummy) d->dummy->hide(); else d->dummy->show(); + layout->addWidget( closeButton ); + layout->activate(); + kdDebug(282)<<"KdockWidgetHeader::setDragPanel:minimum height="<<layout->minimumSize().height()<<endl; +#ifdef __GNUC__ +#warning FIXME +#endif + drag->setFixedHeight( closeButton->height()); // /*layout->minimumS*/sizeHint().height() ); +} + +void KDockWidgetHeader::addButton(KDockButton_Private* btn) { + if (!btn) return; + + if (btn->parentWidget()!=this) { + btn->reparent(this,QPoint(0,0)); + } + btn->setFixedSize(closeButton->pixmap()->width(),closeButton->pixmap()->height()); + if (!d->btns.containsRef(btn)) d->btns.append(btn); + + btn->show(); + + delete layout; + layout = new QHBoxLayout( this ); + layout->setResizeMode( QLayout::Minimum ); + + layout->addWidget( drag ); + layout->addWidget( dockbackButton ); + layout->addWidget( d->toDesktopButton ); + layout->addWidget( d->dummy); + layout->addWidget( stayButton ); + bool dontShowDummy=drag->isVisibleTo(this) || dockbackButton->isVisibleTo(this) || + d->toDesktopButton->isVisibleTo(this) || stayButton->isVisibleTo(this) || + closeButton->isVisibleTo(this); + for (QPtrListIterator<KDockButton_Private> it( d->btns );it.current();++it) { + layout->addWidget(it.current()); + dontShowDummy=dontShowDummy || (it.current()->isVisibleTo(this)); + } + if (dontShowDummy) d->dummy->hide(); else d->dummy->show(); + layout->addWidget( closeButton ); + layout->activate(); + drag->setFixedHeight( layout->minimumSize().height() ); +} + +void KDockWidgetHeader::removeButton(KDockButton_Private* btn) { + if (btn->parentWidget()==this) { + if (d->btns.containsRef(btn)) d->btns.removeRef(btn); + delete btn; + } +} + + +void KDockWidgetHeader::slotStayClicked() +{ + setDragEnabled(!stayButton->isOn()); +} + +bool KDockWidgetHeader::dragEnabled() const +{ + return drag->isEnabled(); +} + +void KDockWidgetHeader::showUndockButton(bool show) +{ + kdDebug(282)<<"KDockWidgetHeader::showUndockButton("<<show<<")"<<endl; + if( d->showToDesktopButton == show ) + return; + + d->showToDesktopButton = show; + if( !show || d->topLevel ) + d->toDesktopButton->hide( ); + else + d->toDesktopButton->show( ); +} + +void KDockWidgetHeader::setDragEnabled(bool b) +{ + stayButton->setOn(!b); + closeButton->setEnabled(b); + drag->setEnabled(b); +} + +#ifndef NO_KDE2 +void KDockWidgetHeader::saveConfig( KConfig* c ) +{ + c->writeEntry( QString("%1%2").arg(parent()->name()).arg(":stayButton"), stayButton->isOn() ); +} + +void KDockWidgetHeader::loadConfig( KConfig* c ) +{ + setDragEnabled( !c->readBoolEntry( QString("%1%2").arg(parent()->name()).arg(":stayButton"), false ) ); +} +#endif + +/*************************************************************************/ + +class KDockManager::KDockManagerPrivate +{ +public: + /** + * This rectangle is used to highlight the current dockposition. It stores global screen coordinates. + */ + QRect dragRect; + + /** + * This rectangle is used to erase the previously highlighted dockposition. It stores global screen coordinates. + */ + QRect oldDragRect; + + /** + * This flag stores the information if dragging is ready to start. Used between mousePress and mouseMove event. + */ + bool readyToDrag; + + /** + * This variable stores the offset of the mouse cursor to the upper left edge of the current drag widget. + */ + QPoint dragOffset; + + /** + * These flags store information about the splitter behavior + */ + bool splitterOpaqueResize; + bool splitterKeepSize; + bool splitterHighResolution; + + QGuardedPtr<KDockWidget> mainDockWidget; + + QObjectList containerDocks; + + QGuardedPtr<KDockWidget> leftContainer; + QGuardedPtr<KDockWidget> topContainer; + QGuardedPtr<KDockWidget> rightContainer; + QGuardedPtr<KDockWidget> bottomContainer; + int m_readDockConfigMode; +}; + + +/*************************************************************************/ +KDockWidget::KDockWidget( KDockManager* dockManager, const char* name, const QPixmap &pixmap, QWidget* parent, const QString& strCaption, const QString& strTabPageLabel, WFlags f) +#ifdef BORDERLESS_WINDOWS +: QWidget( parent, name, f )//| WType_Dialog | WStyle_Customize | WStyle_NoBorder ) +#else +: QWidget( parent, name, f ) +#endif + ,formerBrotherDockWidget(0L) + ,currentDockPos(DockNone) + ,formerDockPos(DockNone) + ,widget(0L) + ,pix(new QPixmap(pixmap)) + ,prevSideDockPosBeforeDrag(DockNone) + ,isGroup(false) +{ + d = new KDockWidgetPrivate(); // create private data + + d->_parent = parent; + + layout = new QVBoxLayout( this ); + layout->setResizeMode( QLayout::Minimum ); + + manager = dockManager; + manager->childDock->append( this ); + installEventFilter( manager ); + + eDocking = DockFullDocking; + sDocking = DockFullSite; + + header = 0L; + setHeader( new KDockWidgetHeader( this, "AutoCreatedDockHeader" ) ); + + if( strCaption.isNull() ) + setCaption( name ); + else + setCaption( strCaption); + + if( strTabPageLabel == " ") + setTabPageLabel( caption()); + else + setTabPageLabel( strTabPageLabel); + + isTabGroup = false; + d->isContainer =false; + setIcon( pixmap); + widget = 0L; + + QObject::connect(this, SIGNAL(hasUndocked()), manager->main, SLOT(slotDockWidgetUndocked()) ); + applyToWidget( parent, QPoint(0,0) ); +} + +void KDockWidget::setPixmap(const QPixmap& pixmap) { + delete pix; + pix=new QPixmap(pixmap); + setIcon(*pix); + KDockTabGroup *dtg=parentDockTabGroup(); + if (dtg) + dtg->changeTab(this,pixmap,dtg->tabLabel(this)); + QWidget *contWid=parentDockContainer(); + if (contWid) { + KDockContainer *x = dynamic_cast<KDockContainer*>(contWid); + if (x) { + x->setPixmap(this,pixmap); + } + } +} + +const QPixmap& KDockWidget::pixmap() const { + return *pix; +} + +KDockWidget::~KDockWidget() +{ + d->pendingDtor = true; + if ( !manager->undockProcess ){ + d->blockHasUndockedSignal = true; + undock(); + d->blockHasUndockedSignal = false; + } + + if (latestKDockContainer()) { + KDockContainer *x = dynamic_cast<KDockContainer*>(latestKDockContainer()); + if (x) { + x->removeWidget(this); + } + } + emit iMBeingClosed(); + if (manager->d) manager->d->containerDocks.remove(this); + manager->childDock->remove( this ); + delete pix; + delete d; // destroy private data + d=0; +} + +void KDockWidget::paintEvent(QPaintEvent* pe) +{ + QWidget::paintEvent(pe); + QPainter paint; + paint.begin( this ); + style().drawPrimitive (QStyle::PE_Panel, &paint, QRect(0,0,width(), height()), colorGroup()); + paint.end(); +} + +void KDockWidget::leaveEvent(QEvent *e) +{ + QWidget::leaveEvent(e); +#ifdef BORDERLESS_WINDOWS + if (parent()) return; +// setCursor(QCursor(ArrowCursor)); +#endif +} + +void KDockWidget::mousePressEvent(QMouseEvent* mme) +{ +#ifdef BORDERLESS_WINDOWS + if (!parent()) + { + kdDebug(282)<<"KDockWidget::mousePressEvent"<<endl; + + bool bbottom; + bool bleft; + bool bright; + bool btop; + int styleheight; + QPoint mp; + mp=mme->pos(); + styleheight=2*style().pixelMetric(QStyle::PM_DefaultFrameWidth,this); + bbottom=mp.y()>=height()-styleheight; + btop=mp.y()<=styleheight; + bleft=mp.x()<=styleheight; + bright=mp.x()>=width()-styleheight; + kdDebug(282)<<"mousemovevent"<<endl; + d->resizing=true; + if (bright) + { + if (btop) + { + d->resizeMode=KDockWidgetPrivate::ResizeTopRight; + d->resizePos=QPoint(width(),0)-mme->pos(); + + } + else + { + d->resizePos=QPoint(width(),height())-mme->pos(); + if (bbottom) d->resizeMode=KDockWidgetPrivate::ResizeBottomRight; + else d->resizeMode=KDockWidgetPrivate::ResizeRight; + } + } + else if (bleft) + { + if (btop) setCursor(QCursor(SizeFDiagCursor)); + else + if (bbottom) setCursor(QCursor(SizeBDiagCursor)); + else setCursor(QCursor(SizeHorCursor)); + } + else + if (bbottom) + { + d->resizeMode=KDockWidgetPrivate::ResizeBottom; + d->resizePos=QPoint(0,height())-mme->pos(); + } + else + if (btop) setCursor(QCursor(SizeVerCursor)); + else d->resizing=false; + + if (d->resizing) grabMouse(cursor()); + + } +#endif + QWidget::mousePressEvent(mme); +} + +void KDockWidget::mouseReleaseEvent(QMouseEvent* ev) +{ +#ifdef BORDERLESS_WINDOWS + d->resizing=false; + releaseMouse(); +#endif + QWidget::mouseReleaseEvent(ev); +} + +void KDockWidget::mouseMoveEvent(QMouseEvent* mme) +{ + QWidget::mouseMoveEvent(mme); +#ifdef BORDERLESS_WINDOWS + if (parent()) return; + + if (d->resizing) + { + switch (d->resizeMode) + { + case KDockWidgetPrivate::ResizeRight: + resize(mme->pos().x()+d->resizePos.x(),height()); + break; + case KDockWidgetPrivate::ResizeBottomRight: + resize(mme->pos().x()+d->resizePos.x(),mme->pos().y()+d->resizePos.y()); + break; + case KDockWidgetPrivate::ResizeBottom: + resize(width(),mme->pos().y()+d->resizePos.y()); + break; + default: + break; + } + return; + } + + + bool bbottom; + bool bleft; + bool bright; + bool btop; + int styleheight; + QPoint mp; + mp=mme->pos(); + styleheight=2*style().pixelMetric(QStyle::PM_DefaultFrameWidth,this); + bbottom=mp.y()>=height()-styleheight; + btop=mp.y()<=styleheight; + bleft=mp.x()<=styleheight; + bright=mp.x()>=width()-styleheight; + kdDebug(282)<<"mousemovevent"<<endl; + if (bright) + { + if (btop) setCursor(QCursor(SizeBDiagCursor)); + else + if (bbottom) setCursor(QCursor(SizeFDiagCursor)); + else setCursor(QCursor(SizeHorCursor)); + } + else if (bleft) + { + if (btop) setCursor(QCursor(SizeFDiagCursor)); + else + if (bbottom) setCursor(QCursor(SizeBDiagCursor)); + else setCursor(QCursor(SizeHorCursor)); + } + else + if (bbottom || btop) setCursor(QCursor(SizeVerCursor)); + else setCursor(QCursor(ArrowCursor)); +#endif +} + +void KDockWidget::setLatestKDockContainer(QWidget* container) +{ + if (container) + { + if (dynamic_cast<KDockContainer*>(container)) + d->container=container; + else + d->container=0; + } +} + +QWidget* KDockWidget::latestKDockContainer() +{ + if (!(d->container)) return 0; + if (dynamic_cast<KDockContainer*>(d->container.operator->())) return d->container; + return 0; +} + + + +KDockWidgetAbstractHeader *KDockWidget::getHeader() { + return header; +} + +void KDockWidget::setHeader( KDockWidgetAbstractHeader* h ) +{ + if ( !h ) return; + + if ( header ){ + delete header; + delete layout; + header = h; + layout = new QVBoxLayout( this ); + layout->setResizeMode( QLayout::Minimum ); + layout->addWidget( header ); + setWidget( widget ); + } else { + header = h; + layout->addWidget( header ); + } + kdDebug(282)<<caption()<<": KDockWidget::setHeader"<<endl; + setEnableDocking(eDocking); +} + +void KDockWidget::setEnableDocking( int pos ) +{ + eDocking = pos; + if( header && header->inherits( "KDockWidgetHeader" ) ) + ( ( KDockWidgetHeader* ) header )->showUndockButton( pos & DockDesktop ); + updateHeader(); +} + +void KDockWidget::updateHeader() +{ + if ( parent() ){ +#ifdef BORDERLESS_WINDOWS + layout->setMargin(0); + setMouseTracking(false); + setCursor(QCursor(ArrowCursor)); +#endif + + if ( (parent() == manager->main) || isGroup || (eDocking == KDockWidget::DockNone) ){ + header->hide(); + } else { + header->setTopLevel( false ); + if (widget && dynamic_cast<KDockContainer*>(widget)) + header->hide(); + else + header->show(); + } + } else { + header->setTopLevel( true ); + header->show(); +#ifdef BORDERLESS_WINDOWS + layout->setMargin(2*style().pixelMetric(QStyle::PM_DefaultFrameWidth,this)); + setMouseTracking(true); +#endif + } +} + +void KDockWidget::applyToWidget( QWidget* s, const QPoint& p ) +{ + if ( parent() != s ) + { + hide(); + reparent(s, 0, QPoint(0,0), false); + } + + if ( s && s->inherits("KDockMainWindow") ){ + ((KDockMainWindow*)s)->setView( this ); + } + + if ( manager && s == manager->main ){ + setGeometry( QRect(QPoint(0,0), manager->main->geometry().size()) ); + } + + if ( !s ) + { + move(p); + +#ifndef NO_KDE2 +#ifdef Q_WS_X11 + if (d->transient && d->_parent) + XSetTransientForHint( qt_xdisplay(), winId(), d->_parent->winId() ); + +#ifdef BORDERLESS_WINDOWS + KWin::setType( winId(), NET::Override); //d->windowType ); +// setWFlags(WStyle_Customize | WStyle_NoBorder | WStyle_Tool); +#else + KWin::setType( winId(), d->windowType ); +#endif // BORDERLESS_WINDOW +#endif // Q_WS_X11 +#endif + + } + updateHeader(); + + setIcon(*pix); +} + +void KDockWidget::show() +{ + if ( parent() || manager->main->isVisible() ) + if ( !parent() ){ + emit manager->setDockDefaultPos( this ); + emit setDockDefaultPos(); + if ( parent() ){ + makeDockVisible(); + } else { + QWidget::show(); + } + } else { + QWidget::show(); + } +} + +#ifndef NO_KDE2 + +void KDockWidget::setDockWindowType (NET::WindowType windowType) +{ + d->windowType = windowType; + applyToWidget( parentWidget(), QPoint(0,0) ); +} + +#endif + +void KDockWidget::setDockWindowTransient (QWidget *parent, bool transientEnabled) +{ + d->_parent = parent; + d->transient = transientEnabled; + applyToWidget( parentWidget(), QPoint(0,0) ); +} + +QWidget *KDockWidget::transientTo() { + if (d->transient && d->_parent) return d->_parent; else return 0; +} + +bool KDockWidget::event( QEvent *event ) +{ + switch ( event->type() ) + { + #undef FocusIn + case QEvent::FocusIn: + if (widget && !d->pendingFocusInEvent) { + d->pendingFocusInEvent = true; + widget->setFocus(); + } + d->pendingFocusInEvent = false; + break; + case QEvent::ChildRemoved: + if ( widget == ((QChildEvent*)event)->child() ) widget = 0L; + break; + case QEvent::Show: + if ( widget ) widget->show(); + emit manager->change(); + break; + case QEvent::Hide: + if ( widget ) widget->hide(); + emit manager->change(); + break; + case QEvent::CaptionChange: + if ( parentWidget() ){ + if ( parent()->inherits("KDockSplitter") ){ + ((KDockSplitter*)(parent()))->updateName(); + } + if ( parentDockTabGroup() ){ + setDockTabName( parentDockTabGroup() ); + parentDockTabGroup()->setTabLabel( this, tabPageLabel() ); + } + } + break; + case QEvent::Close: + emit iMBeingClosed(); + break; + default: + break; + } + return QWidget::event( event ); +} + +KDockWidget *KDockWidget::findNearestDockWidget(DockPosition pos) +{ + if (!parent()) return 0; + if (!parent()->inherits("KDockSplitter")) return 0; + Orientation orientation=((pos==DockLeft) || (pos==DockRight)) ? Vertical:Horizontal; + if (((KDockSplitter*)(parent()))->orientation()==orientation) + { + KDockWidget *neighbor= + ((pos==DockLeft)||(pos==DockTop))? + static_cast<KDockWidget*>(((KDockSplitter*)(parent()))->getFirst()): + static_cast<KDockWidget*>(((KDockSplitter*)(parent()))->getLast()); + + if (neighbor==this) + return (static_cast<KDockWidget*>(parent()->parent())->findNearestDockWidget(pos)); + else + if (neighbor->getWidget() && (neighbor->getWidget()->qt_cast("KDockTabGroup"))) + return (KDockWidget*)(((KDockTabGroup*)neighbor->getWidget())->page(0)); + else + return neighbor; + } + else + return (static_cast<KDockWidget*>(parent()->parent())->findNearestDockWidget(pos)); + + return 0; +} + + +KDockWidget* KDockWidget::manualDock( KDockWidget* target, DockPosition dockPos, int spliPos, QPoint pos, bool check, int tabIndex ) +{ + if (this == target) + return 0L; // docking to itself not possible +// kdDebug(282)<<"manualDock called "<<endl; + bool succes = true; // tested flag + + // check allowed this dock submit this operations + if ( !(eDocking & (int)dockPos) ){ + succes = false; +// kdDebug(282)<<"KDockWidget::manualDock(): success = false (1)"<<endl; + } + + KDockWidget *tmpTarget; + switch (dockPos) { + case DockLeft:tmpTarget=dockManager()->d->leftContainer; + break; + case DockRight:tmpTarget=dockManager()->d->rightContainer; + break; + case DockBottom:tmpTarget=dockManager()->d->bottomContainer; + break; + case DockTop:tmpTarget=dockManager()->d->topContainer; + break; + default: tmpTarget=0; + } + + if (this!=tmpTarget) { + if (target && (target==dockManager()->d->mainDockWidget) && tmpTarget) { + return manualDock(tmpTarget,DockCenter,spliPos,pos,check,tabIndex); + } + } + + // check allowed target submit this operations + if ( target && !(target->sDocking & (int)dockPos) ){ + succes = false; +// kdDebug(282)<<"KDockWidget::manualDock(): success = false (2)"<<endl; + } + + if ( parent() && !parent()->inherits("KDockSplitter") && !parentDockTabGroup() && + !(dynamic_cast<KDockContainer*>(parent())) && !parentDockContainer()){ +// kdDebug(282)<<"KDockWidget::manualDock(): success = false (3)"<<endl; +// kdDebug(282)<<parent()->name()<<endl; + succes = false; + } + +// kdDebug(282)<<"KDockWidget::manualDock(): success == false "<<endl; + if ( !succes ){ + // try to make another manualDock + KDockWidget* dock_result = 0L; + if ( target && !check ){ + KDockWidget::DockPosition another__dockPos = KDockWidget::DockNone; + switch ( dockPos ){ + case KDockWidget::DockLeft : another__dockPos = KDockWidget::DockRight ; break; + case KDockWidget::DockRight : another__dockPos = KDockWidget::DockLeft ; break; + case KDockWidget::DockTop : another__dockPos = KDockWidget::DockBottom; break; + case KDockWidget::DockBottom: another__dockPos = KDockWidget::DockTop ; break; + default: break; + } + dock_result = target->manualDock( this, another__dockPos, spliPos, pos, true, tabIndex ); + } + return dock_result; + } + // end check block + + d->blockHasUndockedSignal = true; + undock(); + d->blockHasUndockedSignal = false; + + if ( !target ){ + move( pos ); + show(); + emit manager->change(); + return this; + } + +// kdDebug(282)<<"Looking for KDockTabGroup"<<endl; + KDockTabGroup* parentTab = target->parentDockTabGroup(); + if ( parentTab ){ + // add to existing TabGroup + applyToWidget( parentTab ); + parentTab->insertTab( this, icon() ? *icon() : QPixmap(), + tabPageLabel(), tabIndex ); + + QWidget *wantTransient=parentTab->transientTo(); + target->setDockWindowTransient(wantTransient,wantTransient); + + setDockTabName( parentTab ); + if( !toolTipStr.isEmpty()) + parentTab->setTabToolTip( this, toolTipStr); + + currentDockPos = KDockWidget::DockCenter; + emit manager->change(); + return (KDockWidget*)parentTab->parent(); + } + else + { +// kdDebug(282)<<"Looking for KDockContainer"<<endl; + QWidget *contWid=target->parentDockContainer(); + if (!contWid) contWid=target->widget; + if (contWid) + { + KDockContainer *cont=dynamic_cast<KDockContainer*>(contWid); + if (cont) + { + if (latestKDockContainer() && (latestKDockContainer()!=contWid)) { + KDockContainer* dc = dynamic_cast<KDockContainer*>(latestKDockContainer()); + if (dc) { + dc->removeWidget(this); + } + } +// kdDebug(282)<<"KDockContainerFound"<<endl; + applyToWidget( contWid ); + cont->insertWidget( this, icon() ? *icon() : QPixmap(), + tabPageLabel(), tabIndex ); + setLatestKDockContainer(contWid); +// setDockTabName( parentTab ); + if( !toolTipStr.isEmpty()) + cont->setToolTip( this, toolTipStr); + + currentDockPos = KDockWidget::DockCenter; + emit manager->change(); + return (KDockWidget*)(cont->parentDockWidget()); + + } + } + } + + // create a new dockwidget that will contain the target and this + QWidget* parentDock = target->parentWidget(); + KDockWidget* newDock = new KDockWidget( manager, "tempName", QPixmap(""), parentDock ); + newDock->currentDockPos = target->currentDockPos; + + if ( dockPos == KDockWidget::DockCenter ){ + newDock->isTabGroup = true; + } else { + newDock->isGroup = true; + } + newDock->eDocking = (target->eDocking & eDocking) & (~(int)KDockWidget::DockCenter); + + newDock->applyToWidget( parentDock ); + + if ( !parentDock ){ + // dock to a toplevel dockwidget means newDock is toplevel now + newDock->move( target->frameGeometry().topLeft() ); + newDock->resize( target->geometry().size() ); + if ( target->isVisibleToTLW() ) newDock->show(); + } + + // redirect the dockback button to the new dockwidget + if( target->formerBrotherDockWidget ) { + newDock->setFormerBrotherDockWidget(target->formerBrotherDockWidget); + if( formerBrotherDockWidget ) + target->loseFormerBrotherDockWidget(); + } + newDock->formerDockPos = target->formerDockPos; + + + // HERE SOMETING CREATING CONTAINERS SHOULD BE ADDED !!!!! + if ( dockPos == KDockWidget::DockCenter ) + { + KDockTabGroup* tab = new KDockTabGroup( newDock, "_dock_tab"); + QObject::connect(tab, SIGNAL(currentChanged(QWidget*)), d, SLOT(slotFocusEmbeddedWidget(QWidget*))); + newDock->setWidget( tab ); + + target->applyToWidget( tab ); + applyToWidget( tab ); + + + tab->insertTab( target, target->icon() ? *(target->icon()) : QPixmap(), + target->tabPageLabel() ); + + + + if( !target->toolTipString().isEmpty()) + tab->setTabToolTip( target, target->toolTipString()); + + tab->insertTab( this, icon() ? *icon() : QPixmap(), + tabPageLabel(), tabIndex ); + + QRect geom=newDock->geometry(); + QWidget *wantTransient=tab->transientTo(); + newDock->setDockWindowTransient(wantTransient,wantTransient); + newDock->setGeometry(geom); + + if( !toolTipString().isEmpty()) + tab->setTabToolTip( this, toolTipString()); + + setDockTabName( tab ); + tab->show(); + + currentDockPos = DockCenter; + target->formerDockPos = target->currentDockPos; + target->currentDockPos = DockCenter; + } + else { + // if to dock not to the center of the target dockwidget, + // dock to newDock + KDockSplitter* panner = 0L; + if ( dockPos == KDockWidget::DockTop || dockPos == KDockWidget::DockBottom ) panner = new KDockSplitter( newDock, "_dock_split_", Horizontal, spliPos, manager->splitterHighResolution() ); + if ( dockPos == KDockWidget::DockLeft || dockPos == KDockWidget::DockRight ) panner = new KDockSplitter( newDock, "_dock_split_", Vertical , spliPos, manager->splitterHighResolution() ); + newDock->setWidget( panner ); + + panner->setOpaqueResize(manager->splitterOpaqueResize()); + panner->setKeepSize(manager->splitterKeepSize()); + panner->setFocusPolicy( NoFocus ); + target->applyToWidget( panner ); + applyToWidget( panner ); + target->formerDockPos = target->currentDockPos; + if ( dockPos == KDockWidget::DockRight) { + panner->activate( target, this ); + currentDockPos = KDockWidget::DockRight; + target->currentDockPos = KDockWidget::DockLeft; + } + else if( dockPos == KDockWidget::DockBottom) { + panner->activate( target, this ); + currentDockPos = KDockWidget::DockBottom; + target->currentDockPos = KDockWidget::DockTop; + } + else if( dockPos == KDockWidget::DockTop) { + panner->activate( this, target ); + currentDockPos = KDockWidget::DockTop; + target->currentDockPos = KDockWidget::DockBottom; + } + else if( dockPos == KDockWidget::DockLeft) { + panner->activate( this, target ); + currentDockPos = KDockWidget::DockLeft; + target->currentDockPos = KDockWidget::DockRight; + } + target->show(); + show(); + panner->show(); + } + + if ( parentDock ){ + if ( parentDock->inherits("KDockSplitter") ){ + KDockSplitter* sp = (KDockSplitter*)parentDock; + sp->deactivate(); + if ( sp->getFirst() == target ) + sp->activate( newDock, 0L ); + else + sp->activate( 0L, newDock ); + } + } + + newDock->show(); + emit target->docking( this, dockPos ); + emit manager->replaceDock( target, newDock ); + emit manager->change(); + + return newDock; +} + +KDockTabGroup* KDockWidget::parentDockTabGroup() const +{ + if ( !parent() ) return 0L; + QWidget* candidate = parentWidget()->parentWidget(); + if ( candidate && candidate->inherits("KDockTabGroup") ) return (KDockTabGroup*)candidate; + return 0L; +} + +QWidget *KDockWidget::parentDockContainer() const +{ + if (!parent()) return 0L; + QWidget* candidate = parentWidget()->parentWidget(); + if (candidate && dynamic_cast<KDockContainer*>(candidate)) return candidate; + return 0L; +} + + +void KDockWidget::setForcedFixedWidth(int w) +{ + d->forcedWidth=w; + setFixedWidth(w); + if (!parent()) return; + if (parent()->inherits("KDockSplitter")) + static_cast<KDockSplitter*>(parent()->qt_cast("KDockSplitter"))->setForcedFixedWidth(this,w); +} + +void KDockWidget::setForcedFixedHeight(int h) +{ + d->forcedHeight=h; + setFixedHeight(h); + if (!parent()) return; + if (parent()->inherits("KDockSplitter")) + static_cast<KDockSplitter*>(parent()->qt_cast("KDockSplitter"))->setForcedFixedHeight(this,h); +} + +int KDockWidget::forcedFixedWidth() +{ + return d->forcedWidth; +} + +int KDockWidget::forcedFixedHeight() +{ + return d->forcedHeight; +} + +void KDockWidget::restoreFromForcedFixedSize() +{ + d->forcedWidth=-1; + setMinimumWidth(0); + setMaximumWidth(32000); + setMinimumHeight(0); + setMaximumHeight(32000); + if (!parent()) return; + if (parent()->inherits("KDockSplitter")) + static_cast<KDockSplitter*>(parent()->qt_cast("KDockSplitter"))->restoreFromForcedFixedSize(this); +} + +void KDockWidget::toDesktop() +{ + QPoint p = mapToGlobal( QPoint( -30, -30 ) ); + if( p.x( ) < 0 ) + p.setX( 0 ); + if( p.y( ) < 0 ) + p.setY( 0 ); + manualDock( 0, DockDesktop, 50, p ); +} + +KDockWidget::DockPosition KDockWidget::currentDockPosition() const +{ + return currentDockPos; +} + +void KDockWidget::undock() +{ +// kdDebug(282)<<"KDockWidget::undock()"<<endl; + + manager->d->dragRect = QRect (); + manager->drawDragRectangle (); + + QWidget* parentW = parentWidget(); + if ( !parentW ){ + hide(); + if (!d->blockHasUndockedSignal) + emit hasUndocked(); + return; + } + + formerDockPos = currentDockPos; + currentDockPos = KDockWidget::DockDesktop; + + manager->blockSignals(true); + manager->undockProcess = true; + + bool isV = parentW->isVisibleToTLW(); + + //UNDOCK HAS TO BE IMPLEMENTED CORRECTLY :) + KDockTabGroup* parentTab = parentDockTabGroup(); + if ( parentTab ){ + d->index = parentTab->indexOf( this); // memorize the page position in the tab widget + parentTab->removePage( this ); +/* + QWidget *wantTransient=parentTab->transientTo(); + target->setDockWindowTransient(wantTransient,wantTransient); + */ + setFormerBrotherDockWidget((KDockWidget*)parentTab->page(0)); + applyToWidget( 0L ); + if ( parentTab->count() == 1 ){ + + // last subdock widget in the tab control + KDockWidget* lastTab = (KDockWidget*)parentTab->page(0); + parentTab->removePage( lastTab ); +/* QWidget *wantTransient=parentTab->transientTo(); + target->setDockWindowTransient(wantTransient,wantTransient);*/ + + lastTab->applyToWidget( 0L ); + lastTab->move( parentTab->mapToGlobal(parentTab->frameGeometry().topLeft()) ); + + // KDockTabGroup always have a parent that is a KDockWidget + KDockWidget* parentOfTab = (KDockWidget*)parentTab->parent(); + delete parentTab; // KDockTabGroup + + QWidget* parentOfDockWidget = parentOfTab->parentWidget(); + if ( !parentOfDockWidget ){ + if ( isV ) lastTab->show(); + } else { + if ( parentOfDockWidget->inherits("KDockSplitter") ){ + KDockSplitter* split = (KDockSplitter*)parentOfDockWidget; + lastTab->applyToWidget( split ); + split->deactivate(); + if ( split->getFirst() == parentOfTab ){ + split->activate( lastTab ); + if ( ((KDockWidget*)split->parent())->splitterOrientation == Vertical ) + emit ((KDockWidget*)split->getAnother(parentOfTab))->docking( parentOfTab, KDockWidget::DockLeft ); + else + emit ((KDockWidget*)split->getAnother(parentOfTab))->docking( parentOfTab, KDockWidget::DockTop ); + } else { + split->activate( 0L, lastTab ); + if ( ((KDockWidget*)split->parent())->splitterOrientation == Vertical ) + emit ((KDockWidget*)split->getAnother(parentOfTab))->docking( parentOfTab, KDockWidget::DockRight ); + else + emit ((KDockWidget*)split->getAnother(parentOfTab))->docking( parentOfTab, KDockWidget::DockBottom ); + } + split->show(); + } else { + lastTab->applyToWidget( parentOfDockWidget ); + } + lastTab->show(); + } + manager->blockSignals(false); + emit manager->replaceDock( parentOfTab, lastTab ); + lastTab->currentDockPos = parentOfTab->currentDockPos; + emit parentOfTab->iMBeingClosed(); + manager->blockSignals(true); + delete parentOfTab; + + } else { + setDockTabName( parentTab ); + } + } else { + /*********************************************************************************************/ + //QWidget* containerWidget = (QWidget*)parent(); + bool undockedFromContainer=false; + if (d->container) + { +// kdDebug(282)<<"undocked from dockcontainer"<<endl; + undockedFromContainer=true; + KDockContainer* dc = dynamic_cast<KDockContainer*>(d->container.operator->()); + if (dc) { + dc->undockWidget(this); + setFormerBrotherDockWidget(dc->parentDockWidget()); + } + applyToWidget( 0L ); + } + if (!undockedFromContainer) { +/*********************************************************************************************/ + if ( parentW->inherits("KDockSplitter") ){ + KDockSplitter* parentSplitterOfDockWidget = (KDockSplitter*)parentW; + d->splitPosInPercent = parentSplitterOfDockWidget->separatorPos(); + + KDockWidget* secondWidget = (KDockWidget*)parentSplitterOfDockWidget->getAnother( this ); + KDockWidget* group = (KDockWidget*)parentSplitterOfDockWidget->parentWidget(); + setFormerBrotherDockWidget(secondWidget); + applyToWidget( 0L ); + group->hide(); + + if ( !group->parentWidget() ){ + secondWidget->applyToWidget( 0L, group->frameGeometry().topLeft() ); + secondWidget->resize( group->width(), group->height() ); + } else { + QWidget* obj = group->parentWidget(); + secondWidget->applyToWidget( obj ); + if ( obj->inherits("KDockSplitter") ){ + KDockSplitter* parentOfGroup = (KDockSplitter*)obj; + parentOfGroup->deactivate(); + + if ( parentOfGroup->getFirst() == group ) + parentOfGroup->activate( secondWidget ); + else + parentOfGroup->activate( 0L, secondWidget ); + } + } + secondWidget->currentDockPos = group->currentDockPos; + secondWidget->formerDockPos = group->formerDockPos; + delete parentSplitterOfDockWidget; + manager->blockSignals(false); + emit manager->replaceDock( group, secondWidget ); + emit group->iMBeingClosed(); + manager->blockSignals(true); + delete group; + + if ( isV ) secondWidget->show(); + } else { + if (!d->pendingDtor) { + // don't reparent in the dtor of this + applyToWidget( 0L ); + } + } +/*********************************************************************************************/ + } + } + manager->blockSignals(false); + if (!d->blockHasUndockedSignal) + emit manager->change(); + manager->undockProcess = false; + + if (!d->blockHasUndockedSignal) + emit hasUndocked(); +} + +void KDockWidget::setWidget( QWidget* mw ) +{ + if ( !mw ) return; + + if ( mw->parent() != this ){ + mw->reparent(this, 0, QPoint(0,0), false); + } + +#ifdef BORDERLESS_WINDOWS + if (!mw->ownCursor()) mw->setCursor(QCursor(ArrowCursor)); +#endif + widget = mw; + delete layout; + + layout = new QVBoxLayout( this ); + layout->setResizeMode( QLayout::Minimum ); + + KDockContainer* dc = dynamic_cast<KDockContainer*>(widget); + if (dc) + { + d->isContainer=true; + manager->d->containerDocks.append(this); + } + else + { + d->isContainer=false; + } + + { + header->show(); + layout->addWidget( header ); + layout->addWidget( widget,1 ); + } + updateHeader(); + emit widgetSet(mw); +} + +void KDockWidget::setDockTabName( KDockTabGroup* tab ) +{ + QString listOfName; + QString listOfCaption; + for ( int i = 0; i < tab->count(); ++i ) { + QWidget *w = tab->page( i ); + listOfCaption.append( w->caption() ).append(","); + listOfName.append( w->name() ).append(","); + } + listOfCaption.remove( listOfCaption.length()-1, 1 ); + listOfName.remove( listOfName.length()-1, 1 ); + + tab->parentWidget()->setName( listOfName.utf8() ); + tab->parentWidget()->setCaption( listOfCaption ); + + tab->parentWidget()->repaint( false ); // KDockWidget->repaint + if ( tab->parentWidget()->parent() ) + if ( tab->parentWidget()->parent()->inherits("KDockSplitter") ) + ((KDockSplitter*)(tab->parentWidget()->parent()))->updateName(); +} + +bool KDockWidget::mayBeHide() const +{ + bool f = (parent() != manager->main); + return ( !isGroup && !isTabGroup && f && isVisible() && ( eDocking != (int)KDockWidget::DockNone ) ); +} + +bool KDockWidget::mayBeShow() const +{ + bool f = (parent() != manager->main); + return ( !isGroup && !isTabGroup && f && !isVisible() ); +} + +void KDockWidget::changeHideShowState() +{ + if ( mayBeHide() ){ + undock(); + return; + } + + if ( mayBeShow() ){ + if ( manager->main->inherits("KDockMainWindow") ){ + ((KDockMainWindow*)manager->main)->makeDockVisible(this); + } else { + makeDockVisible(); + } + } +} + +void KDockWidget::makeDockVisible() +{ + if ( parentDockTabGroup() ){ + parentDockTabGroup()->showPage( this ); + } + if (parentDockContainer()) { + QWidget *contWid=parentDockContainer(); + KDockContainer *x = dynamic_cast<KDockContainer*>(contWid); + if (x) { + x->showWidget(this); + } + } + if ( isVisible() ) return; + + QWidget* p = parentWidget(); + while ( p ){ + if ( !p->isVisible() ) + p->show(); + p = p->parentWidget(); + } + if( !parent() ) // is undocked + dockBack(); + show(); +} + +void KDockWidget::setFormerBrotherDockWidget(KDockWidget *dockWidget) +{ + formerBrotherDockWidget = dockWidget; + if( formerBrotherDockWidget ) + QObject::connect( formerBrotherDockWidget, SIGNAL(iMBeingClosed()), + this, SLOT(loseFormerBrotherDockWidget()) ); +} + +void KDockWidget::loseFormerBrotherDockWidget() +{ + if( formerBrotherDockWidget ) + QObject::disconnect( formerBrotherDockWidget, SIGNAL(iMBeingClosed()), + this, SLOT(loseFormerBrotherDockWidget()) ); + formerBrotherDockWidget = 0L; + repaint(); +} + +void KDockWidget::dockBack() +{ + if( formerBrotherDockWidget) { + // search all children if it tries to dock back to a child + bool found = false; + QObjectList* cl = queryList("KDockWidget"); + QObjectListIt it( *cl ); + QObject * obj; + while ( !found && (obj=it.current()) != 0 ) { + ++it; + QWidget* widg = (QWidget*)obj; + if( widg == formerBrotherDockWidget) + found = true; + } + delete cl; + + if( !found) { + // can dock back to the former brother dockwidget + manualDock( formerBrotherDockWidget, formerDockPos, d->splitPosInPercent, QPoint(0,0), false, d->index); + formerBrotherDockWidget = 0L; + makeDockVisible(); + return; + } + } + + // else dockback to the dockmainwindow (default behavior) + manualDock( ((KDockMainWindow*)manager->main)->getMainDockWidget(), formerDockPos, d->splitPosInPercent, QPoint(0,0), false, d->index); + formerBrotherDockWidget = 0L; + if (parent()) + makeDockVisible(); +} + +bool KDockWidget::isDockBackPossible() const +{ + if( !(formerBrotherDockWidget) || !(formerBrotherDockWidget->dockSite() & formerDockPos)) + return false; + else + return true; +} + +/**************************************************************************************/ + + +KDockManager::KDockManager( QWidget* mainWindow , const char* name ) +:QObject( mainWindow, name ) + ,main(mainWindow) + ,currentDragWidget(0L) + ,currentMoveWidget(0L) + ,childDockWidgetList(0L) + ,autoCreateDock(0L) + ,storeW(0) + ,storeH(0) + ,dragging(false) + ,undockProcess(false) + ,dropCancel(true) +{ + d = new KDockManagerPrivate; + + d->readyToDrag = false; + d->mainDockWidget=0; + +#ifndef NO_KDE2 + d->splitterOpaqueResize = KGlobalSettings::opaqueResize(); +#else + d->splitterOpaqueResize = false; +#endif + + d->splitterKeepSize = false; + d->splitterHighResolution = false; + d->m_readDockConfigMode = WrapExistingWidgetsOnly; // default as before + + main->installEventFilter( this ); + + undockProcess = false; + + menuData = new QPtrList<MenuDockData>; + menuData->setAutoDelete( true ); + menuData->setAutoDelete( true ); + +#ifndef NO_KDE2 + menu = new KPopupMenu(); +#else + menu = new QPopupMenu(); +#endif + + connect( menu, SIGNAL(aboutToShow()), SLOT(slotMenuPopup()) ); + connect( menu, SIGNAL(activated(int)), SLOT(slotMenuActivated(int)) ); + + childDock = new QObjectList(); + childDock->setAutoDelete( false ); +} + + +void KDockManager::setMainDockWidget2(KDockWidget *w) +{ + d->mainDockWidget=w; +} + +KDockManager::~KDockManager() +{ + delete menuData; + delete menu; + + QObjectListIt it( *childDock ); + KDockWidget * obj; + + while ( (obj=(KDockWidget*)it.current()) ) { + delete obj; + } + delete childDock; + delete d; + d=0; +} + +void KDockManager::activate() +{ + QObjectListIt it( *childDock ); + KDockWidget * obj; + + while ( (obj=(KDockWidget*)it.current()) ) { + ++it; + if ( obj->widget ) obj->widget->show(); + if ( !obj->parentDockTabGroup() ){ + obj->show(); + } + } + if ( !main->inherits("QDialog") ) main->show(); +} + +bool KDockManager::eventFilter( QObject *obj, QEvent *event ) +{ + + if ( obj->inherits("KDockWidgetAbstractHeaderDrag") ){ + KDockWidget* pDockWdgAtCursor = 0L; + KDockWidget* curdw = ((KDockWidgetAbstractHeaderDrag*)obj)->dockWidget(); + switch ( event->type() ){ + case QEvent::MouseButtonDblClick: + if (curdw->currentDockPos == KDockWidget::DockDesktop) curdw->dockBack(); + else + { + curdw->toDesktop(); + // curdw->manualDock (0, KDockWidget::DockDesktop); + } + break; + + case QEvent::MouseButtonPress: + if ( ((QMouseEvent*)event)->button() == LeftButton ){ + if ( curdw->eDocking != (int)KDockWidget::DockNone ){ + dropCancel = true; + curdw->setFocus(); + qApp->processOneEvent(); + + currentDragWidget = curdw; + currentMoveWidget = 0L; + childDockWidgetList = new QWidgetList(); + childDockWidgetList->append( curdw ); + findChildDockWidget( curdw, childDockWidgetList ); + + //d->oldDragRect = QRect(); should fix rectangle not erased problem + d->dragRect = QRect(curdw->geometry()); + QPoint p = curdw->mapToGlobal(QPoint(0,0)); + d->dragRect.moveTopLeft(p); + drawDragRectangle(); + d->readyToDrag = true; + + d->dragOffset = QCursor::pos()-currentDragWidget->mapToGlobal(QPoint(0,0)); + } + + } + break; + case QEvent::MouseButtonRelease: + if ( ((QMouseEvent*)event)->button() == LeftButton ){ + if ( dragging ){ + if ( !dropCancel ) + drop(); + else + cancelDrop(); + } + if (d->readyToDrag) { + d->readyToDrag = false; + //d->oldDragRect = QRect(); should fix rectangle not erased problem + d->dragRect = QRect(curdw->geometry()); + QPoint p = curdw->mapToGlobal(QPoint(0,0)); + d->dragRect.moveTopLeft(p); + drawDragRectangle(); + currentDragWidget = 0L; + delete childDockWidgetList; + childDockWidgetList = 0L; + } + dragging = false; + dropCancel = true; + } + break; + case QEvent::MouseMove: + if ( dragging ) { + +#ifdef BORDERLESS_WINDOWS +//BEGIN TEST + KDockWidget *oldMoveWidget; + if (!curdw->parent()) + { + curdw->move(QCursor::pos()-d->dragOffset); + pDockWdgAtCursor = findDockWidgetAt( QCursor::pos()-QPoint(0,d->dragOffset.y()+3) ); + oldMoveWidget = currentMoveWidget; + } + else + { + pDockWdgAtCursor = findDockWidgetAt( QCursor::pos() ); + oldMoveWidget = currentMoveWidget; + } +//END TEST +#else + pDockWdgAtCursor = findDockWidgetAt( QCursor::pos() ); + KDockWidget* oldMoveWidget = currentMoveWidget; +#endif + + if ( currentMoveWidget && pDockWdgAtCursor == currentMoveWidget ) { //move + dragMove( currentMoveWidget, currentMoveWidget->mapFromGlobal( QCursor::pos() ) ); + break; + } else { + if (dropCancel && curdw) { + d->dragRect = QRect(curdw->geometry()); + QPoint p = curdw->mapToGlobal(QPoint(0,0)); + d->dragRect.moveTopLeft(p); + }else + d->dragRect = QRect(); + + drawDragRectangle(); + } + + if ( !pDockWdgAtCursor && !(curdw->eDocking & (int)KDockWidget::DockDesktop) ){ + // just moving at the desktop + currentMoveWidget = pDockWdgAtCursor; + curPos = KDockWidget::DockDesktop; + } else { + if ( oldMoveWidget && pDockWdgAtCursor != currentMoveWidget ) { //leave + currentMoveWidget = pDockWdgAtCursor; + curPos = KDockWidget::DockDesktop; + } + } + + if ( oldMoveWidget != pDockWdgAtCursor && pDockWdgAtCursor ) { //enter pDockWdgAtCursor + currentMoveWidget = pDockWdgAtCursor; + curPos = KDockWidget::DockDesktop; + } + } else { + if (d->readyToDrag) { + d->readyToDrag = false; + } + if ( (((QMouseEvent*)event)->state() == LeftButton) && + (curdw->eDocking != (int)KDockWidget::DockNone) ) { + startDrag( curdw); + } + } + break; + default: + break; + } + } + return QObject::eventFilter( obj, event ); +} + +KDockWidget* KDockManager::findDockWidgetAt( const QPoint& pos ) +{ + dropCancel = true; + + if (!currentDragWidget) + return 0L; // pointer access safety + + if (currentDragWidget->eDocking == (int)KDockWidget::DockNone ) return 0L; + + QWidget* p = QApplication::widgetAt( pos ); + if ( !p ) { + dropCancel = false; + return 0L; + } +#if defined(_OS_WIN32_) || defined(Q_OS_WIN32) + p = p->topLevelWidget(); +#endif + QWidget* w = 0L; + findChildDockWidget( w, p, p->mapFromGlobal(pos) ); + if ( !w ){ + if ( !p->inherits("KDockWidget") ) { + return 0L; + } + w = p; + } + if ( qt_find_obj_child( w, "KDockSplitter", "_dock_split_" ) ) return 0L; + if ( qt_find_obj_child( w, "KDockTabGroup", "_dock_tab" ) ) return 0L; + if (dynamic_cast<KDockContainer*>(w)) return 0L; + + if (!childDockWidgetList) return 0L; + if ( childDockWidgetList->find(w) != -1 ) return 0L; + if ( currentDragWidget->isGroup && ((KDockWidget*)w)->parentDockTabGroup() ) return 0L; + + KDockWidget* www = (KDockWidget*)w; + if ( www->sDocking == (int)KDockWidget::DockNone ) return 0L; + if( !www->widget ) + return 0L; + + KDockWidget::DockPosition curPos = KDockWidget::DockDesktop; + QPoint cpos = www->mapFromGlobal( pos ); + + int ww = www->widget->width() / 3; + int hh = www->widget->height() / 3; + + if ( cpos.y() <= hh ){ + curPos = KDockWidget::DockTop; + } else + if ( cpos.y() >= 2*hh ){ + curPos = KDockWidget::DockBottom; + } else + if ( cpos.x() <= ww ){ + curPos = KDockWidget::DockLeft; + } else + if ( cpos.x() >= 2*ww ){ + curPos = KDockWidget::DockRight; + } else + curPos = KDockWidget::DockCenter; + + if ( !(www->sDocking & (int)curPos) ) return 0L; + if ( !(currentDragWidget->eDocking & (int)curPos) ) return 0L; + if ( www->manager != this ) return 0L; + + dropCancel = false; + return www; +} + +void KDockManager::findChildDockWidget( QWidget*& ww, const QWidget* p, const QPoint& pos ) +{ + if ( p->children() ) { + QWidget *w; + QObjectListIt it( *p->children() ); + it.toLast(); + while ( it.current() ) { + if ( it.current()->isWidgetType() ) { + w = (QWidget*)it.current(); + if ( w->isVisible() && w->geometry().contains(pos) ) { + if ( w->inherits("KDockWidget") ) ww = w; + findChildDockWidget( ww, w, w->mapFromParent(pos) ); + return; + } + } + --it; + } + } + return; +} + +void KDockManager::findChildDockWidget( const QWidget* p, QWidgetList*& list ) +{ + if ( p->children() ) { + QWidget *w; + QObjectListIt it( *p->children() ); + it.toLast(); + while ( it.current() ) { + if ( it.current()->isWidgetType() ) { + w = (QWidget*)it.current(); + if ( w->isVisible() ) { + if ( w->inherits("KDockWidget") ) list->append( w ); + findChildDockWidget( w, list ); + } + } + --it; + } + } + return; +} + +void KDockManager::startDrag( KDockWidget* w ) +{ + if(( w->currentDockPos == KDockWidget::DockLeft) || ( w->currentDockPos == KDockWidget::DockRight) + || ( w->currentDockPos == KDockWidget::DockTop) || ( w->currentDockPos == KDockWidget::DockBottom)) { + w->prevSideDockPosBeforeDrag = w->currentDockPos; + + if ( w->parentWidget()->inherits("KDockSplitter") ){ + KDockSplitter* parentSplitterOfDockWidget = (KDockSplitter*)(w->parentWidget()); + w->d->splitPosInPercent = parentSplitterOfDockWidget->separatorPos(); + } + } + + curPos = KDockWidget::DockDesktop; + dragging = true; + + QApplication::setOverrideCursor(QCursor(sizeAllCursor)); +} + +void KDockManager::dragMove( KDockWidget* dw, QPoint pos ) +{ + QPoint p = dw->mapToGlobal( dw->widget->pos() ); + KDockWidget::DockPosition oldPos = curPos; + + QSize r = dw->widget->size(); + if ( dw->parentDockTabGroup() ){ + curPos = KDockWidget::DockCenter; + if ( oldPos != curPos ) { + d->dragRect.setRect( p.x()+2, p.y()+2, r.width()-4, r.height()-4 ); + } + return; + } + + int w = r.width() / 3; + int h = r.height() / 3; + + if ( pos.y() <= h ){ + curPos = KDockWidget::DockTop; + w = r.width(); + } else + if ( pos.y() >= 2*h ){ + curPos = KDockWidget::DockBottom; + p.setY( p.y() + 2*h ); + w = r.width(); + } else + if ( pos.x() <= w ){ + curPos = KDockWidget::DockLeft; + h = r.height(); + } else + if ( pos.x() >= 2*w ){ + curPos = KDockWidget::DockRight; + p.setX( p.x() + 2*w ); + h = r.height(); + } else + { + curPos = KDockWidget::DockCenter; + p.setX( p.x() + w ); + p.setY( p.y() + h ); + } + + if ( oldPos != curPos ) { + d->dragRect.setRect( p.x(), p.y(), w, h ); + drawDragRectangle(); + } +} + + +void KDockManager::cancelDrop() +{ + QApplication::restoreOverrideCursor(); + + delete childDockWidgetList; + childDockWidgetList = 0L; + + d->dragRect = QRect(); // cancel drawing + drawDragRectangle(); // only the old rect will be deleted +} + + +void KDockManager::drop() +{ + d->dragRect = QRect(); // cancel drawing + drawDragRectangle(); // only the old rect will be deleted + + QApplication::restoreOverrideCursor(); + + delete childDockWidgetList; + childDockWidgetList = 0L; + + if ( dropCancel ) return; + if ( !currentMoveWidget && (!(currentDragWidget->eDocking & (int)KDockWidget::DockDesktop)) ) { + d->dragRect = QRect(); // cancel drawing + drawDragRectangle(); // only the old rect will be deleted + return; + } + if ( !currentMoveWidget && !currentDragWidget->parent() ) { + currentDragWidget->move( QCursor::pos() - d->dragOffset ); + } + else { + int splitPos = currentDragWidget->d->splitPosInPercent; + // do we have to calculate 100%-splitPosInPercent? + if( (curPos != currentDragWidget->prevSideDockPosBeforeDrag) && (curPos != KDockWidget::DockCenter) && (curPos != KDockWidget::DockDesktop)) { + switch( currentDragWidget->prevSideDockPosBeforeDrag) { + case KDockWidget::DockLeft: if(curPos != KDockWidget::DockTop) splitPos = 100-splitPos; break; + case KDockWidget::DockRight: if(curPos != KDockWidget::DockBottom) splitPos = 100-splitPos; break; + case KDockWidget::DockTop: if(curPos != KDockWidget::DockLeft) splitPos = 100-splitPos; break; + case KDockWidget::DockBottom: if(curPos != KDockWidget::DockRight) splitPos = 100-splitPos; break; + default: break; + } + } + currentDragWidget->manualDock( currentMoveWidget, curPos , splitPos, QCursor::pos() - d->dragOffset ); + currentDragWidget->makeDockVisible(); + } +} + + +static QDomElement createStringEntry(QDomDocument &doc, const QString &tagName, const QString &str) +{ + QDomElement el = doc.createElement(tagName); + + el.appendChild(doc.createTextNode(str)); + return el; +} + + +static QDomElement createBoolEntry(QDomDocument &doc, const QString &tagName, bool b) +{ + return createStringEntry(doc, tagName, QString::fromLatin1(b? "true" : "false")); +} + + +static QDomElement createNumberEntry(QDomDocument &doc, const QString &tagName, int n) +{ + return createStringEntry(doc, tagName, QString::number(n)); +} + + +static QDomElement createRectEntry(QDomDocument &doc, const QString &tagName, const QRect &rect) +{ + QDomElement el = doc.createElement(tagName); + + QDomElement xel = doc.createElement("x"); + xel.appendChild(doc.createTextNode(QString::number(rect.x()))); + el.appendChild(xel); + QDomElement yel = doc.createElement("y"); + yel.appendChild(doc.createTextNode(QString::number(rect.y()))); + el.appendChild(yel); + QDomElement wel = doc.createElement("width"); + wel.appendChild(doc.createTextNode(QString::number(rect.width()))); + el.appendChild(wel); + QDomElement hel = doc.createElement("height"); + hel.appendChild(doc.createTextNode(QString::number(rect.height()))); + el.appendChild(hel); + + return el; +} + + +static QDomElement createListEntry(QDomDocument &doc, const QString &tagName, + const QString &subTagName, const QStrList &list) +{ + QDomElement el = doc.createElement(tagName); + + QStrListIterator it(list); + for (; it.current(); ++it) { + QDomElement subel = doc.createElement(subTagName); + subel.appendChild(doc.createTextNode(QString::fromLatin1(it.current()))); + el.appendChild(subel); + } + + return el; +} + + +static QString stringEntry(QDomElement &base, const QString &tagName) +{ + return base.namedItem(tagName).firstChild().toText().data(); +} + + +static bool boolEntry(QDomElement &base, const QString &tagName) +{ + return base.namedItem(tagName).firstChild().toText().data() == "true"; +} + + +static int numberEntry(QDomElement &base, const QString &tagName) +{ + return stringEntry(base, tagName).toInt(); +} + + +static QRect rectEntry(QDomElement &base, const QString &tagName) +{ + QDomElement el = base.namedItem(tagName).toElement(); + + int x = numberEntry(el, "x"); + int y = numberEntry(el, "y"); + int width = numberEntry(el, "width"); + int height = numberEntry(el, "height"); + + return QRect(x, y, width, height); +} + + +static QStrList listEntry(QDomElement &base, const QString &tagName, const QString &subTagName) +{ + QStrList list; + + for( QDomNode n = base.namedItem(tagName).firstChild(); !n.isNull(); n = n.nextSibling() ) + { + QDomElement subel = n.toElement(); + if (subel.tagName() == subTagName) + list.append(subel.firstChild().toText().data().latin1()); + } + + return list; +} + + +void KDockManager::writeConfig(QDomElement &base) +{ + // First of all, clear the tree under base + while (!base.firstChild().isNull()) + base.removeChild(base.firstChild()); + QDomDocument doc = base.ownerDocument(); + + QStrList nameList; + QString mainWidgetStr; + + // collect widget names + QStringList nList; + QObjectListIt it(*childDock); + KDockWidget *obj1; + while ( (obj1=(KDockWidget*)it.current()) ) { + if ( obj1->parent() == main ) + mainWidgetStr = QString::fromLatin1(obj1->name()); + nList.append(obj1->name()); + ++it; + } + + for (QObjectListIt it(d->containerDocks);it.current();++it) + { + KDockContainer* dc = dynamic_cast<KDockContainer*>(((KDockWidget*)it.current())->widget); + if (dc) { + dc->prepareSave(nList); + } + } + + QStringList::Iterator nListIt=nList.begin(); + while ( nListIt!=nList.end() ) { + KDockWidget *obj = getDockWidgetFromName( *nListIt); + if ((obj->isGroup && (!obj->d->isContainer)) && (nameList.find( obj->firstName.latin1() ) == -1 + || nameList.find(obj->lastName.latin1()) == -1)) { + // Skip until children are saved (why?) + ++nListIt; +// nList.next(); +//falk? if ( !nList.current() ) nList.first(); + continue; + } + + QDomElement groupEl; + if (obj->d->isContainer) { + KDockContainer* x = dynamic_cast<KDockContainer*>(obj->widget); + if (x) { + groupEl=doc.createElement("dockContainer"); + x->save(groupEl); + } + } else + if (obj->isGroup) { + //// Save a group + groupEl = doc.createElement("splitGroup"); + + groupEl.appendChild(createStringEntry(doc, "firstName", obj->firstName)); + groupEl.appendChild(createStringEntry(doc, "secondName", obj->lastName)); + groupEl.appendChild(createNumberEntry(doc, "orientation", (int)obj->splitterOrientation)); + groupEl.appendChild(createNumberEntry(doc, "separatorPos", ((KDockSplitter*)obj->widget)->separatorPos())); + } else if (obj->isTabGroup) { + //// Save a tab group + groupEl = doc.createElement("tabGroup"); + + QStrList list; + for ( int i = 0; i < ((KDockTabGroup*)obj->widget)->count(); ++i ) + list.append( ((KDockTabGroup*)obj->widget)->page( i )->name() ); + groupEl.appendChild(createListEntry(doc, "tabs", "tab", list)); + groupEl.appendChild(createNumberEntry(doc, "currentTab", ((KDockTabGroup*)obj->widget)->currentPageIndex())); + if (!obj->parent()) { + groupEl.appendChild(createStringEntry(doc, "dockBackTo", obj->formerBrotherDockWidget ? obj->formerBrotherDockWidget->name() : "")); + groupEl.appendChild(createNumberEntry(doc, "dockBackToPos", obj->formerDockPos)); + } + } else { + //// Save an ordinary dock widget + groupEl = doc.createElement("dock"); + groupEl.appendChild(createStringEntry(doc, "tabCaption", obj->tabPageLabel())); + groupEl.appendChild(createStringEntry(doc, "tabToolTip", obj->toolTipString())); + if (!obj->parent()) { + groupEl.appendChild(createStringEntry(doc, "dockBackTo", obj->formerBrotherDockWidget ? obj->formerBrotherDockWidget->name() : "")); + groupEl.appendChild(createNumberEntry(doc, "dockBackToPos", obj->formerDockPos)); + } + } + + groupEl.appendChild(createStringEntry(doc, "name", QString::fromLatin1(obj->name()))); + groupEl.appendChild(createBoolEntry(doc, "hasParent", obj->parent())); + if ( !obj->parent() ) { + groupEl.appendChild(createRectEntry(doc, "geometry", QRect(main->frameGeometry().topLeft(), main->size()))); + groupEl.appendChild(createBoolEntry(doc, "visible", obj->isVisible())); + } + if (obj->header && obj->header->inherits("KDockWidgetHeader")) { + KDockWidgetHeader *h = static_cast<KDockWidgetHeader*>(obj->header); + groupEl.appendChild(createBoolEntry(doc, "dragEnabled", h->dragEnabled())); + } + + base.appendChild(groupEl); + nameList.append(obj->name()); + nList.remove(nListIt); + nListIt=nList.begin(); + } + + if (main->inherits("KDockMainWindow")) { + KDockMainWindow *dmain = (KDockMainWindow*)main; + QString centralWidgetStr = QString(dmain->centralWidget()? dmain->centralWidget()->name() : ""); + base.appendChild(createStringEntry(doc, "centralWidget", centralWidgetStr)); + QString mainDockWidgetStr = QString(dmain->getMainDockWidget()? dmain->getMainDockWidget()->name() : ""); + base.appendChild(createStringEntry(doc, "mainDockWidget", mainDockWidgetStr)); + } else { + base.appendChild(createStringEntry(doc, "mainWidget", mainWidgetStr)); + } + + base.appendChild(createRectEntry(doc, "geometry", QRect(main->frameGeometry().topLeft(), main->size()))); +} + + +void KDockManager::readConfig(QDomElement &base) +{ + if (base.namedItem("group").isNull() + && base.namedItem("tabgroup").isNull() + && base.namedItem("dock").isNull() + && base.namedItem("dockContainer").isNull()) { + activate(); + return; + } + + autoCreateDock = new QObjectList(); + autoCreateDock->setAutoDelete( true ); + + bool isMainVisible = main->isVisible(); + main->hide(); + + QObjectListIt it(*childDock); + KDockWidget *obj1; + while ( (obj1=(KDockWidget*)it.current()) ) { + if ( !obj1->isGroup && !obj1->isTabGroup ) { + if ( obj1->parent() ) + obj1->undock(); + else + obj1->hide(); + } + ++it; + } + + // firstly, recreate all common dockwidgets + for( QDomNode n = base.firstChild(); !n.isNull(); n = n.nextSibling() ) + { + QDomElement childEl = n.toElement(); + if (childEl.tagName() != "dock") continue; + + // Read an ordinary dock widget + KDockWidget *obj = getDockWidgetFromName(stringEntry(childEl, "name")); + obj->setTabPageLabel(stringEntry(childEl, "tabCaption")); + obj->setToolTipString(stringEntry(childEl, "tabToolTip")); + + if (!boolEntry(childEl, "hasParent")) { + QRect r = rectEntry(childEl, "geometry"); + obj = getDockWidgetFromName(stringEntry(childEl, "name")); + obj->applyToWidget(0); + obj->setGeometry(r); + if (boolEntry(childEl, "visible")) + obj->QWidget::show(); + } + + if (obj && obj->header && obj->header->inherits("KDockWidgetHeader")) { + KDockWidgetHeader *h = static_cast<KDockWidgetHeader*>(obj->header); + h->setDragEnabled(boolEntry(childEl, "dragEnabled")); + } + } + + // secondly, now iterate again and create the groups and tabwidgets, apply the dockwidgets to them + for( QDomNode n = base.firstChild(); !n.isNull(); n = n.nextSibling() ) + { + QDomElement childEl = n.toElement(); + if (childEl.isNull()) continue; + + KDockWidget *obj = 0; + + if (childEl.tagName() == "dockContainer") { + + KDockWidget *cont=getDockWidgetFromName(stringEntry(childEl, "name")); + kdDebug(282)<<"dockContainer: "<<stringEntry(childEl,"name")<<endl; + if (!(cont->d->isContainer)) { + kdDebug(282)<<"restoration of dockContainer is only supported for already existing dock containers"<<endl; + } else { + KDockContainer *dc=dynamic_cast<KDockContainer*>(cont->getWidget()); + if (!dc) kdDebug(282)<<"Error while trying to handle dockcontainer configuration restoration"<<endl; + else { + dc->load(childEl); + removeFromAutoCreateList(cont); + } + + } + } + else + if (childEl.tagName() == "splitGroup") { + // Read a group + QString name = stringEntry(childEl, "name"); + QString firstName = stringEntry(childEl, "firstName"); + QString secondName = stringEntry(childEl, "secondName"); + int orientation = numberEntry(childEl, "orientation"); + int separatorPos = numberEntry(childEl, "separatorPos"); + + KDockWidget *first = getDockWidgetFromName(firstName); + KDockWidget *second = getDockWidgetFromName(secondName); + if (first && second) { + obj = first->manualDock(second, + (orientation == (int)Vertical)? KDockWidget::DockLeft : KDockWidget::DockTop, + separatorPos); + if (obj) + obj->setName(name.latin1()); + } + } else if (childEl.tagName() == "tabGroup") { + // Read a tab group + QString name = stringEntry(childEl, "name"); + QStrList list = listEntry(childEl, "tabs", "tab"); + + KDockWidget *d1 = getDockWidgetFromName( list.first() ); + list.next(); + KDockWidget *d2 = getDockWidgetFromName( list.current() ); + + KDockWidget *obj = d2->manualDock( d1, KDockWidget::DockCenter ); + if (obj) { + KDockTabGroup *tab = (KDockTabGroup*)obj->widget; + list.next(); + while (list.current() && obj) { + KDockWidget *tabDock = getDockWidgetFromName(list.current()); + obj = tabDock->manualDock(d1, KDockWidget::DockCenter); + list.next(); + } + if (obj) { + obj->setName(name.latin1()); + tab->showPage(tab->page(numberEntry(childEl, "currentTab"))); + } + } + } else { + continue; + } + + if (!boolEntry(childEl, "hasParent")) { + QRect r = rectEntry(childEl, "geometry"); + obj = getDockWidgetFromName(stringEntry(childEl, "name")); + obj->applyToWidget(0); + obj->setGeometry(r); + if (boolEntry(childEl, "visible")) + obj->QWidget::show(); + } + + if (obj && obj->header && obj->header->inherits("KDockWidgetHeader")) { + KDockWidgetHeader *h = static_cast<KDockWidgetHeader*>(obj->header); + h->setDragEnabled(boolEntry(childEl, "dragEnabled")); + } + } + + // thirdly, now that all ordinary dockwidgets are created, + // iterate them again and link them with their corresponding dockwidget for the dockback action + for( QDomNode n = base.firstChild(); !n.isNull(); n = n.nextSibling() ) + { + QDomElement childEl = n.toElement(); + + if (childEl.tagName() != "dock" && childEl.tagName() != "tabGroup") + continue; + + KDockWidget *obj = 0; + + if (!boolEntry(childEl, "hasParent")) { + // Read a common toplevel dock widget + obj = getDockWidgetFromName(stringEntry(childEl, "name")); + QString name = stringEntry(childEl, "dockBackTo"); + if (!name.isEmpty()) { + obj->setFormerBrotherDockWidget(getDockWidgetFromName(name)); + } + obj->formerDockPos = KDockWidget::DockPosition(numberEntry(childEl, "dockBackToPos")); + obj->updateHeader(); + } + } + + if (main->inherits("KDockMainWindow")) { + KDockMainWindow *dmain = (KDockMainWindow*)main; + + QString mv = stringEntry(base, "centralWidget"); + if (!mv.isEmpty() && getDockWidgetFromName(mv) ) { + KDockWidget *mvd = getDockWidgetFromName(mv); + mvd->applyToWidget(dmain); + mvd->show(); + dmain->setCentralWidget(mvd); + } + QString md = stringEntry(base, "mainDockWidget"); + if (!md.isEmpty() && getDockWidgetFromName(md)) { + KDockWidget *mvd = getDockWidgetFromName(md); + dmain->setMainDockWidget(mvd); + } + } else { + QString mv = stringEntry(base, "mainWidget"); + if (!mv.isEmpty() && getDockWidgetFromName(mv)) { + KDockWidget *mvd = getDockWidgetFromName(mv); + mvd->applyToWidget(main); + mvd->show(); + } + + // only resize + move non-mainwindows + QRect mr = rectEntry(base, "geometry"); + main->move(mr.topLeft()); + main->resize(mr.size()); + } + + if (isMainVisible) + main->show(); + + if (d->m_readDockConfigMode == WrapExistingWidgetsOnly) { + finishReadDockConfig(); // remove empty dockwidgets + } +} + +void KDockManager::removeFromAutoCreateList(KDockWidget* pDockWidget) +{ + if (!autoCreateDock) return; + autoCreateDock->setAutoDelete(false); + autoCreateDock->removeRef(pDockWidget); + autoCreateDock->setAutoDelete(true); +} + +void KDockManager::finishReadDockConfig() +{ + delete autoCreateDock; + autoCreateDock = 0; +} + +void KDockManager::setReadDockConfigMode(int mode) +{ + d->m_readDockConfigMode = mode; +} + +#ifndef NO_KDE2 +void KDockManager::writeConfig( KConfig* c, QString group ) +{ + //debug("BEGIN Write Config"); + if ( !c ) c = KGlobal::config(); + if ( group.isEmpty() ) group = "dock_setting_default"; + + c->setGroup( group ); + c->writeEntry( "Version", DOCK_CONFIG_VERSION ); + + QStringList nameList; + QStringList findList; + QObjectListIt it( *childDock ); + KDockWidget * obj; + + // collect KDockWidget's name + QStringList nList; + while ( (obj=(KDockWidget*)it.current()) ) { + ++it; + //debug(" +Add subdock %s", obj->name()); + nList.append( obj->name() ); + if ( obj->parent() == main ) + c->writeEntry( "Main:view", obj->name() ); + } + +// kdDebug(282)<<QString("list size: %1").arg(nList.count())<<endl; + for (QObjectListIt it(d->containerDocks);it.current();++it) + { + KDockContainer* dc = dynamic_cast<KDockContainer*>(((KDockWidget*)it.current())->widget); + if (dc) { + dc->prepareSave(nList); + } + } +// kdDebug(282)<<QString("new list size: %1").arg(nList.count())<<endl; + + QStringList::Iterator nListIt=nList.begin(); + while ( nListIt!=nList.end() ){ + //debug(" -Try to save %s", nList.current()); + obj = getDockWidgetFromName( *nListIt ); + QString cname = obj->name(); + if ( obj->header ){ + obj->header->saveConfig( c ); + } + if (obj->d->isContainer) { + KDockContainer* x = dynamic_cast<KDockContainer*>(obj->widget); + if (x) { + x->save(c,group); + } + } +/*************************************************************************************************/ + if ( obj->isGroup ){ + if ( (findList.find( obj->firstName ) != findList.end()) && (findList.find( obj->lastName ) != findList.end() )){ + + c->writeEntry( cname+":type", "GROUP"); + if ( !obj->parent() ){ + c->writeEntry( cname+":parent", "___null___"); + c->writeEntry( cname+":geometry", QRect(obj->frameGeometry().topLeft(), obj->size()) ); + c->writeEntry( cname+":visible", obj->isVisible()); + } else { + c->writeEntry( cname+":parent", "yes"); + } + c->writeEntry( cname+":first_name", obj->firstName ); + c->writeEntry( cname+":last_name", obj->lastName ); + c->writeEntry( cname+":orientation", (int)obj->splitterOrientation ); + c->writeEntry( cname+":sepPos", ((KDockSplitter*)obj->widget)->separatorPos() ); + + nameList.append( obj->name() ); + findList.append( obj->name() ); + //debug(" Save %s", nList.current()); + nList.remove(nListIt); + nListIt=nList.begin(); //nList.first(); + } else { +/*************************************************************************************************/ + //debug(" Skip %s", nList.current()); + //if ( findList.find( obj->firstName ) == -1 ) + // debug(" ? Not found %s", obj->firstName); + //if ( findList.find( obj->lastName ) == -1 ) + // debug(" ? Not found %s", obj->lastName); + ++nListIt; + // if ( !nList.current() ) nList.first(); + if (nListIt==nList.end()) nListIt=nList.begin(); + } + } else { +/*************************************************************************************************/ + if ( obj->isTabGroup){ + c->writeEntry( cname+":type", "TAB_GROUP"); + if ( !obj->parent() ){ + c->writeEntry( cname+":parent", "___null___"); + c->writeEntry( cname+":geometry", QRect(obj->frameGeometry().topLeft(), obj->size()) ); + c->writeEntry( cname+":visible", obj->isVisible()); + c->writeEntry( cname+":dockBackTo", obj->formerBrotherDockWidget ? obj->formerBrotherDockWidget->name() : ""); + c->writeEntry( cname+":dockBackToPos", obj->formerDockPos); + } else { + c->writeEntry( cname+":parent", "yes"); + } + QStrList list; + for ( int i = 0; i < ((KDockTabGroup*)obj->widget)->count(); ++i ) + list.append( ((KDockTabGroup*)obj->widget)->page( i )->name() ); + c->writeEntry( cname+":tabNames", list ); + c->writeEntry( cname+":curTab", ((KDockTabGroup*)obj->widget)->currentPageIndex() ); + + nameList.append( obj->name() ); + findList.append( obj->name() ); // not really need !!! + //debug(" Save %s", nList.current()); + nList.remove(nListIt); + nListIt=nList.begin(); + } else { +/*************************************************************************************************/ + c->writeEntry( cname+":tabCaption", obj->tabPageLabel()); + c->writeEntry( cname+":tabToolTip", obj->toolTipString()); + if ( !obj->parent() ){ + c->writeEntry( cname+":type", "NULL_DOCK"); + c->writeEntry( cname+":geometry", QRect(obj->frameGeometry().topLeft(), obj->size()) ); + c->writeEntry( cname+":visible", obj->isVisible()); + c->writeEntry( cname+":dockBackTo", obj->formerBrotherDockWidget ? obj->formerBrotherDockWidget->name() : ""); + c->writeEntry( cname+":dockBackToPos", obj->formerDockPos); + } else { + c->writeEntry( cname+":type", "DOCK"); + } + nameList.append( cname.latin1() ); + //debug(" Save %s", nList.current()); + findList.append( obj->name() ); + nList.remove(nListIt); + nListIt=nList.begin(); + } + } + } + c->writeEntry( "NameList", nameList ); + + c->writeEntry( "Main:Geometry", QRect(main->frameGeometry().topLeft(), main->size()) ); + c->writeEntry( "Main:visible", main->isVisible()); // curently nou use + + if ( main->inherits("KDockMainWindow") ){ + KDockMainWindow* dmain = (KDockMainWindow*)main; + // for KDockMainWindow->setView() in readConfig() + c->writeEntry( "Main:view", dmain->centralWidget() ? dmain->centralWidget()->name():"" ); + c->writeEntry( "Main:dock", dmain->getMainDockWidget() ? dmain->getMainDockWidget()->name() :"" ); + } + + c->sync(); + //debug("END Write Config"); +} +#include <qmessagebox.h> +void KDockManager::readConfig( KConfig* c, QString group ) +{ + if ( !c ) c = KGlobal::config(); + if ( group.isEmpty() ) group = "dock_setting_default"; + + c->setGroup( group ); + QStrList nameList; + c->readListEntry( "NameList", nameList ); + QString ver = c->readEntry( "Version", "0.0.1" ); + nameList.first(); + if ( !nameList.current() || ver != DOCK_CONFIG_VERSION ){ + activate(); + return; + } + + autoCreateDock = new QObjectList(); + autoCreateDock->setAutoDelete( true ); + + bool isMainVisible = main->isVisible(); + // if (isMainVisible) // CCC + //QMessageBox::information(0,"","hallo"); +//COMMENTED4TESTING main->hide(); + + QObjectListIt it( *childDock ); + KDockWidget * obj; + + while ( (obj=(KDockWidget*)it.current()) ){ + ++it; + if ( !obj->isGroup && !obj->isTabGroup ) + { + if ( obj->parent() ) obj->undock(); else obj->hide(); + } + } + + // firstly, only the common dockwidgets, + // they must be restored before e.g. tabgroups are restored + nameList.first(); + while ( nameList.current() ){ + QString oname = nameList.current(); + c->setGroup( group ); + QString type = c->readEntry( oname + ":type" ); + obj = 0L; + + if ( type == "NULL_DOCK" || c->readEntry( oname + ":parent") == "___null___" ){ + QRect r = c->readRectEntry( oname + ":geometry" ); + obj = getDockWidgetFromName( oname ); + obj->applyToWidget( 0L ); + obj->setGeometry(r); + + c->setGroup( group ); + obj->setTabPageLabel(c->readEntry( oname + ":tabCaption" )); + obj->setToolTipString(c->readEntry( oname + ":tabToolTip" )); + if ( c->readBoolEntry( oname + ":visible" ) ){ + obj->QWidget::show(); + } + } + + if ( type == "DOCK" ){ + obj = getDockWidgetFromName( oname ); + obj->setTabPageLabel(c->readEntry( oname + ":tabCaption" )); + obj->setToolTipString(c->readEntry( oname + ":tabToolTip" )); + } + + if (obj && obj->d->isContainer) { + dynamic_cast<KDockContainer*>(obj->widget)->load(c,group); + removeFromAutoCreateList(obj); + } + if ( obj && obj->header){ + obj->header->loadConfig( c ); + } + nameList.next(); + } + + // secondly, after the common dockwidgets, restore the groups and tabgroups + nameList.first(); + while ( nameList.current() ){ + QString oname = nameList.current(); + c->setGroup( group ); + QString type = c->readEntry( oname + ":type" ); + obj = 0L; + + if ( type == "GROUP" ){ + KDockWidget* first = getDockWidgetFromName( c->readEntry( oname + ":first_name" ) ); + KDockWidget* last = getDockWidgetFromName( c->readEntry( oname + ":last_name" ) ); + int sepPos = c->readNumEntry( oname + ":sepPos" ); + + Orientation p = (Orientation)c->readNumEntry( oname + ":orientation" ); + if ( first && last ){ + obj = first->manualDock( last, ( p == Vertical ) ? KDockWidget::DockLeft : KDockWidget::DockTop, sepPos ); + if (obj){ + obj->setName( oname.latin1() ); + } + } + } + + if ( type == "TAB_GROUP" ){ + QStrList list; + KDockWidget* tabDockGroup = 0L; + c->readListEntry( oname+":tabNames", list ); + KDockWidget* d1 = getDockWidgetFromName( list.first() ); + list.next(); + KDockWidget* d2 = getDockWidgetFromName( list.current() ); + tabDockGroup = d2->manualDock( d1, KDockWidget::DockCenter ); + if ( tabDockGroup ){ + KDockTabGroup* tab = dynamic_cast<KDockTabGroup*>(tabDockGroup->widget); + list.next(); + while ( list.current() && tabDockGroup ){ + KDockWidget* tabDock = getDockWidgetFromName( list.current() ); + tabDockGroup = tabDock->manualDock( d1, KDockWidget::DockCenter ); + list.next(); + } + if ( tabDockGroup ){ + tabDockGroup->setName( oname.latin1() ); + c->setGroup( group ); + if (tab) + tab->showPage( tab->page( c->readNumEntry( oname+":curTab" ) ) ); + } + } + obj = tabDockGroup; + } + + if (obj && obj->d->isContainer) dynamic_cast<KDockContainer*>(obj->widget)->load(c,group); + if ( obj && obj->header){ + obj->header->loadConfig( c ); + } + nameList.next(); + } + + // thirdly, now that all ordinary dockwidgets are created, + // iterate them again and link the toplevel ones of them with their corresponding dockwidget for the dockback action + nameList.first(); + while ( nameList.current() ){ + QString oname = nameList.current(); + c->setGroup( group ); + QString type = c->readEntry( oname + ":type" ); + obj = 0L; + + if ( type == "NULL_DOCK" || c->readEntry( oname + ":parent") == "___null___" ){ + obj = getDockWidgetFromName( oname ); + c->setGroup( group ); + QString name = c->readEntry( oname + ":dockBackTo" ); + if (!name.isEmpty()) { + obj->setFormerBrotherDockWidget(getDockWidgetFromName( name )); + } + obj->formerDockPos = KDockWidget::DockPosition(c->readNumEntry( oname + ":dockBackToPos" )); + } + + nameList.next(); + } + + if ( main->inherits("KDockMainWindow") ){ + KDockMainWindow* dmain = (KDockMainWindow*)main; + + c->setGroup( group ); + QString mv = c->readEntry( "Main:view" ); + if ( !mv.isEmpty() && getDockWidgetFromName( mv ) ){ + KDockWidget* mvd = getDockWidgetFromName( mv ); + mvd->applyToWidget( dmain ); + mvd->show(); + dmain->setView( mvd ); + } + c->setGroup( group ); + QString md = c->readEntry( "Main:dock" ); + if ( !md.isEmpty() && getDockWidgetFromName( md ) ){ + KDockWidget* mvd = getDockWidgetFromName( md ); + dmain->setMainDockWidget( mvd ); + } + } else { + c->setGroup( group ); + QString mv = c->readEntry( "Main:view" ); + if ( !mv.isEmpty() && getDockWidgetFromName( mv ) ){ + KDockWidget* mvd = getDockWidgetFromName( mv ); + mvd->applyToWidget( main ); + mvd->show(); + } + + } + + // delete all autocreate dock + if (d->m_readDockConfigMode == WrapExistingWidgetsOnly) { + finishReadDockConfig(); // remove empty dockwidgets + } + + c->setGroup( group ); + QRect mr = c->readRectEntry("Main:Geometry"); + main->move(mr.topLeft()); + main->resize(mr.size()); + if ( isMainVisible ) main->show(); +} +#endif + + +void KDockManager::dumpDockWidgets() { + QObjectListIt it( *childDock ); + KDockWidget * obj; + while ( (obj=(KDockWidget*)it.current()) ) { + ++it; + kdDebug(282)<<"KDockManager::dumpDockWidgets:"<<obj->name()<<endl; + } + +} + +KDockWidget* KDockManager::getDockWidgetFromName( const QString& dockName ) +{ + QObjectListIt it( *childDock ); + KDockWidget * obj; + while ( (obj=(KDockWidget*)it.current()) ) { + ++it; + if ( QString(obj->name()) == dockName ) return obj; + } + + KDockWidget* autoCreate = 0L; + if ( autoCreateDock ){ + kdDebug(282)<<"Autocreating dock: "<<dockName<<endl; + autoCreate = new KDockWidget( this, dockName.latin1(), QPixmap("") ); + autoCreateDock->append( autoCreate ); + } + return autoCreate; +} +void KDockManager::setSplitterOpaqueResize(bool b) +{ + d->splitterOpaqueResize = b; +} + +bool KDockManager::splitterOpaqueResize() const +{ + return d->splitterOpaqueResize; +} + +void KDockManager::setSplitterKeepSize(bool b) +{ + d->splitterKeepSize = b; +} + +bool KDockManager::splitterKeepSize() const +{ + return d->splitterKeepSize; +} + +void KDockManager::setSplitterHighResolution(bool b) +{ + d->splitterHighResolution = b; +} + +bool KDockManager::splitterHighResolution() const +{ + return d->splitterHighResolution; +} + +void KDockManager::slotMenuPopup() +{ + menu->clear(); + menuData->clear(); + + QObjectListIt it( *childDock ); + KDockWidget * obj; + int numerator = 0; + while ( (obj=(KDockWidget*)it.current()) ) { + ++it; + if ( obj->mayBeHide() ) + { + menu->insertItem( obj->icon() ? *(obj->icon()) : QPixmap(), i18n("Hide %1").arg(obj->caption()), numerator++ ); + menuData->append( new MenuDockData( obj, true ) ); + } + + if ( obj->mayBeShow() ) + { + menu->insertItem( obj->icon() ? *(obj->icon()) : QPixmap(), i18n("Show %1").arg(obj->caption()), numerator++ ); + menuData->append( new MenuDockData( obj, false ) ); + } + } +} + +void KDockManager::slotMenuActivated( int id ) +{ + MenuDockData* data = menuData->at( id ); + data->dock->changeHideShowState(); +} + +KDockWidget* KDockManager::findWidgetParentDock( QWidget* w ) const +{ + QObjectListIt it( *childDock ); + KDockWidget * dock; + KDockWidget * found = 0L; + + while ( (dock=(KDockWidget*)it.current()) ) { + ++it; + if ( dock->widget == w ){ found = dock; break; } + } + return found; +} + +void KDockManager::drawDragRectangle() +{ +#ifdef BORDERLESS_WINDOWS + return +#endif + if (d->oldDragRect == d->dragRect) + return; + + int i; + QRect oldAndNewDragRect[2]; + oldAndNewDragRect[0] = d->oldDragRect; + oldAndNewDragRect[1] = d->dragRect; + + // 2 calls, one for the old and one for the new drag rectangle + for (i = 0; i <= 1; i++) { + if (oldAndNewDragRect[i].isEmpty()) + continue; + + KDockWidget* pDockWdgAtRect = (KDockWidget*) QApplication::widgetAt( oldAndNewDragRect[i].topLeft(), true ); + if (!pDockWdgAtRect) + continue; + + bool isOverMainWdg = false; + bool unclipped; + KDockMainWindow* pMain = 0L; + KDockWidget* pTLDockWdg = 0L; + QWidget* topWdg; + if (pDockWdgAtRect->topLevelWidget() == main) { + isOverMainWdg = true; + topWdg = pMain = (KDockMainWindow*) main; + unclipped = pMain->testWFlags( WPaintUnclipped ); + pMain->setWFlags( WPaintUnclipped ); + } + else { + topWdg = pTLDockWdg = (KDockWidget*) pDockWdgAtRect->topLevelWidget(); + unclipped = pTLDockWdg->testWFlags( WPaintUnclipped ); + pTLDockWdg->setWFlags( WPaintUnclipped ); + } + + // draw the rectangle unclipped over the main dock window + QPainter p; + p.begin( topWdg ); + if ( !unclipped ) { + if (isOverMainWdg) + pMain->clearWFlags(WPaintUnclipped); + else + pTLDockWdg->clearWFlags(WPaintUnclipped); + } + // draw the rectangle + p.setRasterOp(Qt::NotXorROP); + QRect r = oldAndNewDragRect[i]; + r.moveTopLeft( r.topLeft() - topWdg->mapToGlobal(QPoint(0,0)) ); + p.drawRect(r.x(), r.y(), r.width(), r.height()); + p.end(); + } + + // memorize the current rectangle for later removing + d->oldDragRect = d->dragRect; +} + +void KDockManager::setSpecialLeftDockContainer(KDockWidget* container) { + d->leftContainer=container; +} + +void KDockManager::setSpecialTopDockContainer(KDockWidget* container) { + d->topContainer=container; +} + +void KDockManager::setSpecialRightDockContainer(KDockWidget* container) { + d->rightContainer=container; + +} + +void KDockManager::setSpecialBottomDockContainer(KDockWidget* container) { + d->bottomContainer=container; +} + + +KDockArea::KDockArea( QWidget* parent, const char *name) +:QWidget( parent, name) +{ + QString new_name = QString(name) + QString("_DockManager"); + dockManager = new KDockManager( this, new_name.latin1() ); + mainDockWidget = 0L; +} + +KDockArea::~KDockArea() +{ + delete dockManager; +} + +KDockWidget* KDockArea::createDockWidget( const QString& name, const QPixmap &pixmap, QWidget* parent, const QString& strCaption, const QString& strTabPageLabel) +{ + return new KDockWidget( dockManager, name.latin1(), pixmap, parent, strCaption, strTabPageLabel ); +} + +void KDockArea::makeDockVisible( KDockWidget* dock ) +{ + if ( dock ) + dock->makeDockVisible(); +} + +void KDockArea::makeDockInvisible( KDockWidget* dock ) +{ + if ( dock ) + dock->undock(); +} + +void KDockArea::makeWidgetDockVisible( QWidget* widget ) +{ + makeDockVisible( dockManager->findWidgetParentDock(widget) ); +} + +void KDockArea::writeDockConfig(QDomElement &base) +{ + dockManager->writeConfig(base); +} + +void KDockArea::readDockConfig(QDomElement &base) +{ + dockManager->readConfig(base); +} + +void KDockArea::slotDockWidgetUndocked() +{ + QObject* pSender = (QObject*) sender(); + if (!pSender->inherits("KDockWidget")) return; + KDockWidget* pDW = (KDockWidget*) pSender; + emit dockWidgetHasUndocked( pDW); +} + +void KDockArea::resizeEvent(QResizeEvent *rsize) +{ + QWidget::resizeEvent(rsize); + if (children()){ +#ifndef NO_KDE2 +// kdDebug(282)<<"KDockArea::resize"<<endl; +#endif + QObjectList *list=queryList("QWidget",0,false); + + QObjectListIt it( *list ); // iterate over the buttons + QObject *obj; + + while ( (obj = it.current()) != 0 ) { + // for each found object... + ((QWidget*)obj)->setGeometry(QRect(QPoint(0,0),size())); + break; + } + delete list; +#if 0 + KDockSplitter *split; +// for (unsigned int i=0;i<children()->count();i++) + { +// QPtrList<QObject> list(children()); +// QObject *obj=((QPtrList<QObject*>)children())->at(i); + QObject *obj=children()->getFirst(); + if (split = dynamic_cast<KDockSplitter*>(obj)) + { + split->setGeometry( QRect(QPoint(0,0), size() )); +// break; + } + } +#endif + } +} + +#ifndef NO_KDE2 +void KDockArea::writeDockConfig( KConfig* c, QString group ) +{ + dockManager->writeConfig( c, group ); +} + +void KDockArea::readDockConfig( KConfig* c, QString group ) +{ + dockManager->readConfig( c, group ); +} + +void KDockArea::setMainDockWidget( KDockWidget* mdw ) +{ + if ( mainDockWidget == mdw ) return; + mainDockWidget = mdw; + mdw->applyToWidget(this); +} +#endif + + + +// KDOCKCONTAINER - AN ABSTRACTION OF THE KDOCKTABWIDGET +KDockContainer::KDockContainer(){m_overlapMode=false; m_childrenListBegin=0; m_childrenListEnd=0;} +KDockContainer::~KDockContainer(){ + + if (m_childrenListBegin) + { + struct ListItem *tmp=m_childrenListBegin; + while (tmp) + { + struct ListItem *tmp2=tmp->next; + free(tmp->data); + delete tmp; + tmp=tmp2; + } + m_childrenListBegin=0; + m_childrenListEnd=0; + } + +} + +void KDockContainer::activateOverlapMode(int nonOverlapSize) { + m_nonOverlapSize=nonOverlapSize; + m_overlapMode=true; + if (parentDockWidget()) { + if (parentDockWidget()->parent()) { + kdDebug(282)<<"KDockContainer::activateOverlapMode: recalculating sizes"<<endl; + KDockSplitter *sp= static_cast<KDockSplitter*>(parentDockWidget()-> + parent()->qt_cast("KDockSplitter")); + if (sp) sp->resizeEvent(0); + } + } +} + +void KDockContainer::deactivateOverlapMode() { + if (!m_overlapMode) return; + m_overlapMode=false; + if (parentDockWidget()) { + if (parentDockWidget()->parent()) { + kdDebug(282)<<"KDockContainer::deactivateOverlapMode: recalculating sizes"<<endl; + KDockSplitter *sp= static_cast<KDockSplitter*>(parentDockWidget()-> + parent()->qt_cast("KDockSplitter")); + if (sp) sp->resizeEvent(0); + } + } + +} + +bool KDockContainer::isOverlapMode() { + return m_overlapMode; +} + + +bool KDockContainer::dockDragEnter(KDockWidget*, QMouseEvent *) { return false;} +bool KDockContainer::dockDragMove(KDockWidget*, QMouseEvent *) { return false;} +bool KDockContainer::dockDragLeave(KDockWidget*, QMouseEvent *) { return false;} + + +KDockWidget *KDockContainer::parentDockWidget(){return 0;} + +QStringList KDockContainer::containedWidgets() const { + QStringList tmp; + for (struct ListItem *it=m_childrenListBegin;it;it=it->next) { + tmp<<QString(it->data); + } + + return tmp; +} + +void KDockContainer::showWidget(KDockWidget *) { +} + +void KDockContainer::insertWidget (KDockWidget *dw, QPixmap, const QString &, int &) + { + struct ListItem *it=new struct ListItem; + it->data=strdup(dw->name()); + it->next=0; + + if (m_childrenListEnd) + { + m_childrenListEnd->next=it; + it->prev=m_childrenListEnd; + m_childrenListEnd=it; + } + else + { + it->prev=0; + m_childrenListEnd=it; + m_childrenListBegin=it; + } + } +void KDockContainer::removeWidget (KDockWidget *dw){ + for (struct ListItem *tmp=m_childrenListBegin;tmp;tmp=tmp->next) + { + if (!strcmp(tmp->data,dw->name())) + { + free(tmp->data); + if (tmp->next) tmp->next->prev=tmp->prev; + if (tmp->prev) tmp->prev->next=tmp->next; + if (tmp==m_childrenListBegin) m_childrenListBegin=tmp->next; + if (tmp==m_childrenListEnd) m_childrenListEnd=tmp->prev; + delete tmp; + break; + } + } +} + +//m_children.remove(dw->name());} +void KDockContainer::undockWidget (KDockWidget *){;} +void KDockContainer::setToolTip(KDockWidget *, QString &){;} +void KDockContainer::setPixmap(KDockWidget*,const QPixmap&){;} +void KDockContainer::load (KConfig*, const QString&){;} +void KDockContainer::save (KConfig*, const QString&){;} +void KDockContainer::load (QDomElement&){;} +void KDockContainer::save (QDomElement&){;} +void KDockContainer::prepareSave(QStringList &names) +{ + + for (struct ListItem *tmp=m_childrenListBegin;tmp; tmp=tmp->next) + names.remove(tmp->data); +// for (uint i=0;i<m_children.count();i++) +// { +// names.remove(m_children.at(i)); +// } +} + + +QWidget *KDockTabGroup::transientTo() { + QWidget *tT=0; + for (int i=0;i<count();i++) { + KDockWidget *dw=static_cast<KDockWidget*>(page(i)->qt_cast("KDockWidget")); + QWidget *tmp; + if ((tmp=dw->transientTo())) { + if (!tT) tT=tmp; + else { + if (tT!=tmp) { + kdDebug(282)<<"KDockTabGroup::transientTo: widget mismatch"<<endl; + return 0; + } + } + } + } + + kdDebug(282)<<"KDockTabGroup::transientTo: "<<(tT?"YES":"NO")<<endl; + + return tT; +} + +void KDockWidgetAbstractHeader::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +void KDockWidgetAbstractHeaderDrag::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +void KDockWidgetHeaderDrag::virtual_hook( int id, void* data ) +{ KDockWidgetAbstractHeaderDrag::virtual_hook( id, data ); } + +void KDockWidgetHeader::virtual_hook( int id, void* data ) +{ KDockWidgetAbstractHeader::virtual_hook( id, data ); } + +void KDockTabGroup::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +void KDockWidget::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +void KDockManager::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + +void KDockMainWindow::virtual_hook( int id, void* data ) +{ KMainWindow::virtual_hook( id, data ); } + +void KDockArea::virtual_hook( int, void* ) +{ /*KMainWindow::virtual_hook( id, data );*/ } + + +#ifndef NO_INCLUDE_MOCFILES // for Qt-only projects, because tmake doesn't take this name +#include "kdockwidget.moc" +#endif diff --git a/lib/compatibility/kmdi/qextmdi/kdockwidget.h b/lib/compatibility/kmdi/qextmdi/kdockwidget.h new file mode 100644 index 00000000..8858b9ba --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kdockwidget.h @@ -0,0 +1,1534 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Max Judin <novaprint@mtu-net.ru> + Copyright (C) 2000 Falk Brettschneider <falk@kdevelop.org> + Copyright (C) 2002,2003 Joseph Wenninger <jowenn@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 version 2 as published by the Free Software Foundation. + + 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. +*/ + +/* + activities: + ----------- + 05/2001 - : useful patches, bugfixes by Christoph Cullmann <crossfire@babylon2k.de>, + Joseph Wenninger <jowenn@bigfoot.com> and Falk Brettschneider + 03/2001 - 05/2001 : maintained and enhanced by Falk Brettschneider <falk@kdevelop.org> + 03/2000 : class documentation added by Falk Brettschneider <gigafalk@yahoo.com> + 10/1999 - 03/2000 : programmed by Max Judin <novaprint@mtu-net.ru> + + C++ classes in this file: + ------------------------- + - KDockWidgetAbstractHeader - minor helper class + - KDockWidgetAbstractHeaderDrag - minor helper class + - KDockWidgetHeaderDrag - drag panel in a dockwidget title bar + - KDockWidgetHeader - dockwidget title bar containing the drag panel + - KDockTabGroup - minor helper class + - KDockWidget - IMPORTANT CLASS: the one and only dockwidget class + - KDockManager - helper class + - KDockMainWindow - IMPORTANT CLASS: a special KMainWindow that can have dockwidgets + - KDockArea - like KDockMainWindow but inherits just QWidget + + IMPORTANT Note: This file compiles also in Qt-only mode by using the NO_KDE2 precompiler definition! +*/ + + +#ifndef KDOCKWIDGET_H +#define KDOCKWIDGET_H + +#define _KDOCKWIDGET_2_2_ + +#include <qpoint.h> +#include <qptrlist.h> +#include <qframe.h> +#include <qdom.h> +#include <qtabwidget.h> + +#ifndef NO_KDE2 +#include <kmainwindow.h> +#include <netwm_def.h> +#else + +#include <qmainwindow.h> +#include "exportdockclass.h" +#include "dummykmainwindow.h" +#endif + +#include <kdelibs_export.h> + +class KDockSplitter; +class KDockManager; +class KDockMoveManager; +class KDockWidget; +class KDockButton_Private; +class KDockWidgetPrivate; +class KDockWidgetHeaderPrivate; +class KDockArea; + +class QObjectList; +class QPopupMenu; +class QVBoxLayout; +class QHBoxLayout; +class QPixmap; + +#ifndef NO_KDE2 +class KToolBar; +class KConfig; +#else +class QToolBar; +#endif + +class KDockContainer; + +namespace KMDI +{ + class MainWindow; +} + +/** + * An abstract base clase for all dockwidget headers (and member of the dockwidget class set). + * See the class description of KDockWidgetHeader! + * More or less a minor helper class for the dockwidget class set. + * + * @author Max Judin (documentation: Falk Brettschneider). + */ +class KDockWidgetAbstractHeader : public QFrame +{ + Q_OBJECT +public: + + /** + * Constructs this. + * + * @param parent the parent widget (usually a dockwidget) + * @param name the object instance name + */ + KDockWidgetAbstractHeader( KDockWidget* parent, const char* name = 0L ); + + /** + * Destructs this. + */ + virtual ~KDockWidgetAbstractHeader(){}; + + /** + * Provides things concerning to switching to toplevel mode. Must be overridden by an inheriting class. + */ + virtual void setTopLevel( bool ){}; + +#ifndef NO_KDE2 + /** + * Provides saving the current configuration. Must be overridden by an inheriting class. + */ + virtual void saveConfig( KConfig* ){}; + + /** + * Provides loading the current configuration. Must be overridden by an inheriting class + */ + virtual void loadConfig( KConfig* ){}; +#endif + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KDockWidgetAbstractHeaderPrivate; + KDockWidgetAbstractHeaderPrivate *d; +}; + +/** + * An abstract class for all dockwidget drag-panels of a dockwidgets (and member of the dockwidget class set). + * See the class description of KDockWidgetHeaderDrag! + * More or less a minor helper class for the dockwidget class set. + * + * @author Max Judin (documentation: Falk Brettschneider). + */ +class KDEUI_EXPORT KDockWidgetAbstractHeaderDrag : public QFrame +{ + Q_OBJECT +public: + + /** + * Constructs this. + * + * @param parent the parent widget (usually a dockwidget header) + * @param dock the dockwidget where it belongs to + * @param name the object instance name + */ + KDockWidgetAbstractHeaderDrag( KDockWidgetAbstractHeader* parent, + KDockWidget* dock, const char* name = 0L ); + + /** + * Destructs this. + */ + virtual ~KDockWidgetAbstractHeaderDrag(){}; + + /** + * @return the dockwidget where this belongs to + */ + KDockWidget* dockWidget() const { return dw; } + +private: + /** + * the dockwidget where this belongs to + */ + KDockWidget* dw; +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KDockWidgetAbstractHeaderDragPrivate; + KDockWidgetAbstractHeaderDragPrivate *d; +}; + +/** + * This special widget is the panel one can grip with the mouses (and member of the dockwidget class set). + * The widget for dragging, so to speak. + * Usually it is located in the KDockWidgetHeader. + * More or less a minor helper class for the dockwidget class set. + * + * @author Max Judin (documentation: Falk Brettschneider). + */ +class KDEUI_EXPORT KDockWidgetHeaderDrag : public KDockWidgetAbstractHeaderDrag +{ + Q_OBJECT +public: + + /** + * Constructs this. + * + * @param parent the parent widget (usually a dockwidget header) + * @param dock the dockwidget where it belongs to + * @param name the object instance name + */ + KDockWidgetHeaderDrag( KDockWidgetAbstractHeader* parent, KDockWidget* dock, + const char* name = 0L ); + + /** + * Destructs this. + */ + virtual ~KDockWidgetHeaderDrag(){}; + +protected: + + /** + * Draws the drag panel (a double line) + */ + virtual void paintEvent( QPaintEvent* ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KDockWidgetHeaderDragPrivate; + KDockWidgetHeaderDragPrivate *d; +}; + +/** + * The header (additional bar) for a KDockWidget s (and member of the dockwidget class set). + * It have got the buttons located there. And it is for recording and reading the button states. + * More or less a minor helper class for the dockwidget class set. + * + * @author Max Judin (documentation: Falk Brettschneider). + */ +class KDEUI_EXPORT KDockWidgetHeader : public KDockWidgetAbstractHeader +{ + Q_OBJECT +public: + + /** + * Constructs this. + * + * @param parent the parent widget (usually a dockwidget) + * @param name the object instance name + */ + KDockWidgetHeader( KDockWidget* parent, const char* name = 0L ); + + /** + * Destructs this. + */ + virtual ~KDockWidgetHeader(){}; + + /** + * Hides the close button and stay button when switching to toplevel or vice versa shows them. + * + * @param t toplevel or not + */ + virtual void setTopLevel( bool t); + + /** + * Sets the drag panel of this header. + * + * @param nd A pointer to the new drag panel + */ + void setDragPanel( KDockWidgetHeaderDrag* nd ); + + /** + * Get the drag panel of this header. + * + * @since 3.4 + */ + KDockWidgetHeaderDrag *dragPanel(); + + bool dragEnabled() const; + void setDragEnabled(bool b); + /// @since 3.1 + void showUndockButton(bool show); + + /// @since 3.2 + void forceCloseButtonHidden(bool enable=true); +#ifndef NO_KDE2 + /** + * Saves the current button state to a KDE config container object. + * + * @param c the configuration safe + */ + virtual void saveConfig( KConfig* c); + + /** + * Loads the current button state from a KDE config container object. + * + * @param c the configuration safe + */ + virtual void loadConfig( KConfig* c); +#endif + + /*@since 3.2 + * add an arbitrary button to the dockwidget header + * NOT PART OF THE PUBLIC API (you don't have access the class defintion anyways, without special + * header file copying. (don't do it)) + */ + void addButton(KDockButton_Private*); + + /*@since 3.2 + * remove an arbtrary button from the dockwidget header + * NOT PART OF THE PUBLIC API (you don't have access the class defintion anyways, without special + * header file copying. (don't do it)) + */ + void removeButton(KDockButton_Private*); + + + +protected slots: + /** + * Sets dragging the dockwidget off when the stay button is pressed down and vice versa. + */ + void slotStayClicked(); + +protected: + + /** + * A layout manager for placing the embedded buttons (close and stay) + */ + QHBoxLayout* layout; + + /** + * a little button for closing (undocking and hiding) the dockwidget + */ + KDockButton_Private* closeButton; + + /** + * a little button for enabling/disabling dragging the dockwidget with the mouse + */ + KDockButton_Private* stayButton; + + /** + * a little button for dock back the dockwidget to it's previous dockwidget + */ + KDockButton_Private* dockbackButton; + + /** + * the drag panel (double line) + */ + KDockWidgetHeaderDrag* drag; + +protected: + virtual void virtual_hook( int id, void* data ); +private: + KDockWidgetHeaderPrivate *d; +}; + +/** + * It just hides the special implementation of a dockwidget tab groups (and is member of the dockwidget class set). + * An abstraction what it is currently. + * In general it is like QTabWidget but is more useful for the dockwidget class set. + * More or less a minor helper class for the dockwidget class set. + * + * @author Max Judin (documentation: Falk Brettschneider). + */ +class KDEUI_EXPORT KDockTabGroup : public QTabWidget +{ + Q_OBJECT +public: + /** + * Constructs this. It just calls the method of the base class. + */ + KDockTabGroup( QWidget *parent = 0, const char *name = 0 ) + :QTabWidget( parent, name ){}; + + /** + * Destructs a KDockTabGroup. + */ + virtual ~KDockTabGroup(){}; + + QWidget *transientTo(); +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KDockTabGroupPrivate; + KDockTabGroupPrivate *d; +}; + + +/** + * Floatable widget that can be dragged around with the mouse and + * encapsulate the actual widgets (and member of the dockwidget class + * set). + * + * You just grip the double-lined panel, tear it off its parent + * widget, drag it somewhere and let it loose. Depending on the + * position where you leave it, the dockwidget becomes a toplevel + * window on the desktop (floating mode) or docks to a new widget + * (dock mode). Note: A KDockWidget can only be docked to a + * KDockWidget. + * + * If you want to use this kind of widget, your main application + * window has to be a KDockMainWindow. That is because it has + * got several additional dock management features, for instance a + * KDockManager that has an overview over all dockwidgets and and + * a dockmovemanager (internal class) that handles the dock process. + * + * Usually you create an KDockWidget that covers the actual widget in this way: + * \code + * ... + * KDockMainWindow* mainWidget; + * ... + * KDockWidget* dock = 0L; + * dock = mainWidget->createDockWidget( "Any window caption", nicePixmap, 0L, i18n("window caption")); // 0L==no parent + * QWidget* actualWidget = new QWidget( dock); + * dock->setWidget( actualWidget); // embed it + * dock->setToolTipString(i18n("That's me")); // available when appearing as tab page + * ... + * \endcode + * + * See KDockMainWindow how a dockwidget is docked in. + * + * + * @author Max Judin (documentation: Falk Brettschneider). + */ +class KDEUI_EXPORT KDockWidget: public QWidget +{ + Q_OBJECT +friend class KDockManager; +friend class KDockSplitter; +friend class KDockMainWindow; +friend class KDockArea; + +public: + /** + * Construct a dockwidget. + * + * Initially, docking to another and docking to this is allowed for + * every @p DockPosition. It is supposed to be no (tab) group. It will + * taken under control of its dockmanager. + * + * @param dockManager The responsible manager (dock helper) + * @param name Object instance name + * @param pixmap An icon (for instance shown when docked centered) + * @param parent Parent widget + * @param strCaption Title of the dockwidget window (shown when toplevel) + * @param strTabPageLabel The title of the tab page (shown when in tab page mode), if it is "", only the icon will be shown, if it is 0L, the label is set to strCaption + * @param f Qt::WidgetFlags widget flags + */ + KDockWidget( KDockManager* dockManager, const char* name, + const QPixmap &pixmap, QWidget* parent = 0L, const QString& strCaption = QString::null, + const QString& strTabPageLabel = QString::fromLatin1( " " ), WFlags f = 0); + + /** + * Destructs a dockwidget. + */ + virtual ~KDockWidget(); + + /** + * The possible positions where a dockwidget can dock to another dockwidget + */ + enum DockPosition + { + DockNone = 0, + DockTop = 0x0001, + DockLeft = 0x0002, + DockRight = 0x0004, + DockBottom = 0x0008, + DockCenter = 0x0010, + DockDesktop= 0x0020, + DockToSpecialSites=0x0040, ///< @since 3.1 + DockCorner = DockTop | DockLeft | DockRight | DockBottom, + DockFullSite = DockCorner | DockCenter, + DockFullDocking = DockFullSite | DockDesktop + }; + + /** + * This is a key method of this class! Use it to dock dockwidgets to + * another dockwidget at the right position within its + * KDockMainWindow or a toplevel dockwidget. + * + * + * If the target is null, it will become a toplevel dockwidget at position pos; + * Note: Docking to another dockwidget means exactly: + * A new parent dockwidget will be created, that replaces the target dockwidget and contains another single helper widget (tab widget or panner) + * which contains both dockwidgets, this and the target dockwidget. So consider parent<->child relationships change completely during such actions. + * + * @param target The dockwidget to dock to + * @param dockPos One of the DockPositions this is going to dock to + * @param spliPos The split relation (in percent, or percent*100 in high resolution) between both dockwidgets, target and this + * @param pos The dock position, mainly of interest for docking to the desktop (as toplevel dockwidget) + * @param check Only for internal use; + * @param tabIndex The position index of the tab widget (when in tab page mode), -1 (default) means append + * @return result The group dockwidget that replaces the target dockwidget and will be grandparent of target and @p this. + */ + KDockWidget* manualDock( KDockWidget* target, DockPosition dockPos, int spliPos = 50, QPoint pos = QPoint(0,0), bool check = false, int tabIndex = -1); + + /** + * Specify where it is either possible or impossible for this to dock to another dockwidget. + * + * @param pos An OR'ed set of @p DockPositions + */ + void setEnableDocking( int pos ); + + /** + * @return Where it is either possible or impossible for this to dock to another dockwidget (an OR'ed set of DockPositions). + */ + int enableDocking() const { return eDocking; } + + /** + * Specify where it is either possible or impossible for another dockwidget to dock to this. + * + * @param pos An OR'ed set of @p DockPositions + */ + void setDockSite( int pos ){ sDocking = pos;} + + /** + * @return There it is either possible or impossible for another dockwidget to dock to this (an OR'ed set of @p DockPositions). + */ + int dockSite() const { return sDocking; } + + /** + * Sets the embedded widget. + * + * A QLayout takes care about proper resizing, automatically. + * + * @param w The pointer to the dockwidget's child widget. + */ + void setWidget( QWidget* w); + + /** + * Get the embedded widget. + * + * @return The pointer to the dockwidget's child widget, 0L if there's no such child. + */ + QWidget* getWidget() const { return widget; }; + + /** + * Sets the header of this dockwidget. + * + * A QLayout takes care about proper resizing, automatically. + * The header contains the drag panel, the close button and the stay button. + * + * @param ah A base class pointer to the dockwidget header + */ + void setHeader( KDockWidgetAbstractHeader* ah); + + /**@since 3.2 + * get the pointer to the header widget + */ + KDockWidgetAbstractHeader *getHeader(); + + /** + * Normally it simply shows the dockwidget. + * + * But additionally, if it is docked to a tab widget (@p DockCenter), it is set as the active (visible) tab page. + */ + void makeDockVisible(); + + /** + * @return If it may be possible to hide this. + * + * There are reasons that it's impossible: + * @li It is a (tab) group. + * @li It is already invisible ;-) + * @li The parent of this is the KDockMainWindow. + * @li It isn't able to dock to another widget. + */ + bool mayBeHide() const; + + /** + * @return If it may be possible to show this. + * There are reasons that it's impossible: + * @li It is a (tab) group. + * @li It is already visible ;-) + * @li The parent of this is the @p KDockMainWindow. + */ + bool mayBeShow() const; + + /** + * @return The dockmanager that is responsible for this. + */ + KDockManager* dockManager() const { return manager; } + + /** + * Stores a string for a tooltip. + * + * That tooltip string has only a meaning when this dockwidget is shown as tab page. + * In this case the tooltip is shown when one holds the mouse cursor on the tab page header. + * Such tooltip will for instance be useful, if you use only icons there. + * Note: Setting an empty string switches the tooltip off. + * + * @param ttStr A string for the tooltip on the tab. + */ + void setToolTipString(const QString& ttStr) { toolTipStr = ttStr; }; + + /** + * @return The tooltip string being shown on the appropriate tab page header when in dock-centered mode. + */ + const QString& toolTipString() const { return toolTipStr; }; + + /** + * @return result @p true, if a dockback is possible, otherwise @p false. + */ + bool isDockBackPossible() const; + + /** + * Sets a string that is used for the label of the tab page when in tab page mode + * @param label The new tab page label. + */ + void setTabPageLabel( const QString& label) { tabPageTitle = label; }; + + /** + * @return A string that is used for the label of the tab page when in tab page mode. + */ + const QString& tabPageLabel() const { return tabPageTitle; }; + + /** + * Catches and processes some QWidget events that are interesting for dockwidgets. + */ + virtual bool event( QEvent * ); + + /** + * Add dockwidget management actions to QWidget::show. + */ + virtual void show(); + /** + * @return the parent widget of this if it inherits class KDockTabGroup + */ + KDockTabGroup* parentDockTabGroup() const; + + /// @since 3.1 + QWidget *parentDockContainer() const; + +#ifndef NO_KDE2 + + /** + * Sets the type of the dock window + * + * @param windowType is type of dock window + */ + void setDockWindowType (NET::WindowType windowType); + +#endif + + void setDockWindowTransient (QWidget *parent, bool transientEnabled); + + /** + * Returns the widget this dockwidget is set transient to, otherwise 0 + * @since 3.2 + */ + QWidget *transientTo(); + + /** + * Lookup the nearest dockwidget docked left/right/top/bottom to this one or return 0 + * + * @param pos is the position the wanted widget is docked to this one + * @since 3.1 + */ + KDockWidget *findNearestDockWidget(DockPosition pos); + + /** + * Allows changing the pixmap which is used for the caption or dock tabs + * + * @param pixmap is the pixmap to set + * @since 3.2 + */ + void setPixmap(const QPixmap& pixmap=QPixmap()); + + /** + * Returns the dockwidget's associated caption/dock tab pixmap + * + * @since 3.2 + */ + const QPixmap& pixmap() const; + + /** + * @return the current dock position. + * @since 3.3 + */ + KDockWidget::DockPosition currentDockPosition() const; + +public slots: + /** + * subject to changes. It doesn't completely work yet without small hacks from within the calling application (Perhaps + * KDE 3.1.x oder 3.2 + * width is in pixel. It only affects a widget, which is placed directly into a horizontal KDockSplitter + * @since 3.1 + **/ + void setForcedFixedWidth(int); + /** + * subject to changes. It doesn't completely work yet without small hacks from within the calling application (Perhaps + * KDE 3.1.x oder 3.2 + * height is in pixel. It only affects a widget, which is placed directly into a vertical KDockSplitter + * @since 3.1 + **/ + void setForcedFixedHeight(int); + /// @since 3.1 + void restoreFromForcedFixedSize(); + + /// @since 3.1 + int forcedFixedWidth(); + /// @since 3.1 + int forcedFixedHeight(); + + /** + * Docks a dockwidget back to the dockwidget that was the neighbor + widget before the current dock position. + */ + void dockBack(); + + /** + * Toggles the visibility state of the dockwidget if it is able to be shown or to be hidden. + */ + void changeHideShowState(); + + /** + * Undocks this. It means it becomes a toplevel widget framed by the system window manager. + * A small panel at the top of this undocked widget gives the possibility to drag it into + * another dockwidget by mouse (docking). + */ + void undock(); + + /** + * Docks the widget to the desktop (as a toplevel widget) + * @since 3.1 + */ + void toDesktop( ); + +protected: + friend class KMdiMainFrm; + friend class KMDI::MainWindow; + /** + * Checks some conditions and shows or hides the dockwidget header (drag panel). + * The header is hidden if: + * @li the parent widget is the KDockMainWindow + * @li this is a (tab) group dockwidget + * @li it is not able to dock to another dockwidget + */ + void updateHeader(); + + /// @since 3.1 + void setLatestKDockContainer(QWidget *); + /// @since 3.1 + QWidget *latestKDockContainer(); + + /// @since 3.2 + void setFormerBrotherDockWidget(KDockWidget *); + +signals: + /** + *@since 3.2 + *is emitted after the setWidget method has finished + */ + void widgetSet(QWidget*); + + /** + * Emitted when another dock widget is docking to this. + * + * @param dw the dockwidget that is docking to this + * @param dp the DockPosition where it wants to dock to + */ + void docking( KDockWidget* dw, KDockWidget::DockPosition dp); + + /** + * Signals that the dock default position is set. + */ + void setDockDefaultPos(); + + /** + * Emitted when the close button of the panel ( KDockWidgetHeader) has been clicked. + */ + void headerCloseButtonClicked(); + + /** + * Emitted when the dockback button of the panel ( KDockWidgetHeader) has been clicked. + */ + void headerDockbackButtonClicked(); + + /** + * Emitted when the widget processes a close event. + */ + void iMBeingClosed(); + /** + * Emitted when the widget has undocked. + */ + void hasUndocked(); + +protected slots: + + /** Does several things here when it has noticed that the former brother widget (closest neighbor) gets lost. + * The former brother widget is needed for a possible dockback action, to speak with the Beatles: + * "To get back to where you once belonged" ;-) + */ + void loseFormerBrotherDockWidget(); + + virtual void paintEvent(QPaintEvent*); + + virtual void mousePressEvent(QMouseEvent*); + virtual void mouseReleaseEvent(QMouseEvent*); + virtual void mouseMoveEvent(QMouseEvent*); + virtual void leaveEvent(QEvent*); +protected: + friend class KDockWidgetHeader; + /** + * earlier closest neighbor widget, so it's possible to dock back to it. + */ + KDockWidget* formerBrotherDockWidget; + /** + * the current dock position. + */ + DockPosition currentDockPos; + /** + * the former dock position when it really was at another position before. + */ + DockPosition formerDockPos; + /** + * a string used as tooltip for the tab page header when in dock-centered mode. + */ + QString toolTipStr; + /** + * a string used as title of the tab page when in tab page mode + */ + QString tabPageTitle; + +private: + /** + * Sets the caption (window title) of the given tab widget. + * + * @param g the group (tab) widget + */ + void setDockTabName( KDockTabGroup* g); + + /** + * Reparent to s or set this to the KDockMainWindow's view if s is that dockmainwindow. + * If s is O, simply move the widget. + * + * @param s the target widget to reparent to + * @param p the point to move to (if it doesn't reparent) + */ + void applyToWidget( QWidget* s, const QPoint& p = QPoint(0,0) ); + + /** + * A base class pointer to the header of this dockwidget + */ + KDockWidgetAbstractHeader* header; + + /** + * the embedded widget + */ + QWidget* widget; + + /** + * the layout manager that takes care about proper resizing and moving the embedded widget and the header + */ + QVBoxLayout* layout; + + /** + * the responsible dockmanager + */ + KDockManager* manager; + + /** + * an icon for the tab widget header + */ + QPixmap* pix; + + /** + * Information about the ability for docking to another dockwidget. + */ + int eDocking; + + /** + * Information which site of this dockwidget is free for docking of other dockwidgets. + */ + int sDocking; + + /** + * Previous side (left,right,top,bottom) where this dockwidget was before a dragging action, none if it wasn't dragged before. + */ + KDockWidget::DockPosition prevSideDockPosBeforeDrag; + + // GROUP data + QString firstName; + QString lastName; + Orientation splitterOrientation; + bool isGroup; + bool isTabGroup; +protected: + virtual void virtual_hook( int id, void* data ); +private: + KDockWidgetPrivate *d; +}; + +/** + * The manager that knows all dockwidgets and handles the dock process (and member of the dockwidget class set). + * More or less a helper class for the KDockWidget class set but of interest for some functionality + * that can be called within a KDockMainWindow or a KDockWidget . + * + * An important feature is the ability to read or save the current state of all things concerning to + * dockwidgets to KConfig . + * + * The dockmanager is also often used when a certain dockwidget or a child of such dockwidget must be found. + * + * @author Max Judin (documentation: Falk Brettschneider). + */ +class KDEUI_EXPORT KDockManager: public QObject +{ + Q_OBJECT +friend class KDockWidget; +friend class KDockMainWindow; + +public: + enum EnReadDockConfigMode { + Unknown, + WrapExistingWidgetsOnly, + RestoreAllDockwidgets + }; + +public: + /** + * Constructs a dockmanager. Some initialization happen: + * @li It installs an event filter for the main window, + * @li a control list for dock objects + * @li a control list for menu items concerning to menus provided by the dockmanager + * @li Some state variables are set + * + * @param mainWindow the main window controlled by this + * @param name the internal QOject name + */ + KDockManager( QWidget* mainWindow, const char* name = 0L ); + + /** + * Destructs a dockmanager. + */ + virtual ~KDockManager(); + + void dumpDockWidgets(); + +#ifndef NO_KDE2 + /** + * Saves the current state of the dockmanager and of all controlled widgets. + * State means here to save the geometry, visibility, parents, internal object names, orientation, + * separator positions, dockwidget-group information, tab widget states (if it is a tab group) and + * last but not least some necessary things for recovering the dockmainwindow state. + * + * @param c the KDE configuration saver + * @param group the name of the section in KConfig + */ + void writeConfig( KConfig* c = 0L, QString group = QString::null ); + + /** + * Like writeConfig but reads the whole stuff in. + * + * In order to restore a window configuration + * from a config file, it looks up widgets by name + * (QObject::name) in the childDock variable of + * KDockManager. This list in turn contains all + * KDockWidgets (according to the KDockWidget constructor). + * So in principle, in order to restore a window layout, + * one must first construct all widgets, put each of them in a + * KDockWidget and then call readConfig(). And for all that + * to work, each widget must have a unique name. + * + * @param c the KDE configuration saver + * @param group the name of the section in KConfig + */ + void readConfig ( KConfig* c = 0L, QString group = QString::null ); +#endif + + /// @since 3.1 + void setMainDockWidget2(KDockWidget *); + + /** + * Saves the current dock window layout into a DOM tree below the given element. + */ + void writeConfig(QDomElement &base); + /** + * Reads the current dock window layout from a DOM tree below the given element. + */ + void readConfig(QDomElement &base); + + /** + * Shows all encapsulated widgets of all controlled dockwidgets and shows all dockwidgets which are + * parent of a dockwidget tab group. + */ + void activate(); + + /** + * It's more or less a method that catches several events which are interesting for the dockmanager. + * Mainly mouse events during the drag process of a dockwidgets are of interest here. + * + * @param object the object that sends the event + * @param event the event + * @return the return value of the method call of the base class method + */ + virtual bool eventFilter( QObject * object, QEvent * event ); + + /** + * This method finds out what a widgets' dockwidget is. That means the dockmanager has a look at all + * dockwidgets it knows and tells you when one of those dockwidgets covers the given widget. + * + * @param w any widget that is supposed to be encapsulated by one of the controlled dockwidgets + * @return the dockwidget that encapsulates that widget, otherwise 0 + */ + KDockWidget* findWidgetParentDock( QWidget* w) const; + + /** + * Works like makeDockVisible() but can be called for widgets that covered by a dockwidget. + * + * @param w the widget that is encapsulated by a dockwidget that turns to visible. + */ + void makeWidgetDockVisible( QWidget* w ){ findWidgetParentDock(w)->makeDockVisible(); } + + /** + * @return the popupmenu for showing/hiding dockwidgets + */ + QPopupMenu* dockHideShowMenu() const { return menu; } + + /** + * @param dockName an internal QObject name + * @return the dockwidget that has got that internal QObject name + */ + KDockWidget* getDockWidgetFromName( const QString& dockName ); + + /** + * Enables opaque resizing. Opaque resizing defaults to KGlobalSettings::opaqueResize(). + * Call this method before you create any dock widgets! + */ + void setSplitterOpaqueResize(bool b=true); + + /** + * Returns true if opaque resizing is enabled, false otherwise. + */ + bool splitterOpaqueResize() const; + + /** + * Try to preserve the widget's size. Works like KeepSize resize mode + * of QSplitter. Off by default. + * Call this method before you create any dock widgets! + */ + void setSplitterKeepSize(bool b=true); + + /** + * Returns true if the KeepSize is enabled, false otherwise. + */ + bool splitterKeepSize() const; + + /** + * Operate the splitter with a higher resolution. Off by default. + * Call this method before you create any dock widgets! + * If high resolution is used all splitter position parameters + * are percent*100 instead of percent. + */ + void setSplitterHighResolution(bool b=true); + + /** + * Returns true if the splitter uses the high resolution, false otherwise. + */ + bool splitterHighResolution() const; + + /** + * @since 3.2 + */ + void setSpecialLeftDockContainer(KDockWidget* container); + void setSpecialTopDockContainer(KDockWidget* container); + void setSpecialRightDockContainer(KDockWidget* container); + void setSpecialBottomDockContainer(KDockWidget* container); + + void removeFromAutoCreateList(KDockWidget* pDockWidget); + void finishReadDockConfig(); + void setReadDockConfigMode(int mode); + +signals: + + /** + * Signals changes of the docking state of a dockwidget. Usually the dock-toolbar will be updated then. + */ + void change(); + + /** + * Signals a dockwidget is replaced with another one. + */ + void replaceDock( KDockWidget* oldDock, KDockWidget* newDock ); + + /** + * Signals a dockwidget without parent (toplevel) is shown. + */ + void setDockDefaultPos( KDockWidget* ); + +private slots: + + /** + * Clears the popupmenu for showing/hiding dockwidgets and fills it with the current states of all controlled dockwidgets. + */ + void slotMenuPopup(); + + /** + * This method assumes a menuitem of the popupmenu for showing/hiding dockwidgets is selected and toggles that state. + * + * @param id the popupmenu id of the selected menuitem + */ + void slotMenuActivated( int id); + + /* clears the old drawn drag rectangle (oldDragRect) from screen and + * draws the new current drag rectangle (dragRect) depending on the current mouse position. + * This highlights the dockwidget which is the currently chosen target during a dock action. + */ + void drawDragRectangle(); + +private: + + /** + * A data structure containing data about every dockwidget that is under control. + */ + struct MenuDockData + { + MenuDockData( KDockWidget* _dock, bool _hide ) + { + dock = _dock; + hide = _hide; + }; + ~MenuDockData(){}; + + KDockWidget* dock; + bool hide; + }; + + /** + * Finds the KDockWidget at the position given as parameter + * + * @param pos global (desktop) position of the wanted dockwidget + * @return the dockwidget at that position + */ + KDockWidget* findDockWidgetAt( const QPoint& pos ); + + /** + * Finds the QWidget recursively at the position given as parameter + * + * @param w a variable where the method puts the QWidget at that position (instead of a return value) + * @param p the parent widget where the recursive search should start from + * @param pos global (desktop) position of the wanted dockwidget + */ + void findChildDockWidget( QWidget*& w, const QWidget* p, const QPoint& pos ); + + /** + * Finds all dockwidgets which are child, grandchild and so on of p. + * + * @param p the parent widget where the recursive search starts from + * @param l the widget list that contains the search result after the return of this method + */ + void findChildDockWidget( const QWidget* p, QWidgetList*& l); + + /** + * Sets a dockwidget in drag mode. + */ + void startDrag( KDockWidget* ); + + /** + * Moves a dockwidget that is in drag mode. + * + * @param d the dockwidget which is dragged + * @param pos the new position of the dragged dockwidget + */ + void dragMove( KDockWidget* d, QPoint pos ); + + /** + * Aborts the drag mode. Restores the cursor and hides the drag indicator. + */ + void cancelDrop(); + + /** + * Finishes the drag mode. If the user let it drop on an other dockwidget, it will possibly be docked (if allowed), + * if the user drops it outside of the application window it becomes toplevel. + */ + void drop(); + +// class members + + /** + * Usually the KDockMainWindow but not necessarily. + */ + QWidget* main; + + /** + * The dockwidget that is being dragged at the moment + */ + KDockWidget* currentDragWidget; + + /** + * The target dockwidget where the currentDragWidget is dropped + */ + KDockWidget* currentMoveWidget; // widget where mouse moving + + /** + * It is of interest during the dock process. Then it contains all child dockwidgets. + */ + QWidgetList* childDockWidgetList; + + /** + * The dockposition where the dockwidget would be docked to, if we dropped it here. + */ + KDockWidget::DockPosition curPos; + + /** + * A QList of all objects that are important for docking. + * Some serve as group widgets of dockwidgets, others encapsulate normal widgets. + */ + QObjectList* childDock; + + /** + * Contains dockwidgets that are created automatically by the dockmanager. For internal use. + */ + QObjectList* autoCreateDock; + + /** + * For storing the width during the dragging of a dockwidget. + */ + int storeW; + + /** + * For storing the height during the dragging of a dockwidget. + */ + int storeH; + + /** + * State variable if there is a drag process active. + */ + bool dragging; + + /** + * State variable if there is an undock process active + */ + bool undockProcess; + + /** + * The dockmanager sets it to true if the user cancels the drag by moving the cursor + * on a invalid drop place + */ + bool dropCancel; + + /** + * A popup menu that contains one menuitem for each dockwidget that shows the current visibility state and + * to show or hide the appropriate dockwidget. + */ + QPopupMenu* menu; + + /** + * An internal list containing data for the menuitems for the visibility popup menu. + */ + QPtrList<MenuDockData> *menuData; + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KDockManagerPrivate; + KDockManagerPrivate *d; +}; + +/** + * A special kind of KMainWindow that is able to have dockwidget child widgets (and member of the dockwidget class set). + * + * The main widget should be a KDockWidget where other KDockWidget can be docked to + * the left, right, top, bottom or to the middle. + * Note: dock to the middle means to drop on a dockwidget and to unite them to a new widget, a tab control. + * + * Furthermore, the KDockMainWindow has got the KDockManager and some data about the dock states. + * + * If you've got some dockwidgets, you can dock them to the dockmainwindow to initialize a start scene: + * Here an example: + * \code + * DockApplication::DockApplication( const char* name) : KDockMainWindow( name) + * { + * ... + * KDockWidget* mainDock; + * mainDock = createDockWidget( "Falk's MainDockWidget", mainPixmap, 0L, "main_dock_widget"); + * AnyContentsWidget* cw = new AnyContentsWidget( mainDock); + * mainDock->setWidget( cw); + * // allow others to dock to the 4 sides + * mainDock->setDockSite(KDockWidget::DockCorner); + * // forbit docking abilities of mainDock itself + * mainDock->setEnableDocking(KDockWidget::DockNone); + * setView( mainDock); // central widget in a KDE mainwindow + * setMainDockWidget( mainDock); // master dockwidget + * ... + * KDockWidget* dockLeft; + * dockLeft = createDockWidget( "Intially left one", anyOtherPixmap, 0L, i18n("The left dockwidget")); + * AnotherWidget* aw = new AnotherWidget( dockLeft); + * dockLeft->setWidget( aw); + * dockLeft->manualDock( mainDock, // dock target + * KDockWidget::DockLeft, // dock site + * 20 ); // relation target/this (in percent) + * ... + * \endcode + * + * Docking is fully dynamic at runtime. That means you can always move dockwidgets via drag and drop. + * + * And last but not least you can use the popupmenu for showing or hiding any controlled dockwidget + * of this class and insert it to your main menu bar or anywhere else. + * + * @author Max Judin (documentation: Falk Brettschneider). + */ +class KDEUI_EXPORT KDockMainWindow : public KMainWindow +{ + Q_OBJECT + +friend class KDockManager; + +public: + + /** + * Constructs a dockmainwindow. It calls its base class constructor and does additional things concerning + * to the dock stuff: + * @li information about the dock state of this' children gets initialized + * @li a dockmanager is created... + * @li ...and gets initialized + * @li the main dockwidget is set to 0 + * + * @param parent Parent widget for the dock main widget + * @param name internal object name + * @param f Qt::WidgetFlags widget flags + */ + KDockMainWindow( QWidget* parent = 0L, const char *name = 0L, WFlags f = WType_TopLevel | WDestructiveClose ); + + /** + * Destructs a dockmainwindow. + */ + virtual ~KDockMainWindow(); + + /** + * Returns the dockmanager of this. (see KDockManager) + * @return pointer to the wanted dockmanager + */ + KDockManager* manager() const { return dockManager; } + + /** + * Sets a new main dockwidget. + * Additionally, the toolbar is re-initialized. + * + * @param dockwidget dockwidget that become the new main dockwidget + */ + void setMainDockWidget( KDockWidget* dockwidget); + + /** + * Returns the main dockwidget. + * + * @return pointer to the main dockwidget + */ + KDockWidget* getMainDockWidget() const { return mainDockWidget; } + + /** + * This is one of the most important methods! + * The KDockMainWindow creates a new dockwidget object here that usually should encapsulate the user's widget. + * The new dockwidget is automatically taken under control by the dockmanager of the dockmainwindow. + * + * @param name QObject name (default dockwidget caption) + * @param pixmap window icon (for instance shown when docked as tabwidget entry) + * @param parent parent widget for the new dockwidget + * @param strCaption window title (shown when toplevel) + * @param strTabPageLabel title of the tab page (visible when in tab page mode), if it is "", only the icon will be shown; if it is 0L, the label is set to strCaption + * @return a pointer to the new created dockwidget + */ + KDockWidget* createDockWidget( const QString& name, const QPixmap &pixmap, QWidget* parent = 0L, + const QString& strCaption = QString::null, const QString& strTabPageLabel = QString::fromLatin1( " " ) ); + + /** + * Saves the current dock window layout into a DOM tree below the given element. + */ + void writeDockConfig(QDomElement &base); + /** + * Reads the current dock window layout from a DOM tree below the given element. + */ + void readDockConfig(QDomElement &base); + +#ifndef NO_KDE2 + /** + * It writes the current dock state in the given section of KConfig. + * + * @param c KDE class for saving configurations + * @param group name of section to write to + */ + void writeDockConfig( KConfig* c = 0L, QString group = QString::null ); + + /** + * It reads the current dock state from the given section of KConfig. + * + * @param c KDE class for saving configurations + * @param group name of section to read from + */ + void readDockConfig ( KConfig* c = 0L, QString group = QString::null ); +#endif + + /** + * It runs through all dockwidgets which are under control of the dockmanager and calls show() for every + * encapsulated widget and show() for the dockwidget itself if it is not in tab mode. + * Additionally, if the main dockwidget is not a QDialog, it will be shown. + */ + void activateDock(){ dockManager->activate(); } + + /** + * Returns a popup menu that contains entries for all controlled dockwidgets making hiding and showing + * them possible. + * + * @return the wanted popup menu + */ + QPopupMenu* dockHideShowMenu() const { return dockManager->dockHideShowMenu(); } + + /** + * This method shows the given dockwidget. + * The clue is that it also considers the dockwidget could be a tab page + * and must set to be the activate one. + * + * @param dock the dockwidget that is to be shown + */ + void makeDockVisible( KDockWidget* dock ); + + /** + * This method hides the given dockwidget. + * + * @param dock the dockwidget that is to be shown + */ + void makeDockInvisible( KDockWidget* dock ); + + /** + * This is an overloaded member function, provided for convenience. + * It differs from the above function only in what argument(s) it accepts. + */ + void makeWidgetDockVisible( QWidget* widget ); + + /** + * This method calls the base class method. + * If the given widget inherits KDockWidget, applyToWidget(this) is called. + * + * @param widget any widget that should become the main view + */ + void setView( QWidget * widget ); + +signals: + /** + * Signals a certain dockwidget is undocked now. + */ + void dockWidgetHasUndocked(KDockWidget*); + +protected: + + /** + * A pointer to the main dockwidget (where one can manualDock() to + */ + KDockWidget* mainDockWidget; + + /** + * A pointer to the manager for the dock process + */ + KDockManager* dockManager; + +protected slots: + /** + * Called whenever one of the dockwidgets of this has been undocked. + */ + void slotDockWidgetUndocked(); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KDockMainWindowPrivate; + KDockMainWindowPrivate *d; +}; + +class KDEUI_EXPORT KDockArea : public QWidget +{ + Q_OBJECT + +friend class KDockManager; + +public: + + + KDockArea( QWidget* parent = 0L, const char *name = 0L); + + virtual ~KDockArea(); + + KDockManager* manager(){ return dockManager; } + + + void setMainDockWidget( KDockWidget* ); + KDockWidget* getMainDockWidget(){ return mainDockWidget; } + + KDockWidget* createDockWidget( const QString& name, const QPixmap &pixmap, QWidget* parent = 0L, + const QString& strCaption = QString::null, const QString& strTabPageLabel = QString::fromLatin1( " " ) ); + + void writeDockConfig(QDomElement &base); + void readDockConfig(QDomElement &base); + +#ifndef NO_KDE2 + void writeDockConfig( KConfig* c = 0L, QString group = QString::null ); + void readDockConfig ( KConfig* c = 0L, QString group = QString::null ); +#endif + + + + void activateDock(){ dockManager->activate(); } + QPopupMenu* dockHideShowMenu(){ return dockManager->dockHideShowMenu(); } + void makeDockVisible( KDockWidget* dock ); + void makeDockInvisible( KDockWidget* dock ); + void makeWidgetDockVisible( QWidget* widget ); + //void setView( QWidget* ); + +signals: + /** + * Signals a certain dockwidget is undocked now. + */ + void dockWidgetHasUndocked(KDockWidget*); + +protected: + + KDockWidget* mainDockWidget; + KDockManager* dockManager; + +protected slots: + void slotDockWidgetUndocked(); + +public: + virtual void resizeEvent(QResizeEvent *); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + class KDockMainWindowPrivate; + KDockMainWindowPrivate *d; +}; + + +#endif + + diff --git a/lib/compatibility/kmdi/qextmdi/kdockwidget_p.h b/lib/compatibility/kmdi/qextmdi/kdockwidget_p.h new file mode 100644 index 00000000..7c14394e --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kdockwidget_p.h @@ -0,0 +1,89 @@ +/* This file is part of the KDE libraries + Copyright (C) 2002,2003 Joseph Wenninger <jowenn@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 version 2 as published by the Free Software Foundation. + + 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. +*/ + +/*********************************************************************** +************************************************************************ + IMPORTANT - IMPORTANT - IMPORTANT - IMPORTANT - IMPORTANT - IMPORTANT +************************************************************************ +************************************************************************ + +THIS IS ___NOT___ PART OF THE PUBLIC API YET. DON'T USE IT IN YOUR +APPLICATIONS,SINCE IT'S MOST PROBABLY ___NOT___ GOING TO STAY BINARY +COMPATIBLE. THIS HEADER IS ONLY INSTALLED, BECAUSE IT IS NEEDED IN + KDE 3.1'S KATE APPLICATON + +************************************************************************ +************************************************************************ + IMPORTANT - IMPORTANT - IMPORTANT - IMPORTANT - IMPORTANT - IMPORTANT +************************************************************************ +***********************************************************************/ + +#ifndef KDOCKWIDGET_P_H +#define KDOCKWIDGET_P_H + +#include <kdockwidget.h> +#include <qstringlist.h> +// Add some describing comment !! + +class KDEUI_EXPORT KDockContainer +{ +public: + KDockContainer(); + virtual ~KDockContainer(); + virtual KDockWidget *parentDockWidget(); + virtual void insertWidget (KDockWidget *, QPixmap, const QString &, int &); + virtual void showWidget(KDockWidget *); + virtual void removeWidget(KDockWidget*); + virtual void undockWidget(KDockWidget*); + virtual void save(KConfig *cfg,const QString& group_or_prefix); + virtual void save(QDomElement& dockElement); + virtual void load(KConfig *cfg,const QString& group_or_prefix); + virtual void load(QDomElement& dockElement); + virtual void setToolTip (KDockWidget *, QString &); + virtual void setPixmap(KDockWidget*,const QPixmap&); + QStringList containedWidgets() const; + virtual bool dockDragEnter(KDockWidget* dockWidget, QMouseEvent *event); + virtual bool dockDragMove(KDockWidget* dockWidget, QMouseEvent *event); + virtual bool dockDragLeave(KDockWidget* dockWidget, QMouseEvent *event); +protected: + friend class KDockManager; + friend class KDockSplitter; + void prepareSave(QStringList &names); + void activateOverlapMode(int nonOverlapSize); + void deactivateOverlapMode(); + bool isOverlapMode(); +private: + + struct ListItem { + struct ListItem *prev; + struct ListItem *next; + char *data; + }; + + + + struct ListItem *m_childrenListBegin; + struct ListItem *m_childrenListEnd; + + class KDockContainerPrivate; + KDockContainerPrivate *d; + bool m_overlapMode; + int m_nonOverlapSize; +}; + +#endif diff --git a/lib/compatibility/kmdi/qextmdi/kdockwidget_private.cpp b/lib/compatibility/kmdi/qextmdi/kdockwidget_private.cpp new file mode 100644 index 00000000..3c4783f1 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kdockwidget_private.cpp @@ -0,0 +1,631 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Max Judin <novaprint@mtu-net.ru> + Copyright (C) 2002,2003 Joseph Wenninger <jowenn@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 version 2 as published by the Free Software Foundation. + + 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 "kdockwidget.h" +#include "kdockwidget_p.h" +#include "kdockwidget_private.h" + +#include <qpainter.h> +#include <qcursor.h> +#include <kdebug.h> +#include <qtimer.h> +#include <qapplication.h> + +KDockSplitter::KDockSplitter(QWidget *parent, const char *name, Orientation orient, int pos, bool highResolution) +: QWidget(parent, name) +{ + m_dontRecalc=false; + divider = 0L; + child0 = 0L; + child1 = 0L; + fixedWidth0=-1; + fixedWidth1=-1; + fixedHeight0=-1; + fixedHeight1=-1; + + m_orientation = orient; + mOpaqueResize = false; + mKeepSize = false; + mHighResolution = highResolution; + setSeparatorPos( pos, false ); + initialised = false; +} + +void KDockSplitter::activate(QWidget *c0, QWidget *c1) +{ + if ( c0 ) child0 = c0; + if ( c1 ) child1 = c1; + + setupMinMaxSize(); + + if (divider) delete divider; + divider = new QFrame(this, "pannerdivider"); + divider->setFrameStyle(QFrame::Panel | QFrame::Raised); + divider->setLineWidth(1); + divider->raise(); + + if (m_orientation == Horizontal) + divider->setCursor(QCursor(sizeVerCursor)); + else + divider->setCursor(QCursor(sizeHorCursor)); + + divider->installEventFilter(this); + + initialised= true; + + updateName(); + divider->show(); + resizeEvent(0); + if (fixedWidth0!=-1) restoreFromForcedFixedSize((KDockWidget*)child0); + if (fixedWidth1!=-1) restoreFromForcedFixedSize((KDockWidget*)child1); + if (((KDockWidget*)child0)->forcedFixedWidth()!=-1) + { + setForcedFixedWidth(((KDockWidget*)child0),((KDockWidget*)child0)->forcedFixedWidth()); + //QTimer::singleShot(100,this,SLOT(delayedResize())); + } + else + if (((KDockWidget*)child1)->forcedFixedWidth()!=-1) + { + setForcedFixedWidth(((KDockWidget*)child1),((KDockWidget*)child1)->forcedFixedWidth()); + //QTimer::singleShot(100,this,SLOT(delayedResize())); + } + + if (((KDockWidget*)child0)->forcedFixedHeight()!=-1) + { + setForcedFixedHeight(((KDockWidget*)child0),((KDockWidget*)child0)->forcedFixedHeight()); + //QTimer::singleShot(100,this,SLOT(delayedResize())); + } + else + if (((KDockWidget*)child1)->forcedFixedHeight()!=-1) + { + setForcedFixedHeight(((KDockWidget*)child1),((KDockWidget*)child1)->forcedFixedHeight()); + //QTimer::singleShot(100,this,SLOT(delayedResize())); + } + + +} + +/* +void KDockSplitter::delayedResize() +{ + kdDebug(282)<<"*********************** DELAYED RESIZE !!!!!!!!!!!!!!!"<<endl; + resizeEvent(0); +}*/ + +void KDockSplitter::setForcedFixedWidth(KDockWidget *dw,int w) +{ + int factor = (mHighResolution)? 10000:100; + if (dw==child0) + { + if (fixedWidth0==-1) savedXPos=xpos; + if (w==fixedWidth0) return; + fixedWidth0=w; + setSeparatorPos(w*factor/width(),true); + +// setupMinMaxSize(); +// kdDebug(282)<<"Set forced fixed width for widget 0 :"<<w<<endl; + } + else + { + if (fixedWidth1==-1) savedXPos=xpos; + if (w==fixedWidth1) return; + fixedWidth1=w; + setSeparatorPos((width()-w)*factor/width(),true); +// kdDebug(282)<<"Set forced fixed width for widget 1 :"<<w<<endl; +// kdDebug(282)<<"Width() :"<<width()<<endl; + } + divider->hide(); + setupMinMaxSize(); +} + +void KDockSplitter::setForcedFixedHeight(KDockWidget *dw,int h) +{ + int factor = (mHighResolution)? 10000:100; + if (dw==child0) + { + if (fixedHeight0==-1) savedXPos=xpos; + if (h==fixedHeight0) return; + fixedHeight0=h; +// setupMinMaxSize(); + setSeparatorPos(h*factor/height(),true); +// kdDebug(282)<<"Set forced fixed width for widget 0 :"<<h<<endl; + } + else + { + if (fixedHeight1==-1) savedXPos=xpos; + if (h==fixedHeight1) return; + fixedHeight1=h; + setSeparatorPos((height()-h)*factor/height(),true); +// kdDebug(282)<<"Set forced fixed height for widget 1 :"<<h<<endl; + } + divider->hide(); + setupMinMaxSize(); +} + +void KDockSplitter::restoreFromForcedFixedSize(KDockWidget *dw) +{ + if (dw==child0) + { + fixedWidth0=-1; + fixedHeight0=-1; + setSeparatorPos(savedXPos,true); + } + else + { + fixedWidth1=-1; + fixedHeight1=-1; + setSeparatorPos(savedXPos,true); + } + divider->show(); +} + + +void KDockSplitter::setupMinMaxSize() +{ + // Set the minimum and maximum sizes + int minx, maxx, miny, maxy; + if (m_orientation == Horizontal) { + miny = child0->minimumSize().height() + child1->minimumSize().height()+4; + maxy = child0->maximumSize().height() + child1->maximumSize().height()+4; + minx = (child0->minimumSize().width() > child1->minimumSize().width()) ? child0->minimumSize().width() : child1->minimumSize().width(); + maxx = (child0->maximumSize().width() > child1->maximumSize().width()) ? child0->maximumSize().width() : child1->maximumSize().width(); + + miny = (miny > 4) ? miny : 4; + maxy = (maxy < 32000) ? maxy : 32000; + minx = (minx > 2) ? minx : 2; + maxx = (maxx < 32000) ? maxx : 32000; + } else { + minx = child0->minimumSize().width() + child1->minimumSize().width()+4; + maxx = child0->maximumSize().width() + child1->maximumSize().width()+4; + miny = (child0->minimumSize().height() > child1->minimumSize().height()) ? child0->minimumSize().height() : child1->minimumSize().height(); + maxy = (child0->maximumSize().height() > child1->maximumSize().height()) ? child0->maximumSize().height() : child1->maximumSize().height(); + + minx = (minx > 4) ? minx : 4; + maxx = (maxx < 32000) ? maxx : 32000; + miny = (miny > 2) ? miny : 2; + maxy = (maxy < 32000) ? maxy : 32000; + + } + setMinimumSize(minx, miny); + setMaximumSize(maxx, maxy); +} + +void KDockSplitter::deactivate() +{ + delete divider; + divider = 0L; + initialised= false; +} + +void KDockSplitter::setSeparatorPos(int pos, bool do_resize) +{ + xpos = pos; + if (do_resize) + resizeEvent(0); +} + +void KDockSplitter::setSeparatorPosX( int pos, bool do_resize ) +{ + savedXPos = pos; + setSeparatorPos( pos, do_resize ); +} + +int KDockSplitter::separatorPos() const +{ + return xpos; +} + +void KDockSplitter::resizeEvent(QResizeEvent *ev) +{ +// kdDebug(282)<<"ResizeEvent :"<< ((initialised) ? "initialised":"not initialised")<<", "<< ((ev) ? "real event":"")<< +// ", "<<(isVisible() ?"visible":"")<<endl; + if (initialised){ + double factor = (mHighResolution)? 10000.0:100.0; + // real resize event, recalculate xpos + if (ev && mKeepSize && isVisible()) { +// kdDebug(282)<<"mKeepSize : "<< ((m_orientation == Horizontal) ? "Horizontal":"Vertical") <<endl; + + if (ev->oldSize().width() != ev->size().width()) + { + if (m_orientation == Horizontal) { + xpos = qRound(factor * checkValue( child0->height()+1 ) / height()); + } else { + xpos = qRound(factor * checkValue( child0->width()+1 ) / width()); + } + + } + } + else + { +// kdDebug(282)<<"!mKeepSize : "<< ((m_orientation == Horizontal) ? "Horizontal":"Vertical") <<endl; + if (/*ev &&*/ isVisible()) { + if (m_orientation == Horizontal) { + /* if (ev->oldSize().height() != ev->size().height())*/ + { + if (fixedHeight0!=-1) +// xpos=floor(fixedHeight0*factor/height()); + xpos=qRound(fixedHeight0*factor/height()); + else + if (fixedHeight1!=-1) +// xpos=ceil((height()-fixedHeight1)*factor/height()); + xpos=qRound((height()-fixedHeight1)*factor/height()); + } + } + else + { +/* if (ev->oldSize().width() != ev->size().width()) */ + { + if (fixedWidth0!=-1) +// xpos=floor(fixedWidth0*factor/width()); + xpos=qRound(fixedWidth0*factor/width()); + else + if (fixedWidth1!=-1) +// xpos=ceil((width()-fixedWidth1)*factor/width()); + xpos=qRound((width()-fixedWidth1)*factor/width()); + } + } + } +// else kdDebug(282)<<"Something else happened"<<endl; + } + + KDockContainer *dc; + KDockWidget *c0=(KDockWidget*)child0; + KDockWidget *c1=(KDockWidget*)child1; + bool stdHandling=false; + if ( ( (m_orientation==Vertical) &&((fixedWidth0==-1) && (fixedWidth1==-1)) ) || + ( (m_orientation==Horizontal) &&((fixedHeight0==-1) && (fixedHeight1==-1)) ) ) { + if ((c0->getWidget()) && (dc=dynamic_cast<KDockContainer*>(c0->getWidget())) + && (dc->m_overlapMode)) { + int position= qRound((m_orientation == Vertical ? width() : height()) * xpos/factor); + position=checkValueOverlapped(position,child0); + child0->raise(); + divider->raise(); + if (m_orientation == Horizontal){ + child0->setGeometry(0, 0, width(), position); + child1->setGeometry(0, dc->m_nonOverlapSize+4, width(), + height()-dc->m_nonOverlapSize-4); + divider->setGeometry(0, position, width(), 4); + } else { + child0->setGeometry(0, 0, position, height()); + child1->setGeometry(dc->m_nonOverlapSize+4, 0, + width()-dc->m_nonOverlapSize-4, height()); + divider->setGeometry(position, 0, 4, height()); + } + } else { + if ((c1->getWidget()) && (dc=dynamic_cast<KDockContainer*>(c1->getWidget())) + && (dc->m_overlapMode)) { + int position= qRound((m_orientation == Vertical ? width() : height()) * xpos/factor); + position=checkValueOverlapped(position,child1); + child1->raise(); + divider->raise(); + if (m_orientation == Horizontal){ + child0->setGeometry(0, 0, width(), height()-dc->m_nonOverlapSize-4); + child1->setGeometry(0, position+4, width(), + height()-position-4); + divider->setGeometry(0, position, width(), 4); + } else { + child0->setGeometry(0, 0, width()-dc->m_nonOverlapSize-4, height()); + child1->setGeometry(position+4, 0, + width()-position-4, height()); + divider->setGeometry(position, 0, 4, height()); + } + } + else stdHandling=true; + } + } + else stdHandling=true; + + if (stdHandling) { + int position = checkValue( qRound((m_orientation == Vertical ? width() : height()) * xpos/factor) ); + if (m_orientation == Horizontal){ + child0->setGeometry(0, 0, width(), position); + child1->setGeometry(0, position+4, width(), height()-position-4); + divider->setGeometry(0, position, width(), 4); + } else { + child0->setGeometry(0, 0, position, height()); + child1->setGeometry(position+4, 0, width()-position-4, height()); + divider->setGeometry(position, 0, 4, height()); + } + + } + + } +} + +int KDockSplitter::checkValueOverlapped(int position, QWidget *overlappingWidget) const { + if (initialised) { + if (m_orientation == Vertical) { + if (child0==overlappingWidget) { + if (position<(child0->minimumSize().width())) + position=child0->minimumSize().width(); + if (position>width()) position=width()-4; + } else if (position>(width()-(child1->minimumSize().width())-4)){ + position=width()-(child1->minimumSize().width())-4; + if (position<0) position=0; + } + } else {// orientation == Horizontal + if (child0==overlappingWidget) { + if (position<(child0->minimumSize().height())) + position=child0->minimumSize().height(); + if (position>height()) position=height()-4; + } else if (position>(height()-(child1->minimumSize().height())-4)){ + position=height()-(child1->minimumSize().height())-4; + if (position<0) position=0; + + } + } + + } + return position; +} + +int KDockSplitter::checkValue( int position ) const +{ + if (initialised){ + if (m_orientation == Vertical){ + if (position < (child0->minimumSize().width())) + position = child0->minimumSize().width(); + if ((width()-4-position) < (child1->minimumSize().width())) + position = width() - (child1->minimumSize().width()) -4; + } else { + if (position < (child0->minimumSize().height())) + position = (child0->minimumSize().height()); + if ((height()-4-position) < (child1->minimumSize().height())) + position = height() - (child1->minimumSize().height()) -4; + } + } + + if (position < 0) position = 0; + + if ((m_orientation == Vertical) && (position > width())) + position = width(); + if ((m_orientation == Horizontal) && (position > height())) + position = height(); + + return position; +} + +bool KDockSplitter::eventFilter(QObject *o, QEvent *e) +{ + QMouseEvent *mev; + bool handled = false; + int factor = (mHighResolution)? 10000:100; + + switch (e->type()) { + case QEvent::MouseMove: + mev= (QMouseEvent*)e; + child0->setUpdatesEnabled(mOpaqueResize); + child1->setUpdatesEnabled(mOpaqueResize); + if (m_orientation == Horizontal) { + if ((fixedHeight0!=-1) || (fixedHeight1!=-1)) + { + handled=true; break; + } + + if (!mOpaqueResize) { + int position = checkValue( mapFromGlobal(mev->globalPos()).y() ); + divider->move( 0, position ); + } else { + xpos = factor * checkValue( mapFromGlobal(mev->globalPos()).y() ) / height(); + resizeEvent(0); + divider->repaint(true); + } + } else { + if ((fixedWidth0!=-1) || (fixedWidth1!=-1)) + { + handled=true; break; + } + if (!mOpaqueResize) { + int position = checkValue( mapFromGlobal(QCursor::pos()).x() ); + divider->move( position, 0 ); + } else { + xpos = factor * checkValue( mapFromGlobal( mev->globalPos()).x() ) / width(); + resizeEvent(0); + divider->repaint(true); + } + } + handled= true; + break; + case QEvent::MouseButtonRelease: + child0->setUpdatesEnabled(true); + child1->setUpdatesEnabled(true); + mev= (QMouseEvent*)e; + if (m_orientation == Horizontal){ + if ((fixedHeight0!=-1) || (fixedHeight1!=-1)) + { + handled=true; break; + } + xpos = factor* checkValue( mapFromGlobal(mev->globalPos()).y() ) / height(); + resizeEvent(0); + divider->repaint(true); + } else { + if ((fixedWidth0!=-1) || (fixedWidth1!=-1)) + { + handled=true; break; + } + xpos = factor* checkValue( mapFromGlobal(mev->globalPos()).x() ) / width(); + resizeEvent(0); + divider->repaint(true); + } + handled= true; + break; + default: + break; + } + return (handled) ? true : QWidget::eventFilter( o, e ); +} + +bool KDockSplitter::event( QEvent* e ) +{ + if ( e->type() == QEvent::LayoutHint ){ + // change children min/max size + setupMinMaxSize(); + setSeparatorPos(xpos); + } + return QWidget::event(e); +} + +QWidget* KDockSplitter::getAnother( QWidget* w ) const +{ + return ( w == child0 ) ? child1 : child0; +} + +void KDockSplitter::updateName() +{ + if ( !initialised ) return; + + QString new_name = QString( child0->name() ) + "," + child1->name(); + parentWidget()->setName( new_name.latin1() ); + parentWidget()->setCaption( child0->caption() + "," + child1->caption() ); + parentWidget()->repaint( false ); + + ((KDockWidget*)parentWidget())->firstName = child0->name(); + ((KDockWidget*)parentWidget())->lastName = child1->name(); + ((KDockWidget*)parentWidget())->splitterOrientation = m_orientation; + + QWidget* p = parentWidget()->parentWidget(); + if ( p && p->inherits("KDockSplitter" ) ) + ((KDockSplitter*)p)->updateName(); +} + +void KDockSplitter::setOpaqueResize(bool b) +{ + mOpaqueResize = b; +} + +bool KDockSplitter::opaqueResize() const +{ + return mOpaqueResize; +} + +void KDockSplitter::setKeepSize(bool b) +{ + mKeepSize = b; +} + +bool KDockSplitter::keepSize() const +{ + return mKeepSize; +} + +void KDockSplitter::setHighResolution(bool b) +{ + if (mHighResolution) { + if (!b) xpos = xpos/100; + } else { + if (b) xpos = xpos*100; + } + mHighResolution = b; +} + +bool KDockSplitter::highResolution() const +{ + return mHighResolution; +} + + +/*************************************************************************/ +KDockButton_Private::KDockButton_Private( QWidget *parent, const char * name ) +:QPushButton( parent, name ) +{ + moveMouse = false; + setFocusPolicy( NoFocus ); +} + +KDockButton_Private::~KDockButton_Private() +{ +} + +void KDockButton_Private::drawButton( QPainter* p ) +{ + p->fillRect( 0,0, width(), height(), QBrush(colorGroup().brush(QColorGroup::Background)) ); + p->drawPixmap( (width() - pixmap()->width()) / 2, (height() - pixmap()->height()) / 2, *pixmap() ); + if ( moveMouse && !isDown() ){ + p->setPen( white ); + p->moveTo( 0, height() - 1 ); + p->lineTo( 0, 0 ); + p->lineTo( width() - 1, 0 ); + + p->setPen( colorGroup().dark() ); + p->lineTo( width() - 1, height() - 1 ); + p->lineTo( 0, height() - 1 ); + } + if ( isOn() || isDown() ){ + p->setPen( colorGroup().dark() ); + p->moveTo( 0, height() - 1 ); + p->lineTo( 0, 0 ); + p->lineTo( width() - 1, 0 ); + + p->setPen( white ); + p->lineTo( width() - 1, height() - 1 ); + p->lineTo( 0, height() - 1 ); + } +} + +void KDockButton_Private::enterEvent( QEvent * ) +{ + moveMouse = true; + repaint(); +} + +void KDockButton_Private::leaveEvent( QEvent * ) +{ + moveMouse = false; + repaint(); +} + +/*************************************************************************/ +KDockWidgetPrivate::KDockWidgetPrivate() + : QObject() + ,index(-1) + ,splitPosInPercent(50) + ,pendingFocusInEvent(false) + ,blockHasUndockedSignal(false) + ,pendingDtor(false) + ,forcedWidth(-1) + ,forcedHeight(-1) + ,isContainer(false) + ,container(0) + ,resizePos(0,0) + ,resizing(false) +{ +#ifndef NO_KDE2 + windowType = NET::Normal; +#endif + + _parent = 0L; + transient = false; +} + +KDockWidgetPrivate::~KDockWidgetPrivate() +{ +} + +void KDockWidgetPrivate::slotFocusEmbeddedWidget(QWidget* w) +{ + if (w) { + QWidget* embeddedWdg = ((KDockWidget*)w)->getWidget(); + if (embeddedWdg && ((embeddedWdg->focusPolicy() == QWidget::ClickFocus) || (embeddedWdg->focusPolicy() == QWidget::StrongFocus))) { + embeddedWdg->setFocus(); + } + } +} + +#ifndef NO_INCLUDE_MOCFILES // for Qt-only projects, because tmake doesn't take this name +#include "kdockwidget_private.moc" +#endif diff --git a/lib/compatibility/kmdi/qextmdi/kdockwidget_private.h b/lib/compatibility/kmdi/qextmdi/kdockwidget_private.h new file mode 100644 index 00000000..0857bd7a --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kdockwidget_private.h @@ -0,0 +1,204 @@ +/* This file is part of the KDE libraries + Copyright (C) 2000 Max Judin <novaprint@mtu-net.ru> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + 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. +*/ + +/* + IMPORTANT Note: This file compiles also in Qt-only mode by using the NO_KDE2 precompiler definition +*/ + +#ifndef KDOCKWIDGET_PRIVATE_H +#define KDOCKWIDGET_PRIVATE_H + +#include <qwidget.h> +#include <qpushbutton.h> + +#ifndef NO_KDE2 +#include <netwm_def.h> +#endif + +class QFrame; +class KDockContainer; + + +/** + * Like QSplitter but specially designed for dockwidgets stuff. + * @internal + * + * @author Max Judin. +*/ +class KDEUI_EXPORT KDockSplitter : public QWidget +{ + Q_OBJECT +public: + KDockSplitter(QWidget *parent= 0, const char *name= 0, Orientation orient= Vertical, int pos= 50, bool highResolution=false); + virtual ~KDockSplitter(){}; + + void activate(QWidget *c0, QWidget *c1 = 0L); + void deactivate(); + + int separatorPos() const; + void setSeparatorPos(int pos, bool do_resize = true); + /** + * For usage from outside. + * If the splitter is in fixed position when called, + * the value of @p pos will be saved and used when the splitter + * is restored. + * If @p do_resize is true, the size will be changed unless the splitter + * is in fixed mode. + */ + // ### please come up with a nicer name + void setSeparatorPosX(int pos, bool do_resize=false); + + virtual bool eventFilter(QObject *, QEvent *); + virtual bool event( QEvent * ); + + QWidget* getFirst() const { return child0; } + QWidget* getLast() const { return child1; } + QWidget* getAnother( QWidget* ) const; + void updateName(); + + void setOpaqueResize(bool b=true); + bool opaqueResize() const; + + void setKeepSize(bool b=true); + bool keepSize() const; + + void setHighResolution(bool b=true); + bool highResolution() const; + + void setForcedFixedWidth(KDockWidget *dw,int w); + void setForcedFixedHeight(KDockWidget *dw,int h); + void restoreFromForcedFixedSize(KDockWidget *dw); + + Orientation orientation(){return m_orientation;} + +protected: + friend class KDockContainer; + int checkValue( int ) const; + int checkValueOverlapped( int ,QWidget*) const; + virtual void resizeEvent(QResizeEvent *); +/* +protected slots: + void delayedResize();*/ + +private: + void setupMinMaxSize(); + QWidget *child0, *child1; + Orientation m_orientation; + bool initialised; + QFrame* divider; + int xpos, savedXPos; + bool mOpaqueResize, mKeepSize, mHighResolution; + int fixedWidth0,fixedWidth1; + int fixedHeight0,fixedHeight1; + bool m_dontRecalc; +}; + +/** + * A mini-button usually placed in the dockpanel. + * @internal + * + * @author Max Judin. +*/ +class KDEUI_EXPORT KDockButton_Private : public QPushButton +{ + Q_OBJECT +public: + KDockButton_Private( QWidget *parent=0, const char *name=0 ); + ~KDockButton_Private(); + +protected: + virtual void drawButton( QPainter * ); + virtual void enterEvent( QEvent * ); + virtual void leaveEvent( QEvent * ); + +private: + bool moveMouse; +}; + +/** + * resizing enum + **/ + + + +/** + * additional KDockWidget stuff (private) +*/ +class KDEUI_EXPORT KDockWidgetPrivate : public QObject +{ + Q_OBJECT +public: + KDockWidgetPrivate(); + ~KDockWidgetPrivate(); + +public slots: + /** + * Especially used for Tab page docking. Switching the pages requires additional setFocus() for the embedded widget. + */ + void slotFocusEmbeddedWidget(QWidget* w = 0L); + +public: + enum KDockWidgetResize +{ResizeLeft,ResizeTop,ResizeRight,ResizeBottom,ResizeBottomLeft,ResizeTopLeft,ResizeBottomRight,ResizeTopRight}; + + int index; + int splitPosInPercent; + bool pendingFocusInEvent; + bool blockHasUndockedSignal; + bool pendingDtor; + int forcedWidth; + int forcedHeight; + bool isContainer; + +#ifndef NO_KDE2 + NET::WindowType windowType; +#endif + + QWidget *_parent; + bool transient; + + QGuardedPtr<QWidget> container; + + QPoint resizePos; + bool resizing; + KDockWidgetResize resizeMode; +}; + +class KDEUI_EXPORT KDockWidgetHeaderPrivate + : public QObject +{ +public: + KDockWidgetHeaderPrivate( QObject* parent ) + : QObject( parent ) + { + forceCloseButtonHidden=false; + toDesktopButton = 0; + showToDesktopButton = true; + topLevel = false; + dummy=0; + } + KDockButton_Private* toDesktopButton; + + bool showToDesktopButton; + bool topLevel; + QPtrList<KDockButton_Private> btns; + bool forceCloseButtonHidden; + QWidget *dummy; +}; + +#endif diff --git a/lib/compatibility/kmdi/qextmdi/kmdichildarea.cpp b/lib/compatibility/kmdi/qextmdi/kmdichildarea.cpp new file mode 100644 index 00000000..8074dac4 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmdichildarea.cpp @@ -0,0 +1,789 @@ +//---------------------------------------------------------------------------- +// filename : kmdichildarea.cpp +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 07/1999 by Szymon Stefanek as part of kvirc +// (an IRC application) +// changes : 09/1999 by Falk Brettschneider to create an +// - 06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// 2000-2003 maintained by the KDevelop project +// +// copyright : (C) 1999-2003 by Szymon Stefanek (stefanek@tin.it) +// and +// Falk Brettschneider +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program 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. +// +//---------------------------------------------------------------------------- + +#include "kmdichildarea.h" +#include "kmdichildarea.moc" + +#include "kmdidefines.h" + +#include <kconfig.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kglobalsettings.h> + +#include <math.h> +#include <qpopupmenu.h> + + +/////////////////////////////////////////////////////////////////////////////// +// KMdiChildArea +/////////////////////////////////////////////////////////////////////////////// + +//============ KMdiChildArea ============// + +KMdiChildArea::KMdiChildArea( QWidget *parent ) + : QFrame( parent, "kmdi_childarea" ) +{ + setFrameStyle( QFrame::Panel | QFrame::Sunken ); + m_captionFont = QFont(); + QFontMetrics fm( m_captionFont ); + m_captionFontLineSpacing = fm.lineSpacing(); + m_captionActiveBackColor = KGlobalSettings::activeTitleColor(); + m_captionActiveForeColor = KGlobalSettings::activeTextColor(); + m_captionInactiveBackColor = KGlobalSettings::inactiveTitleColor(); + m_captionInactiveForeColor = KGlobalSettings::inactiveTextColor(); + m_pZ = new QPtrList<KMdiChildFrm>; + m_pZ->setAutoDelete( true ); + setFocusPolicy( ClickFocus ); + m_defaultChildFrmSize = QSize( 400, 300 ); +} + + +KMdiChildArea::~KMdiChildArea() +{ + delete m_pZ; //This will destroy all the widgets inside. +} + + +void KMdiChildArea::manageChild( KMdiChildFrm* child, bool show, bool cascade ) +{ + kdDebug( 760 ) << k_funcinfo << "Adding child " << child << " to be managed" << endl; + KMdiChildFrm* top = topChild(); + + //remove old references. There can be more than one so we remove them all + if ( m_pZ->findRef( child ) != -1 ) + { + //QPtrList::find* moves current() to the found item + m_pZ->take(); + while ( m_pZ->findNextRef( child ) != -1 ) + m_pZ->take(); + } + + if ( show ) + m_pZ->append( child ); //visible -> first in the Z order + else + m_pZ->insert( 0, child ); //hidden -> last in the Z order + + if ( cascade ) + child->move( getCascadePoint( m_pZ->count() - 1 ) ); + + if ( show ) + { + if ( top && top->state() == KMdiChildFrm::Maximized ) + { + kdDebug( 760 ) << k_funcinfo << "Maximizing the new child" << endl; + emit sysButtonConnectionsMustChange( top, child ); + top->setState( KMdiChildFrm::Normal, false /*animate*/ ); + child->setState( KMdiChildFrm::Maximized, false /*animate*/ ); + } + child->show(); + focusTopChild(); + } +} + + +void KMdiChildArea::destroyChild( KMdiChildFrm *child, bool focusTop ) +{ + kdDebug( 760 ) << k_funcinfo << "Removing child " << child->caption() << endl; + bool wasMaximized = ( child->state() == KMdiChildFrm::Maximized ); + + // destroy the old one + QObject::disconnect( child ); + child->blockSignals( true ); + m_pZ->setAutoDelete( false ); + m_pZ->removeRef( child ); + + // focus the next new childframe + KMdiChildFrm* newTopChild = topChild(); + if ( wasMaximized ) + { + if ( newTopChild ) + { + newTopChild->setState( KMdiChildFrm::Maximized, false ); + emit sysButtonConnectionsMustChange( child, newTopChild ); + } + else + emit noMaximizedChildFrmLeft( child ); // last childframe removed + } + + delete child; + m_pZ->setAutoDelete( true ); + + if ( focusTop ) + focusTopChild(); +} + + +void KMdiChildArea::destroyChildButNotItsView( KMdiChildFrm* child, bool focusTop ) +{ + kdDebug( 760 ) << k_funcinfo << "Removing child " << child->caption() << endl; + bool wasMaximized = ( child->state() == KMdiChildFrm::Maximized ); + + // destroy the old one + QObject::disconnect( child ); + child->unsetClient(); + m_pZ->setAutoDelete( false ); + m_pZ->removeRef( child ); + + // focus the next new childframe + KMdiChildFrm* newTopChild = topChild(); + if ( wasMaximized ) + { + if ( newTopChild ) + { + newTopChild->setState( KMdiChildFrm::Maximized, false ); + emit sysButtonConnectionsMustChange( child, newTopChild ); + } + else + emit noMaximizedChildFrmLeft( child ); // last childframe removed + } + delete child; + m_pZ->setAutoDelete( true ); + + if ( focusTop ) + focusTopChild(); +} + +void KMdiChildArea::setTopChild( KMdiChildFrm* child, bool /* bSetFocus */ ) +{ + if ( !child ) + return; + + if ( topChild() != child ) + { + kdDebug( 760 ) << k_funcinfo << "Setting " << child->caption() << " as the new top child" << endl; + m_pZ->setAutoDelete( false ); + if ( child ) + m_pZ->removeRef( child ); + m_pZ->setAutoDelete( true ); + + //disable the labels of all the other children + QPtrListIterator<KMdiChildFrm> it( *m_pZ ); + for ( ; ( *it ); ++it ) + ( *it )->m_pCaption->setActive( false ); + + KMdiChildFrm* maximizedChild = topChild(); + bool topChildMaximized = false; + if ( maximizedChild && maximizedChild->state() == KMdiChildFrm::Maximized ) + topChildMaximized = true; + + m_pZ->append( child ); + + int nChildAreaMinW = 0, nChildAreaMinH = 0; + int nChildAreaMaxW = QWIDGETSIZE_MAX, nChildAreaMaxH = QWIDGETSIZE_MAX; + if ( topChildMaximized && child->m_pClient ) + { + //the former top child is maximized, so maximize the new one + nChildAreaMinW = child->m_pClient->minimumWidth(); + nChildAreaMinH = child->m_pClient->minimumHeight(); + /// @todo: setting the maximum size doesn't work properly - fix this later + // nChildAreaMaxW = child->m_pClient->maximumWidth(); + // nChildAreaMaxH = child->m_pClient->maximumHeight(); + } + + //set the min and max sizes of this child area to the new top child + setMinimumSize( nChildAreaMinW, nChildAreaMinH ); + setMaximumSize( nChildAreaMaxW, nChildAreaMaxH ); + + if ( topChildMaximized ) + { //maximize the new view and restore the old + child->setState( KMdiChildFrm::Maximized, false /*animate*/); + maximizedChild->setState( KMdiChildFrm::Normal, false /*animate*/ ); + emit sysButtonConnectionsMustChange( maximizedChild, child ); + } + else + child->raise(); + + QFocusEvent::setReason( QFocusEvent::Other ); + child->m_pClient->setFocus(); + } +} + + +void KMdiChildArea::resizeEvent( QResizeEvent* e ) +{ + //If we have a maximized children at the top , adjust its size + KMdiChildFrm* child = topChild(); + if ( child && child->state() == KMdiChildFrm::Maximized ) + { + int clientw = 0, clienth = 0; + if ( child->m_pClient != 0L ) + { + clientw = child->m_pClient->width(); + clienth = child->m_pClient->height(); + } + child->resize( width() + KMDI_CHILDFRM_DOUBLE_BORDER, + height() + child->m_pCaption->heightHint() + KMDI_CHILDFRM_SEPARATOR + KMDI_CHILDFRM_DOUBLE_BORDER ); + + } + layoutMinimizedChildren(); + QWidget::resizeEvent( e ); +} + +//=============== mousePressEvent =============// + +void KMdiChildArea::mousePressEvent( QMouseEvent *e ) +{ + //Popup the window menu + if ( e->button() & RightButton ) + emit popupWindowMenu( mapToGlobal( e->pos() ) ); +} + +//=============== getCascadePoint ============// + +QPoint KMdiChildArea::getCascadePoint( int indexOfWindow ) +{ + if ( indexOfWindow < 0 ) + { + indexOfWindow = m_pZ->count(); //use the window count + kdDebug( 760 ) << k_funcinfo << "indexOfWindow was less than zero, using " + << indexOfWindow << " as new index" << endl; + } + + QPoint pnt( 0, 0 ); + if ( indexOfWindow == 0 ) + { + kdDebug( 760 ) << k_funcinfo << "No windows. Returning QPoint( 0, 0 ) as the cascade point" << endl; + return pnt; + } + + bool topLevelMode = false; + if ( height() == 1 ) // hacky?! + topLevelMode = true; + + kdDebug( 760 ) << k_funcinfo << "Getting the cascade point for window index " << indexOfWindow << endl; + kdDebug( 760 ) << k_funcinfo << "Do we think we're in top level mode? " << topLevelMode << endl; + + KMdiChildFrm* child = m_pZ->first(); + + //default values + int step = 20; + int h = ( topLevelMode ? QApplication::desktop()->height() : height() ); + int w = ( topLevelMode ? QApplication::desktop()->width() : width() ); + + int availableHeight = h - m_defaultChildFrmSize.height(); + int availableWidth = w - m_defaultChildFrmSize.width(); + int ax = 0; + int ay = 0; + + if ( child ) + { + kdDebug( 760 ) << k_funcinfo << "child frame exists. resetting height and width values" << endl; + step = child->m_pCaption->heightHint() + KMDI_CHILDFRM_BORDER; + availableHeight = h - child->minimumHeight(); + availableWidth = w - child->minimumWidth(); + } + + for ( int i = 0; i < indexOfWindow; i++ ) + { + ax += step; + ay += step; + + //do some bounds checking, because to not do it would be bad. + if ( ax > availableWidth ) + ax = 0; + + if ( ay > availableHeight ) + ay = 0; + } + pnt.setX( ax ); + pnt.setY( ay ); + return pnt; +} + + +void KMdiChildArea::childMinimized( KMdiChildFrm *minimizedChild, bool wasMaximized ) +{ + //can't find the child in our list, so we don't care. + if ( m_pZ->findRef( minimizedChild ) == -1 ) + { + kdDebug( 760 ) << k_funcinfo << "child was minimized but wasn't in our list!" << endl; + return; + } + + kdDebug( 760 ) << k_funcinfo << endl; + if ( m_pZ->count() > 1 ) + { + //move the minimized child to the bottom + m_pZ->setAutoDelete( false ); + m_pZ->removeRef( minimizedChild ); + m_pZ->setAutoDelete( true ); + m_pZ->insert( 0, minimizedChild ); + + if ( wasMaximized ) + { // Need to maximize the new top child + kdDebug( 760 ) << k_funcinfo << "child just minimized from maximized state. maximize new top child" << endl; + minimizedChild = topChild(); + if ( !minimizedChild ) + return; //?? + + if ( minimizedChild->state() == KMdiChildFrm::Maximized ) + return; //it's already maximized + + minimizedChild->setState( KMdiChildFrm::Maximized, false ); //do not animate the change + } + focusTopChild(); + } + else + setFocus(); //Remove focus from the child. We only have one window +} + +void KMdiChildArea::focusTopChild() +{ + KMdiChildFrm* lastChild = topChild(); + if ( !lastChild ) + { + kdDebug( 760 ) << k_funcinfo << "No more child windows left" << endl; + emit lastChildFrmClosed(); + return; + } + + if ( !lastChild->m_pClient->hasFocus() ) + { + //disable the labels of all the other children + QPtrListIterator<KMdiChildFrm> it ( *m_pZ ); + for ( ; ( *it ); ++it ) + { + if ( ( *it ) != lastChild ) + ( *it )->m_pCaption->setActive( false ); + } + + kdDebug( 760 ) << k_funcinfo << "Giving focus to " << lastChild->caption() << endl; + lastChild->raise(); + lastChild->m_pClient->activate(); + } + +} + +void KMdiChildArea::cascadeWindows() +{ + kdDebug( 760 ) << k_funcinfo << "cascading windows but not changing their size" << endl; + int idx = 0; + QPtrList<KMdiChildFrm> list( *m_pZ ); + list.setAutoDelete( false ); + while ( !list.isEmpty() ) + { + KMdiChildFrm* childFrm = list.first(); + if ( childFrm->state() != KMdiChildFrm::Minimized ) + { + if ( childFrm->state() == KMdiChildFrm::Maximized ) + childFrm->restorePressed(); + + childFrm->move( getCascadePoint( idx ) ); + idx++; + } + list.removeFirst(); + } + focusTopChild(); +} + +void KMdiChildArea::cascadeMaximized() +{ + kdDebug( 760 ) << k_funcinfo << "cascading windows. will make sure they are minimum sized" << endl; + int idx = 0; + QPtrList<KMdiChildFrm> list( *m_pZ ); + + list.setAutoDelete( false ); + while ( !list.isEmpty() ) + { + KMdiChildFrm* childFrm = list.first(); + if (childFrm->state() != KMdiChildFrm::Minimized ) + { + if (childFrm->state() == KMdiChildFrm::Maximized ) + childFrm->restorePressed(); + + QPoint pnt( getCascadePoint( idx ) ); + childFrm->move( pnt ); + QSize curSize( width() - pnt.x(), height() - pnt.y() ); + + if ( ( childFrm->minimumSize().width() > curSize.width() ) || + ( childFrm->minimumSize().height() > curSize.height() ) ) + { + childFrm->resize( childFrm->minimumSize() ); + } + else + childFrm->resize( curSize ); + + idx++; + } + list.removeFirst(); + } + focusTopChild(); +} + +void KMdiChildArea::expandVertical() +{ + kdDebug( 760 ) << k_funcinfo << "expanding all child frames vertically" << endl; + int idx = 0; + QPtrList<KMdiChildFrm> list( *m_pZ ); + list.setAutoDelete( false ); + while ( !list.isEmpty() ) + { + KMdiChildFrm* childFrm = list.first(); + if ( childFrm->state() != KMdiChildFrm::Minimized ) + { + if ( childFrm->state() == KMdiChildFrm::Maximized ) + childFrm->restorePressed(); + + childFrm->setGeometry( childFrm->x(), 0, childFrm->width(), height() ); + idx++; + } + list.removeFirst(); + } + focusTopChild(); +} + +void KMdiChildArea::expandHorizontal() +{ + kdDebug( 760 ) << k_funcinfo << "expanding all child frames horizontally" << endl; + int idx = 0; + QPtrList<KMdiChildFrm> list( *m_pZ ); + list.setAutoDelete( false ); + while ( !list.isEmpty() ) + { + KMdiChildFrm* childFrm = list.first(); + if ( childFrm->state() != KMdiChildFrm::Minimized ) + { + if ( childFrm->state() == KMdiChildFrm::Maximized ) + childFrm->restorePressed(); + + childFrm->setGeometry( 0, childFrm->y(), width(), childFrm->height() ); + idx++; + } + list.removeFirst(); + } + focusTopChild(); +} + +int KMdiChildArea::getVisibleChildCount() const +{ + int visibleChildCount = 0; + QPtrListIterator<KMdiChildFrm> it( *m_pZ ); + for ( ; ( *it ); ++it ) + { + if ( ( *it )->state() != KMdiChildFrm::Minimized && ( *it )->isVisible() ) + visibleChildCount++; + } + return visibleChildCount; +} + +void KMdiChildArea::tilePragma() +{ + kdDebug( 760 ) << k_funcinfo << endl; + tileAllInternal( 9 ); +} + +void KMdiChildArea::tileAllInternal( int maxWnds ) +{ + kdDebug( 760 ) << k_funcinfo << endl; + //NUM WINDOWS = 1,2,3,4,5,6,7,8,9 + static int colstable[ 9 ] = { 1, 1, 1, 2, 2, 2, 3, 3, 3 }; //num columns + static int rowstable[ 9 ] = { 1, 2, 3, 2, 3, 3, 3, 3, 3 }; //num rows + static int lastwindw[ 9 ] = { 1, 1, 1, 1, 2, 1, 3, 2, 1 }; //last window multiplier + static int colrecall[ 9 ] = { 0, 0, 0, 3, 3, 3, 6, 6, 6 }; //adjust self + static int rowrecall[ 9 ] = { 0, 0, 0, 0, 4, 4, 4, 4, 4 }; //adjust self + + int numVisible = getVisibleChildCount(); + if ( numVisible < 1 ) + { + kdDebug( 760 ) << k_funcinfo << "No visible child windows to tile" << endl; + return; + } + + KMdiChildFrm *tcw = topChild(); + int numToHandle = ( ( numVisible > maxWnds ) ? maxWnds : numVisible ); + + int xQuantum = width() / colstable[ numToHandle - 1 ]; + int widthToCompare; + + if ( tcw->minimumWidth() > m_defaultChildFrmSize.width() ) + widthToCompare = tcw->minimumWidth(); + else + widthToCompare = m_defaultChildFrmSize.width(); + + if ( xQuantum < widthToCompare ) + { + if ( colrecall[ numToHandle - 1 ] != 0 ) + { + tileAllInternal( colrecall[ numToHandle - 1 ] ); + return ; + } + } + + int yQuantum = height() / rowstable[ numToHandle - 1 ]; + int heightToCompare; + if ( tcw->minimumHeight() > m_defaultChildFrmSize.height() ) + heightToCompare = tcw->minimumHeight(); + else + heightToCompare = m_defaultChildFrmSize.height(); + + if ( yQuantum < heightToCompare ) + { + if ( rowrecall[ numToHandle - 1 ] != 0 ) + { + tileAllInternal( rowrecall[ numToHandle - 1 ] ); + return ; + } + } + int curX = 0; + int curY = 0; + int curRow = 1; + int curCol = 1; + int curWin = 1; + + QPtrListIterator<KMdiChildFrm> it( *m_pZ ); + for ( ; ( *it ); ++it ) + { + KMdiChildFrm* child = ( *it ); + if ( child->state() != KMdiChildFrm::Minimized ) + { + //restore the window + if ( child->state() == KMdiChildFrm::Maximized ) + child->restorePressed(); + + if ( ( curWin % numToHandle ) == 0 ) + child->setGeometry( curX, curY, xQuantum * lastwindw[ numToHandle - 1 ], yQuantum ); + else + child->setGeometry( curX, curY, xQuantum, yQuantum ); + + //example : 12 windows : 3 cols 3 rows + if ( curCol < colstable[ numToHandle - 1 ] ) + { //curCol<3 + curX += xQuantum; //add a column in the same row + curCol++; //increase current column + } + else + { + curX = 0; //new row + curCol = 1; //column 1 + if ( curRow < rowstable[ numToHandle - 1 ] ) + { //curRow<3 + curY += yQuantum; //add a row + curRow++; //increase current row + } + else + { + curY = 0; //restart from beginning + curRow = 1; //reset current row + } + } + curWin++; + } + } + + if ( tcw ) + tcw->m_pClient->activate(); +} + +void KMdiChildArea::tileAnodine() +{ + KMdiChildFrm * topChildWindow = topChild(); + int numVisible = getVisibleChildCount(); // count visible windows + if ( numVisible < 1 ) + return ; + + int numCols = int( sqrt( ( double ) numVisible ) ); // set columns to square root of visible count + // create an array to form grid layout + int *numRows = new int[ numCols ]; + int numCurCol = 0; + + while ( numCurCol < numCols ) + { + numRows[numCurCol] = numCols; // create primary grid values + numCurCol++; + } + + int numDiff = numVisible - ( numCols * numCols ); // count extra rows + int numCurDiffCol = numCols; // set column limiting for grid updates + + while ( numDiff > 0 ) + { + numCurDiffCol--; + numRows[numCurDiffCol]++; // add extra rows to column grid + + if ( numCurDiffCol < 1 ) + numCurDiffCol = numCols; // rotate through the grid + + numDiff--; + } + + numCurCol = 0; + int numCurRow = 0; + int curX = 0; + int curY = 0; + + // the following code will size everything based on my grid above + // there is no limit to the number of windows it will handle + // it's great when a kick-ass theory works!!! // Pragma :) + int xQuantum = width() / numCols; + int yQuantum = height() / numRows[numCurCol]; + QPtrListIterator<KMdiChildFrm> it( *m_pZ ); + for ( ; ( *it ); ++it ) + { + KMdiChildFrm* child = ( *it ); + if ( child->state() != KMdiChildFrm::Minimized ) + { + if ( child->state() == KMdiChildFrm::Maximized ) + child->restorePressed(); + + child->setGeometry( curX, curY, xQuantum, yQuantum ); + numCurRow++; + curY += yQuantum; + + if ( numCurRow == numRows[numCurCol] ) + { + numCurRow = 0; + numCurCol++; + curY = 0; + curX += xQuantum; + if ( numCurCol != numCols ) + yQuantum = height() / numRows[ numCurCol ]; + } + } + } + + delete[] numRows; + + if ( topChildWindow ) + topChildWindow->m_pClient->activate(); +} + + +void KMdiChildArea::tileVertically() +{ + KMdiChildFrm * topChildWindow = topChild(); + int numVisible = getVisibleChildCount(); // count visible windows + if ( numVisible < 1 ) + return ; + + int w = width() / numVisible; + int lastWidth = 0; + + if ( numVisible > 1 ) + lastWidth = width() - ( w * ( numVisible - 1 ) ); + else + lastWidth = w; + + int h = height(); + int posX = 0; + int countVisible = 0; + + QPtrListIterator<KMdiChildFrm> it( *m_pZ ); + for ( ; ( *it ); ++it ) + { + KMdiChildFrm* child = ( *it ); + if ( child->state() != KMdiChildFrm::Minimized ) + { + if ( child->state() == KMdiChildFrm::Maximized ) + child->restorePressed(); + + countVisible++; + + if ( countVisible < numVisible ) + { + child->setGeometry( posX, 0, w, h ); + posX += w; + } + else + { // last visible childframe + child->setGeometry( posX, 0, lastWidth, h ); + } + } + } + + if ( topChildWindow ) + topChildWindow->m_pClient->activate(); +} + + +void KMdiChildArea::layoutMinimizedChildren() +{ + int posX = 0; + int posY = height(); + QPtrListIterator<KMdiChildFrm> it( *m_pZ ); + for ( ; ( *it ); ++it ) + { + KMdiChildFrm* child = *( it ); + if ( child->state() == KMdiChildFrm::Minimized ) + { + + if ( ( posX > 0 ) && ( posX + child->width() > width() ) ) + { + posX = 0; + posY -= child->height(); + } + + child->move( posX, posY - child->height() ); + posX = child->geometry().right(); + } + } +} + + +void KMdiChildArea::setMdiCaptionFont( const QFont& fnt ) +{ + m_captionFont = fnt; + QFontMetrics fm( m_captionFont ); + m_captionFontLineSpacing = fm.lineSpacing(); + + QPtrListIterator<KMdiChildFrm> it( *m_pZ ); + for ( ; ( *it ); ++it ) + ( *it )->doResize(); + +} + +void KMdiChildArea::setMdiCaptionActiveForeColor( const QColor& clr ) +{ + m_captionActiveForeColor = clr; +} + +void KMdiChildArea::setMdiCaptionActiveBackColor( const QColor& clr ) +{ + m_captionActiveBackColor = clr; +} + +void KMdiChildArea::setMdiCaptionInactiveForeColor( const QColor& clr ) +{ + m_captionInactiveForeColor = clr; +} + +void KMdiChildArea::setMdiCaptionInactiveBackColor( const QColor& clr ) +{ + m_captionInactiveBackColor = clr; +} + +//KDE4: remove +void KMdiChildArea::getCaptionColors( const QPalette& /*pal*/, QColor& activeBG, + QColor& activeFG, QColor& inactiveBG, QColor& inactiveFG ) +{ + activeBG = KGlobalSettings::activeTitleColor(); + activeFG = KGlobalSettings::activeTextColor(); + inactiveBG = KGlobalSettings::inactiveTitleColor(); + inactiveFG = KGlobalSettings::inactiveTextColor(); +} + +// kate: space-indent off; replace-tabs off; tab-width 4; indent-mode csands; diff --git a/lib/compatibility/kmdi/qextmdi/kmdichildarea.h b/lib/compatibility/kmdi/qextmdi/kmdichildarea.h new file mode 100644 index 00000000..3eaac559 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmdichildarea.h @@ -0,0 +1,306 @@ +//---------------------------------------------------------------------------- +// filename : kmdichildarea.h +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 07/1999 by Szymon Stefanek as part of kvirc +// (an IRC application) +// changes : 09/1999 by Falk Brettschneider to create an +// - 06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// 2000-2003 maintained by the KDevelop project +// +// copyright : (C) 1999-2003 by Falk Brettschneider +// and +// Szymon Stefanek (stefanek@tin.it) +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program 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. +// +//---------------------------------------------------------------------------- + +#ifndef _KMDI_CHILD_AREA_H_ +#define _KMDI_CHILD_AREA_H_ + +#include <qframe.h> +#include <qptrlist.h> + +#include "kmdichildfrm.h" +#include "kmdichildview.h" + +class KMdiChildAreaPrivate; + +/** + * @short Internal class. + * + * The main frame widget KMdiMainFrm consists of 2 child widgets. One is this class. + * It's the widget where the child frames (emulated toplevel MDI views) live in. + * This class is the manager for the child frame widgets because it controls the + * Z-order widget stack of KMdiChildFrm's. + * It provides all placing and positioning algorithms for docked (attached) MDI views. + * + * KMdiChildArea doesn't know anything about the actual MDI views. It only knows + * and manages the frame widgets of attached MDI views. + * All actions and stuff concerning only to childframes are handled here. + */ +class KMDI_EXPORT KMdiChildArea : public QFrame +{ + friend class KMdiChildFrmCaption; + friend class KMdiChildFrm; + +Q_OBJECT + + // attributes +public: + /** + * Z Order stack of KMdiChildFrm childframe windows (top=last) + */ + QPtrList<KMdiChildFrm> *m_pZ; //Auto delete enabled + + /** + * the default size of an newly created childframe + */ + QSize m_defaultChildFrmSize; +protected: + /** + * The MDI childframe window caption font + */ + QFont m_captionFont; + + /** + * The foreground color of the active MDI childframe window caption + */ + QColor m_captionActiveBackColor; + + /** + * The background color of the active MDI childframe window captions + */ + QColor m_captionActiveForeColor; + + /** + * The foreground color of inactive MDI childframe window captions + */ + QColor m_captionInactiveBackColor; + + /** + * The background color of inactive MDI childframe window captions + */ + QColor m_captionInactiveForeColor; + + int m_captionFontLineSpacing; + + // methods +public: + + /** + * Consruction. Note: This class needn't to know about KMdiMainFrm . + */ + KMdiChildArea( QWidget *parent ); + + /** + * Destructor : THERE should be no child windows anymore... + * Howewer it simply deletes all the child widgets :) + */ + ~KMdiChildArea(); + + /** + * Appends a new KMdiChildFrm to this manager. + * The child is shown,raised and gets focus if this window has it. + */ + void manageChild( KMdiChildFrm *lpC, bool bShow = true, bool bCascade = true ); + + /** + * Destroys a managed KMdiChildFrm + * Also deletes the client attached to this child. + */ + void destroyChild( KMdiChildFrm* child, bool focusTopChild = true ); + + /** + * Destroys a managed KMdiChildFrm + * Clients attached to the KMdiChildFrm are not deleted. + * @param child + */ + void destroyChildButNotItsView( KMdiChildFrm *lpC, bool bFocusTopChild = true ); + + /** + * Brings the child @p child to the top of the stack + * The child is focused if @p setFocus is true. If setFocus is false, the + * child is just raised. + * @param child + */ + void setTopChild( KMdiChildFrm* child, bool setFocus = false ); + + /** + * Returns the topmost child (the active one) or 0 if there are no children. + * Note that the topmost child may be also hidded , if ALL the windows are minimized. + */ + inline KMdiChildFrm * topChild() const { return m_pZ->last(); } + + /** + * Returns the number of visible children + */ + int getVisibleChildCount() const; + + /** + * Calculates the cascade point for the given index. If index is -1 + * the cascade point is calculated for the window following the last window + * @param indexOfWindow the index of the window in relation the z-ordered window list + */ + QPoint getCascadePoint( int indexOfWindow = -1 ); + + /** + * Sets the MDI childframe window caption font + * A relayout does not occur when using this function + */ + void setMdiCaptionFont( const QFont &fnt ); + + /** + * Sets the foreground color of the active MDI childframe window caption + * A relayout does not occur when using this function + */ + void setMdiCaptionActiveForeColor( const QColor &clr ); + + /** + * Sets the background color of the active MDI childframe window captions + * A relayout does not occur when using this function + */ + void setMdiCaptionActiveBackColor( const QColor &clr ); + + /** + * Sets the foreground color of inactive MDI childframe window captions + * A relayout does not occur when using this function + */ + void setMdiCaptionInactiveForeColor( const QColor &clr ); + + /** + * Sets the background color of inactive MDI childframe window captions + * A relayout does not occur when using this function + */ + void setMdiCaptionInactiveBackColor( const QColor &clr ); + + /** + * Gets all caption colors, consistent with current WM settings + * (or other Desktop settings e.g. system settings for win32) + * This method is useful not only for KMDI child windows. + * Colors are returned via activeBG, activeFG, inactiveBG, inactiveFG references. + * + * @deprecated Use KGlobalSettings::activeTitleColor(), KGlobalSettings::activeTextColor(), + * KGlobalSettings::inactiveTitleColor() and KGlobalSettings::inactiveTextColor() instead. + */ + static void getCaptionColors( const QPalette &pal, QColor &activeBG, QColor &activeFG, + QColor &inactiveBG, QColor &inactiveFG ) KDE_DEPRECATED; + +public slots: + /** + * Cascades all windows resizing them to the minimum size. + */ + void cascadeWindows(); + + /** + * Cascades all windows resizing them to the maximum available size. + */ + void cascadeMaximized(); + + /** + * Maximize all windows but only in vertical direction + */ + void expandVertical(); + + /** + * Maximize all windows but only in horizontal direction + */ + void expandHorizontal(); + + /** + * Gives focus to the topmost child if it doesn't get focus + * automatically or you want to wait to give it focus + */ + void focusTopChild(); + + /** + * Tile Pragma + */ + void tilePragma(); + + /** + * Tile Anodine + */ + void tileAnodine(); + + /** + * Tile all the windows in the child area vertically + */ + void tileVertically(); + + /** + * Position and layout the minimized child frames + */ + void layoutMinimizedChildren(); + +protected: + + /** + * Internally used for the tile algorithm + */ + void tileAllInternal( int maxWnds ); + + /** + * Automatically resizes a maximized MDI view and layouts the positions of minimized MDI views. + */ + virtual void resizeEvent( QResizeEvent * ); + + /** + * Shows the 'Window' popup menu on right mouse button click + */ + void mousePressEvent( QMouseEvent *e ); + + /** + * Internally used. Actions that are necessary when an MDI view gets minimized + */ + void childMinimized( KMdiChildFrm *lpC, bool bWasMaximized ); + +signals: + /** + * Signals that there aren't maximized child frames any more + */ + void noMaximizedChildFrmLeft( KMdiChildFrm* ); + + /** + * Signals that the child frames are maximized now + */ + void nowMaximized( bool ); + + /** + * Signals a KMdiMainFrm that the signal/slot connections of the system buttons in the + * menubar (only in Maximize mode) must be updated to another MDI view because the focused + * MDI view has changed + * @internal + */ + void sysButtonConnectionsMustChange( KMdiChildFrm*, KMdiChildFrm* ); + + /** + * Signals a KMdiMainFrm that the 'Window' popup menu must be shown + * @internal + */ + void popupWindowMenu( QPoint ); + + /** + * Signals that the last attached (docked) MDI view has been closed. + * Note: Detached MDI views can remain. + */ + void lastChildFrmClosed(); + +private: + + KMdiChildAreaPrivate *d; +}; + +#endif // _KMDICHILDAREA_H_ + +// kate: indent-mode csands; tab-width 4; auto-insert-doxygen on; diff --git a/lib/compatibility/kmdi/qextmdi/kmdichildfrm.cpp b/lib/compatibility/kmdi/qextmdi/kmdichildfrm.cpp new file mode 100644 index 00000000..1a30a601 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmdichildfrm.cpp @@ -0,0 +1,1409 @@ +//---------------------------------------------------------------------------- +// filename : kmdichildfrm.cpp +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 07/1999 by Szymon Stefanek as part of kvirc +// (an IRC application) +// changes : 09/1999 by Falk Brettschneider to create an +// - 06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// : 01/2003 by Jens Zurheide to allow switching +// between views based on timestamps +// 2000-2003 maintained by the KDevelop project +// +// copyright : (C) 1999-2003 by Szymon Stefanek (stefanek@tin.it) +// and +// Falk Brettschneider +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program 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. +// +//---------------------------------------------------------------------------- + +#include "kmdichildfrm.h" +#include "kmdichildfrm.moc" + +#include "kmdidefines.h" +#include "kmdichildfrmcaption.h" +#include "kmdichildarea.h" +#include "kmdimainfrm.h" + +#include <qpainter.h> +#include <qapplication.h> +#include <qcursor.h> +#include <qobjectlist.h> +#include <qframe.h> +#include <qpopupmenu.h> +#include <qtoolbutton.h> +#include <qnamespace.h> +#include <qimage.h> + +#include <klocale.h> +#include <kiconloader.h> + +////////////////////////////////////////////////////////////////////////////// +// KMdiChildFrm +////////////////////////////////////////////////////////////////////////////// + +#define KMDI_NORESIZE 0 +#define KMDI_RESIZE_TOP 1 +#define KMDI_RESIZE_LEFT 2 +#define KMDI_RESIZE_RIGHT 4 +#define KMDI_RESIZE_BOTTOM 8 +#define KMDI_RESIZE_TOPLEFT (1|2) +#define KMDI_RESIZE_TOPRIGHT (1|4) +#define KMDI_RESIZE_BOTTOMLEFT (8|2) +#define KMDI_RESIZE_BOTTOMRIGHT (8|4) + +#include "filenew.xpm" +#include "win_closebutton.xpm" +#include "win_minbutton.xpm" +#include "win_maxbutton.xpm" +#include "win_restorebutton.xpm" +#include "win_undockbutton.xpm" +#include "kde_closebutton.xpm" +#include "kde_minbutton.xpm" +#include "kde_maxbutton.xpm" +#include "kde_restorebutton.xpm" +#include "kde_undockbutton.xpm" +#include "kde2_closebutton.xpm" +#include "kde2_minbutton.xpm" +#include "kde2_maxbutton.xpm" +#include "kde2_restorebutton.xpm" +#include "kde2_undockbutton.xpm" +#include "kde2laptop_closebutton.xpm" +#include "kde2laptop_minbutton.xpm" +#include "kde2laptop_maxbutton.xpm" +#include "kde2laptop_restorebutton.xpm" +#include "kde2laptop_undockbutton.xpm" + + +KMdiWin32IconButton::KMdiWin32IconButton( QWidget* parent, const char* name ) + : QLabel( parent, name ) +{} + +//============ mousePressEvent ============// + +void KMdiWin32IconButton::mousePressEvent( QMouseEvent* ) +{ + //emit pressed(); +} + +//============ KMdiChildFrm ============// + +KMdiChildFrm::KMdiChildFrm( KMdiChildArea *parent ) + : QFrame( parent, "kmdi_childfrm" ) + , m_pClient( 0L ) + , m_pManager( 0L ) + , m_pCaption( 0L ) + , m_pWinIcon( 0L ) + , m_pUnixIcon( 0L ) + , m_pMinimize( 0L ) + , m_pMaximize( 0L ) + , m_pClose( 0L ) + , m_pUndock( 0L ) + , m_state( Normal ) + , m_restoredRect() + , m_iResizeCorner( KMDI_NORESIZE ) + , m_iLastCursorCorner( KMDI_NORESIZE ) + , m_bResizing( false ) + , m_bDragging( false ) + , m_pIconButtonPixmap( 0L ) + , m_pMinButtonPixmap( 0L ) + , m_pMaxButtonPixmap( 0L ) + , m_pRestoreButtonPixmap( 0L ) + , m_pCloseButtonPixmap( 0L ) + , m_pUndockButtonPixmap( 0L ) + , m_windowMenuID( 0 ) + , m_pSystemMenu( 0L ) + , m_oldClientMinSize() + , m_oldClientMaxSize() + , m_oldLayoutResizeMode( QLayout::Minimum ) +{ + m_pCaption = new KMdiChildFrmCaption( this ); + + m_pManager = parent; + + m_pWinIcon = new KMdiWin32IconButton( m_pCaption, "kmdi_iconbutton_icon" ); + m_pUnixIcon = new QToolButton( m_pCaption, "kmdi_toolbutton_icon" ); + m_pMinimize = new QToolButton( m_pCaption, "kmdi_toolbutton_min" ); + m_pMaximize = new QToolButton( m_pCaption, "kmdi_toolbutton_max" ); + m_pClose = new QToolButton( m_pCaption, "kmdi_toolbutton_close" ); + m_pUndock = new QToolButton( m_pCaption, "kmdi_toolbutton_undock" ); + + QObject::connect( m_pMinimize, SIGNAL( clicked() ), this, SLOT( minimizePressed() ) ); + QObject::connect( m_pMaximize, SIGNAL( clicked() ), this, SLOT( maximizePressed() ) ); + QObject::connect( m_pClose, SIGNAL( clicked() ), this, SLOT( closePressed() ) ); + QObject::connect( m_pUndock, SIGNAL( clicked() ), this, SLOT( undockPressed() ) ); + + m_pIconButtonPixmap = new QPixmap( SmallIcon( "filenew" ) ); + if ( m_pIconButtonPixmap->isNull() ) + * m_pIconButtonPixmap = QPixmap( filenew ); + + redecorateButtons(); + + m_pWinIcon->setFocusPolicy( NoFocus ); + m_pUnixIcon->setFocusPolicy( NoFocus ); + m_pClose->setFocusPolicy( NoFocus ); + m_pMinimize->setFocusPolicy( NoFocus ); + m_pMaximize->setFocusPolicy( NoFocus ); + m_pUndock->setFocusPolicy( NoFocus ); + + setFrameStyle( QFrame::WinPanel | QFrame::Raised ); + setFocusPolicy( NoFocus ); + + setMouseTracking( true ); + + setMinimumSize( KMDI_CHILDFRM_MIN_WIDTH, m_pCaption->heightHint() ); + + m_pSystemMenu = new QPopupMenu(); +} + +//============ ~KMdiChildFrm ============// + +KMdiChildFrm::~KMdiChildFrm() +{ + delete m_pMinButtonPixmap; + delete m_pMaxButtonPixmap; + delete m_pRestoreButtonPixmap; + delete m_pCloseButtonPixmap; + delete m_pUndockButtonPixmap; + delete m_pSystemMenu; + delete m_pIconButtonPixmap; +} + +//============ mousePressEvent =============// +void KMdiChildFrm::mousePressEvent( QMouseEvent *e ) +{ + if ( m_bResizing ) + { + if ( QApplication::overrideCursor() ) + QApplication::restoreOverrideCursor(); + + m_bResizing = false; + releaseMouse(); + } + + m_pCaption->setActive( true ); + m_pManager->setTopChild( this, false ); + + m_iResizeCorner = getResizeCorner( e->pos().x(), e->pos().y() ); + if ( m_iResizeCorner != KMDI_NORESIZE ) + { + m_bResizing = true; + //notify child view + KMdiChildFrmResizeBeginEvent ue( e ); + if ( m_pClient != 0L ) + QApplication::sendEvent( m_pClient, &ue ); + } +} + +//============ mouseReleaseEvent ==============// + +void KMdiChildFrm::mouseReleaseEvent( QMouseEvent *e ) +{ + if ( m_bResizing ) + { + if ( QApplication::overrideCursor() ) + QApplication::restoreOverrideCursor(); + + m_bResizing = false; + //notify child view + KMdiChildFrmResizeEndEvent ue( e ); + if ( m_pClient != 0L ) + QApplication::sendEvent( m_pClient, &ue ); + } +} + +//============= setResizeCursor ===============// + +void KMdiChildFrm::setResizeCursor( int resizeCorner ) +{ + if ( resizeCorner == m_iLastCursorCorner ) + return ; //Don't do it twice + + m_iLastCursorCorner = resizeCorner; + switch ( resizeCorner ) + { + case KMDI_NORESIZE: + if ( QApplication::overrideCursor() ) + QApplication::restoreOverrideCursor(); + break; + case KMDI_RESIZE_LEFT: + case KMDI_RESIZE_RIGHT: + QApplication::setOverrideCursor( Qt::sizeHorCursor, true ); + break; + case KMDI_RESIZE_TOP: + case KMDI_RESIZE_BOTTOM: + QApplication::setOverrideCursor( Qt::sizeVerCursor, true ); + break; + case KMDI_RESIZE_TOPLEFT: + case KMDI_RESIZE_BOTTOMRIGHT: + QApplication::setOverrideCursor( Qt::sizeFDiagCursor, true ); + break; + case KMDI_RESIZE_BOTTOMLEFT: + case KMDI_RESIZE_TOPRIGHT: + QApplication::setOverrideCursor( Qt::sizeBDiagCursor, true ); + break; + } +} + +//============= unsetResizeCursor ===============// + +void KMdiChildFrm::unsetResizeCursor() +{ + if ( !m_bResizing && m_iResizeCorner != KMDI_NORESIZE ) + { + m_iResizeCorner = KMDI_NORESIZE; + m_iLastCursorCorner = KMDI_NORESIZE; + if ( QApplication::overrideCursor() ) + QApplication::restoreOverrideCursor(); + } +} + +//============= mouseMoveEvent ===============// + +void KMdiChildFrm::mouseMoveEvent( QMouseEvent *e ) +{ + if ( m_state != Normal ) + return; + + if ( !m_pClient ) + return; + + if ( m_pClient->minimumSize() == m_pClient->maximumSize() ) + return; + + if ( m_bResizing ) + { + if ( !( e->state() & RightButton ) && !( e->state() & MidButton ) ) + { + // same as: if no button or left button pressed + QPoint p = parentWidget()->mapFromGlobal( e->globalPos() ); + resizeWindow( m_iResizeCorner, p.x(), p.y() ); + } + else + m_bResizing = false; + } + else + { + m_iResizeCorner = getResizeCorner( e->pos().x(), e->pos().y() ); + setResizeCursor( m_iResizeCorner ); + } +} + +//============= moveEvent ===============// + +void KMdiChildFrm::moveEvent( QMoveEvent* me ) +{ + // give its child view the chance to notify a childframe move + KMdiChildFrmMoveEvent cfme( me ); + if ( m_pClient != 0L ) + QApplication::sendEvent( m_pClient, &cfme ); +} + +//=============== leaveEvent ===============// + +void KMdiChildFrm::leaveEvent( QEvent * ) +{ + unsetResizeCursor(); +} + +void KMdiChildFrm::resizeWindow( int resizeCorner, int xPos, int yPos ) +{ + QRect resizeRect( x(), y(), width(), height() ); + + // Calculate the minimum width & height + int minWidth = 0; + int minHeight = 0; + int maxWidth = QWIDGETSIZE_MAX; + int maxHeight = QWIDGETSIZE_MAX; + + // it could be the client forces the childframe to enlarge its minimum size + if ( m_pClient ) + { + minWidth = m_pClient->minimumSize().width() + KMDI_CHILDFRM_DOUBLE_BORDER; + minHeight = m_pClient->minimumSize().height() + KMDI_CHILDFRM_DOUBLE_BORDER + + m_pCaption->heightHint() + KMDI_CHILDFRM_SEPARATOR; + maxWidth = m_pClient->maximumSize().width() + KMDI_CHILDFRM_DOUBLE_BORDER; + maxHeight = m_pClient->maximumSize().height() + KMDI_CHILDFRM_DOUBLE_BORDER + + m_pCaption->heightHint() + KMDI_CHILDFRM_SEPARATOR; + } + + if ( minWidth < minimumWidth() ) + minWidth = minimumWidth(); + + if ( minHeight < minimumHeight() ) + minHeight = minimumHeight(); + + if ( maxWidth > maximumWidth() ) + maxWidth = maximumWidth(); + + if ( maxHeight > maximumHeight() ) + maxHeight = maximumHeight(); + + QPoint mousePos( xPos, yPos ); + + // manipulate width + switch ( resizeCorner ) + { + //left sides + case KMDI_RESIZE_TOPLEFT: + case KMDI_RESIZE_LEFT: + case KMDI_RESIZE_BOTTOMLEFT: + resizeRect.setLeft( mousePos.x() ); + if ( resizeRect.width() < minWidth ) + resizeRect.setLeft( resizeRect.right() - minWidth + 1 ); + if ( resizeRect.width() > maxWidth ) + resizeRect.setLeft( resizeRect.right() - maxWidth + 1 ); + break; + //right sides + case KMDI_RESIZE_TOPRIGHT: + case KMDI_RESIZE_RIGHT: + case KMDI_RESIZE_BOTTOMRIGHT: + resizeRect.setRight( mousePos.x() ); + if ( resizeRect.width() < minWidth ) + resizeRect.setRight( resizeRect.left() + minWidth - 1 ); + if ( resizeRect.width() > maxWidth ) + resizeRect.setRight( resizeRect.left() + maxWidth - 1 ); + break; + default: + break; + } + + // manipulate height + switch ( resizeCorner ) + { + case KMDI_RESIZE_TOPLEFT: + case KMDI_RESIZE_TOP: + case KMDI_RESIZE_TOPRIGHT: + resizeRect.setTop( mousePos.y() ); + if ( resizeRect.height() < minHeight ) + resizeRect.setTop( resizeRect.bottom() - minHeight + 1 ); + if ( resizeRect.height() > maxHeight ) + resizeRect.setTop( resizeRect.bottom() - maxHeight + 1 ); + break; + case KMDI_RESIZE_BOTTOMLEFT: + case KMDI_RESIZE_BOTTOM: + case KMDI_RESIZE_BOTTOMRIGHT: + resizeRect.setBottom( mousePos.y() ); + if ( resizeRect.height() < minHeight ) + resizeRect.setBottom( resizeRect.top() + minHeight - 1 ); + if ( resizeRect.height() > maxHeight ) + resizeRect.setBottom( resizeRect.top() + maxHeight - 1 ); + break; + default: + // nothing to do + break; + } + // actually resize + setGeometry( resizeRect ); + + if ( m_state == Maximized ) + { + m_state = Normal; + m_pMaximize->setPixmap( *m_pMaxButtonPixmap ); + } +} + +//================= getResizeCorner =============// + +int KMdiChildFrm::getResizeCorner( int ax, int ay ) +{ + int ret = KMDI_NORESIZE; + if ( m_pClient->minimumWidth() != m_pClient->maximumWidth() ) + { + if ( ( ax > 0 ) && ( ax < ( KMDI_CHILDFRM_BORDER + 2 ) ) ) + ret |= KMDI_RESIZE_LEFT; + + if ( ( ax < width() ) && ( ax > ( width() - ( KMDI_CHILDFRM_BORDER + 2 ) ) ) ) + ret |= KMDI_RESIZE_RIGHT; + } + if ( m_pClient->minimumHeight() != m_pClient->maximumHeight() ) + { + if ( ( ay > 0 ) && ( ay < ( KMDI_CHILDFRM_BORDER + 2 ) ) ) + ret |= KMDI_RESIZE_TOP; + + if ( ( ay < ( height() ) ) && ( ay > ( height() - ( KMDI_CHILDFRM_BORDER + 2 ) ) ) ) + ret |= KMDI_RESIZE_BOTTOM; + } + return ret; +} + +//============= maximizePressed ============// + +void KMdiChildFrm::maximizePressed() +{ + switch ( m_state ) + { + case Maximized: + emit m_pManager->nowMaximized( false ); + setState( Normal ); + break; + case Normal: + case Minimized: + setState( Maximized ); + emit m_pManager->nowMaximized( true ); + break; + } +} + +void KMdiChildFrm::restorePressed() +{ + if ( m_state == Normal ) + return ; + + if ( m_state == Maximized ) + emit m_pManager->nowMaximized( false ); + + setState( Normal ); +} + +//============= minimizePressed ============// + +void KMdiChildFrm::minimizePressed() +{ + switch ( m_state ) + { + case Minimized: + setState( Normal ); + break; + case Normal: + setState( Minimized ); + break; + case Maximized: + emit m_pManager->nowMaximized( false ); + setState( Normal ); + setState( Minimized ); + break; + } +} + +//============= closePressed ============// + +void KMdiChildFrm::closePressed() +{ + if ( m_pClient ) + m_pClient->close(); +} + +//============= undockPressed ============// + +void KMdiChildFrm::undockPressed() +{ + if ( m_pClient ) + { + if ( m_state == Minimized ) + setState( Normal ); + m_pClient->detach(); + } +} + +//============ setState =================// + +void KMdiChildFrm::setState( MdiWindowState state, bool /*bAnimate*/ ) +{ + if ( m_state == Normal ) //save the current rect + m_restoredRect = QRect( x(), y(), width(), height() ); + + switch ( state ) + { + case Normal: + switch ( m_state ) + { + case Maximized: + m_pClient->m_stateChanged = true; + m_state = state; + // client min / max size / layout behavior don't change + // set frame max size indirectly by setting the clients max size to + // it's current value (calls setMaxSize() of frame) + m_pClient->setMaximumSize( m_pClient->maximumSize().width(), m_pClient->maximumSize().height() ); + m_pMaximize->setPixmap( *m_pMaxButtonPixmap ); + setGeometry( m_restoredRect ); + break; + case Minimized: + m_pClient->m_stateChanged = true; + m_state = state; + // restore client min / max size / layout behavior + m_pClient->setMinimumSize( m_oldClientMinSize.width(), m_oldClientMinSize.height() ); + m_pClient->setMaximumSize( m_oldClientMaxSize.width(), m_oldClientMaxSize.height() ); + if ( m_pClient->layout() != 0L ) + { + m_pClient->layout() ->setResizeMode( m_oldLayoutResizeMode ); + } + m_pMinimize->setPixmap( *m_pMinButtonPixmap ); + m_pMaximize->setPixmap( *m_pMaxButtonPixmap ); + QObject::disconnect( m_pMinimize, SIGNAL( clicked() ), this, SLOT( restorePressed() ) ); + QObject::connect( m_pMinimize, SIGNAL( clicked() ), this, SLOT( minimizePressed() ) ); + setGeometry( m_restoredRect ); + break; + case Normal: + break; + } + break; + case Maximized: + switch ( m_state ) + { + case Minimized: + { + m_pClient->m_stateChanged = true; + m_state = state; + // restore client min / max size / layout behavior + m_pClient->setMinimumSize( m_oldClientMinSize.width(), m_oldClientMinSize.height() ); + m_pClient->setMaximumSize( m_oldClientMaxSize.width(), m_oldClientMaxSize.height() ); + if ( m_pClient->layout() != 0L ) + { + m_pClient->layout() ->setResizeMode( m_oldLayoutResizeMode ); + } + setMaximumSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX ); + // reset to maximize-captionbar + m_pMaximize->setPixmap( *m_pRestoreButtonPixmap ); + m_pMinimize->setPixmap( *m_pMinButtonPixmap ); + QObject::disconnect( m_pMinimize, SIGNAL( clicked() ), this, SLOT( restorePressed() ) ); + QObject::connect( m_pMinimize, SIGNAL( clicked() ), this, SLOT( minimizePressed() ) ); + int nFrameWidth = KMDI_CHILDFRM_DOUBLE_BORDER; + int nFrameHeight = KMDI_CHILDFRM_DOUBLE_BORDER + KMDI_CHILDFRM_SEPARATOR + + m_pCaption->heightHint(); + setGeometry( -m_pClient->x(), -m_pClient->y(), + m_pManager->width() + nFrameWidth, + m_pManager->height() + nFrameHeight ); + raise(); + } + break; + case Normal: + { + m_pClient->m_stateChanged = true; + m_state = state; + // client min / max size / layout behavior don't change + setMaximumSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX ); + m_pMaximize->setPixmap( *m_pRestoreButtonPixmap ); + int nFrameWidth = KMDI_CHILDFRM_DOUBLE_BORDER; + int nFrameHeight = KMDI_CHILDFRM_DOUBLE_BORDER + KMDI_CHILDFRM_SEPARATOR + + m_pCaption->heightHint(); + QRect maximizedFrmRect( -m_pClient->x(), -m_pClient->y(), + m_pManager->width() + nFrameWidth, + m_pManager->height() + nFrameHeight ); + if ( geometry() != maximizedFrmRect ) + { + setGeometry( maximizedFrmRect ); + } + raise(); + } + break; + case Maximized: + break; + } + break; + case Minimized: + switch ( m_state ) + { + case Maximized: + m_pClient->m_stateChanged = true; + m_state = state; + // save client min / max size / layout behavior + m_oldClientMinSize = m_pClient->minimumSize(); + m_oldClientMaxSize = m_pClient->maximumSize(); + if ( m_pClient->layout() != 0L ) + { + m_oldLayoutResizeMode = m_pClient->layout() ->resizeMode(); + } + m_pClient->setMinimumSize( 0, 0 ); + m_pClient->setMaximumSize( 0, 0 ); + if ( m_pClient->layout() != 0L ) + { + m_pClient->layout() ->setResizeMode( QLayout::FreeResize ); + } + switchToMinimizeLayout(); + m_pManager->childMinimized( this, true ); + break; + case Normal: + m_pClient->m_stateChanged = true; + m_state = state; + // save client min / max size / layout behavior + m_oldClientMinSize = m_pClient->minimumSize(); + m_oldClientMaxSize = m_pClient->maximumSize(); + if ( m_pClient->layout() != 0L ) + { + m_oldLayoutResizeMode = m_pClient->layout() ->resizeMode(); + } + m_restoredRect = geometry(); + m_pClient->setMinimumSize( 0, 0 ); + m_pClient->setMaximumSize( 0, 0 ); + if ( m_pClient->layout() != 0L ) + { + m_pClient->layout() ->setResizeMode( QLayout::FreeResize ); + } + switchToMinimizeLayout(); + m_pManager->childMinimized( this, false ); + break; + case Minimized: + break; + } + break; + } + + KMdiChildFrm* pTopFrame = m_pManager->topChild(); + KMdiChildView* pTopChild = 0L; + if ( pTopFrame != 0L ) + { + pTopChild = pTopFrame->m_pClient; + } + if ( ( pTopChild != 0L ) && pTopChild->isMaximized() ) + { + m_pManager->setMinimumSize( pTopChild->minimumWidth(), pTopChild->minimumHeight() ); + /// @todo: setting the maximum size doesn't work properly - fix this later + /// m_pManager->setMaximumSize(pTopChild->maximumWidth(), pTopChild->maximumHeight()); + } + else + { + m_pManager->setMinimumSize( 0, 0 ); + m_pManager->setMaximumSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX ); + } +} + +//============== restoreGeometry ================// + +QRect KMdiChildFrm::restoreGeometry() const +{ + return m_restoredRect; +} + +//============== setRestoreGeometry ================// + +void KMdiChildFrm::setRestoreGeometry( const QRect& newRestGeo ) +{ + m_restoredRect = newRestGeo; +} + +//============ setCaption ===============// + +void KMdiChildFrm::setCaption( const QString& text ) +{ + m_pCaption->setCaption( text ); +} + +//============ enableClose ==============// + +void KMdiChildFrm::enableClose( bool bEnable ) +{ + m_pClose->setEnabled( bEnable ); + m_pClose->repaint( false ); +} + +//============ setIcon ==================// + +void KMdiChildFrm::setIcon( const QPixmap& pxm ) +{ + QPixmap p = pxm; + if ( p.width() != 18 || p.height() != 18 ) + { + QImage img = p.convertToImage(); + p = img.smoothScale( 18, 18, QImage::ScaleMin ); + } + const bool do_resize = m_pIconButtonPixmap->size() != p.size(); + *m_pIconButtonPixmap = p; + m_pWinIcon->setPixmap( p ); + m_pUnixIcon->setPixmap( p ); + if ( do_resize ) + doResize( true ); +} + +//============ icon =================// + +QPixmap* KMdiChildFrm::icon() const +{ + return m_pIconButtonPixmap; +} + +//============ setClient ============// +void KMdiChildFrm::setClient( KMdiChildView *w, bool bAutomaticResize ) +{ + m_pClient = w; + + if ( w->icon() ) + setIcon( *( w->icon() ) ); + + //resize to match the client + int clientYPos = m_pCaption->heightHint() + KMDI_CHILDFRM_SEPARATOR + KMDI_CHILDFRM_BORDER; + if ( bAutomaticResize || w->size().isEmpty() || ( w->size() == QSize( 1, 1 ) ) ) + { + if ( m_pManager->topChild() ) + { + resize( m_pManager->topChild() ->size() ); + } + else + { + resize( m_pManager->m_defaultChildFrmSize.width() + KMDI_CHILDFRM_DOUBLE_BORDER, + m_pManager->m_defaultChildFrmSize.height() + KMDI_CHILDFRM_BORDER + clientYPos ); + } + } + else + { + resize( w->width() + KMDI_CHILDFRM_DOUBLE_BORDER, w->height() + KMDI_CHILDFRM_BORDER + clientYPos ); + } + + // memorize the focuses in a dictionary because they will get lost during reparenting + QDict<FocusPolicy>* pFocPolDict = new QDict<FocusPolicy>; + pFocPolDict->setAutoDelete( true ); + QObjectList *list = m_pClient->queryList( "QWidget" ); + QObjectListIt it( *list ); // iterate over the buttons + QObject * obj; + int i = 1; + while ( ( obj = it.current() ) != 0 ) + { // for each found object... + ++it; + QWidget* widg = ( QWidget* ) obj; + if ( widg->name( 0 ) == 0 ) + { + QString tmpStr; + tmpStr.setNum( i ); + tmpStr = "unnamed" + tmpStr; + widg->setName( tmpStr.latin1() ); + i++; + } + FocusPolicy* pFocPol = new FocusPolicy; + *pFocPol = widg->focusPolicy(); + pFocPolDict->insert( widg->name(), pFocPol ); + } + delete list; // delete the list, not the objects + + //Reparent if needed + if ( w->parent() != this ) + { + //reparent to this widget , no flags , point , show it + QPoint pnt2( KMDI_CHILDFRM_BORDER, clientYPos ); + QSize mincs = w->minimumSize(); + QSize maxcs = w->maximumSize(); + w->setMinimumSize( 0, 0 ); + w->setMaximumSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX ); + + // min/max sizes, flags, DND get lost. :-( + w->reparent( this, 0, pnt2, w->isVisible() ); + + w->setMinimumSize( mincs.width(), mincs.height() ); + w->setMaximumSize( maxcs.width(), maxcs.height() ); + } + else + w->move( KMDI_CHILDFRM_BORDER, clientYPos ); + + linkChildren( pFocPolDict ); + + QObject::connect( m_pClient, SIGNAL( mdiParentNowMaximized( bool ) ), m_pManager, SIGNAL( nowMaximized( bool ) ) ); + + if ( m_pClient->minimumWidth() > m_pManager->m_defaultChildFrmSize.width() ) + setMinimumWidth( m_pClient->minimumSize().width() + KMDI_CHILDFRM_DOUBLE_BORDER ); + + if ( m_pClient->minimumHeight() > m_pManager->m_defaultChildFrmSize.height() ) + { + setMinimumHeight( m_pClient->minimumSize().height() + KMDI_CHILDFRM_DOUBLE_BORDER + + m_pCaption->heightHint() + KMDI_CHILDFRM_SEPARATOR ); + } +} + +//============ unsetClient ============// + +void KMdiChildFrm::unsetClient( QPoint positionOffset ) +{ + if ( !m_pClient ) + return ; + + QObject::disconnect( m_pClient, SIGNAL( mdiParentNowMaximized( bool ) ), m_pManager, SIGNAL( nowMaximized( bool ) ) ); + + //reparent to desktop widget , no flags , point , show it + QDict<FocusPolicy>* pFocPolDict; + pFocPolDict = unlinkChildren(); + + // get name of focused child widget + QWidget* focusedChildWidget = m_pClient->focusedChildWidget(); + const char* nameOfFocusedWidget = ""; + if ( focusedChildWidget != 0 ) + nameOfFocusedWidget = focusedChildWidget->name(); + + QSize mins = m_pClient->minimumSize(); + QSize maxs = m_pClient->maximumSize(); + m_pClient->reparent( 0, 0, mapToGlobal( pos() ) - pos() + positionOffset, isVisible() ); + m_pClient->setMinimumSize( mins.width(), mins.height() ); + m_pClient->setMaximumSize( maxs.width(), maxs.height() ); + + // remember the focus policies using the dictionary and reset them + QObjectList *list = m_pClient->queryList( "QWidget" ); + QObjectListIt it( *list ); // iterate over all child widgets of child frame + QObject * obj; + QWidget* firstFocusableChildWidget = 0; + QWidget* lastFocusableChildWidget = 0; + while ( ( obj = it.current() ) != 0 ) + { // for each found object... + QWidget * widg = ( QWidget* ) obj; + ++it; + FocusPolicy* pFocPol = pFocPolDict->find( widg->name() ); // remember the focus policy from before the reparent + if ( pFocPol ) + widg->setFocusPolicy( *pFocPol ); + + // reset focus to old position (doesn't work :-( for its own unexplicable reasons) + if ( widg->name() == nameOfFocusedWidget ) + widg->setFocus(); + + // get first and last focusable widget + if ( ( widg->focusPolicy() == QWidget::StrongFocus ) || ( widg->focusPolicy() == QWidget::TabFocus ) ) + { + if ( firstFocusableChildWidget == 0 ) + firstFocusableChildWidget = widg; // first widget + lastFocusableChildWidget = widg; // last widget + + } + else + { + if ( widg->focusPolicy() == QWidget::WheelFocus ) + { + if ( firstFocusableChildWidget == 0 ) + firstFocusableChildWidget = widg; // first widget + lastFocusableChildWidget = widg; // last widget + //qDebug("*** %s (%s)",widg->name(),widg->className()); + } + } + } + delete list; // delete the list, not the objects + delete pFocPolDict; + + // reset first and last focusable widget + m_pClient->setFirstFocusableChildWidget( firstFocusableChildWidget ); + m_pClient->setLastFocusableChildWidget( lastFocusableChildWidget ); + + // reset the focus policy of the view + m_pClient->setFocusPolicy( QWidget::ClickFocus ); + + // lose information about the view (because it's undocked now) + m_pClient = 0; +} + +//============== linkChildren =============// +void KMdiChildFrm::linkChildren( QDict<FocusPolicy>* pFocPolDict ) +{ + // reset the focus policies for all widgets in the view (take them from the dictionary) + QObjectList* list = m_pClient->queryList( "QWidget" ); + QObjectListIt it( *list ); // iterate over all child widgets of child frame + QObject* obj; + while ( ( obj = it.current() ) != 0 ) + { // for each found object... + QWidget* widg = ( QWidget* ) obj; + ++it; + FocusPolicy* pFocPol = pFocPolDict->find( widg->name() ); // remember the focus policy from before the reparent + + if ( pFocPol != 0 ) + widg->setFocusPolicy( *pFocPol ); + + if ( !( widg->inherits( "QPopupMenu" ) ) ) + widg->installEventFilter( this ); + + } + delete list; // delete the list, not the objects + delete pFocPolDict; + + // reset the focus policies for the rest + m_pWinIcon->setFocusPolicy( QWidget::NoFocus ); + m_pUnixIcon->setFocusPolicy( QWidget::NoFocus ); + m_pClient->setFocusPolicy( QWidget::ClickFocus ); + m_pCaption->setFocusPolicy( QWidget::NoFocus ); + m_pUndock->setFocusPolicy( QWidget::NoFocus ); + m_pMinimize->setFocusPolicy( QWidget::NoFocus ); + m_pMaximize->setFocusPolicy( QWidget::NoFocus ); + m_pClose->setFocusPolicy( QWidget::NoFocus ); + + // install the event filter (catch mouse clicks) for the rest + m_pWinIcon->installEventFilter( this ); + m_pUnixIcon->installEventFilter( this ); + m_pCaption->installEventFilter( this ); + m_pUndock->installEventFilter( this ); + m_pMinimize->installEventFilter( this ); + m_pMaximize->installEventFilter( this ); + m_pClose->installEventFilter( this ); + m_pClient->installEventFilter( this ); + // m_pClient->installEventFilterForAllChildren(); +} + +//============== unlinkChildren =============// + +QDict<QWidget::FocusPolicy>* KMdiChildFrm::unlinkChildren() +{ + // memorize the focuses in a dictionary because they will get lost during reparenting + QDict<FocusPolicy>* pFocPolDict = new QDict<FocusPolicy>; + pFocPolDict->setAutoDelete( true ); + + QObjectList *list = m_pClient->queryList( "QWidget" ); + QObjectListIt it( *list ); // iterate over all child widgets of child frame + QObject * obj; + int i = 1; + while ( ( obj = it.current() ) != 0 ) + { // for each found object... + ++it; + QWidget* w = ( QWidget* ) obj; + // get current widget object name + if ( w->name( 0 ) == 0 ) + { + QString tmpStr; + tmpStr.setNum( i ); + tmpStr = "unnamed" + tmpStr; + w->setName( tmpStr.latin1() ); + i++; + } + FocusPolicy* pFocPol = new FocusPolicy; + *pFocPol = w->focusPolicy(); + // memorize focus policy + pFocPolDict->insert( w->name(), pFocPol ); + // remove event filter + ( ( QWidget* ) obj ) ->removeEventFilter( this ); + } + delete list; // delete the list, not the objects + + // remove the event filter (catch mouse clicks) for the rest + m_pWinIcon->removeEventFilter( this ); + m_pUnixIcon->removeEventFilter( this ); + m_pCaption->removeEventFilter( this ); + m_pUndock->removeEventFilter( this ); + m_pMinimize->removeEventFilter( this ); + m_pMaximize->removeEventFilter( this ); + m_pClose->removeEventFilter( this ); + m_pClient->removeEventFilter( this ); + + //SCHEDULED_FOR_REMOVE m_pClient->removeEventFilterForAllChildren(); + + return pFocPolDict; +} + +//============== resizeEvent ===============// + +void KMdiChildFrm::resizeEvent( QResizeEvent * ) +{ + doResize(); // an extra method because it can also called directly +} + +void KMdiChildFrm::doResize() +{ + doResize( false ); +} + +void KMdiChildFrm::doResize( bool captionOnly ) +{ + //Resize the caption + int captionHeight = m_pCaption->heightHint(); + int captionWidth = width() - KMDI_CHILDFRM_DOUBLE_BORDER; + int buttonHeight = m_pClose->pixmap() ->height(); + int buttonWidth = m_pClose->pixmap() ->width(); + int heightOffset = captionHeight / 2 - buttonHeight / 2; + int rightOffset1 = 1; + int rightOffset2 = 1; + int frmIconHeight = m_pWinIcon->pixmap() ->height(); + int frmIconWidth = m_pWinIcon->pixmap() ->width(); + int frmIconOffset = 1; + QWidget* pIconWidget = m_pWinIcon; + m_pCaption->setGeometry( KMDI_CHILDFRM_BORDER, KMDI_CHILDFRM_BORDER, captionWidth, captionHeight ); + + //The buttons are caption children + if ( KMdiMainFrm::frameDecorOfAttachedViews() == KMdi::Win95Look ) + { + rightOffset2 += 2; + m_pUnixIcon->hide(); + } + else if ( KMdiMainFrm::frameDecorOfAttachedViews() == KMdi::KDE1Look ) + { + buttonWidth += 4; + buttonHeight += 4; + heightOffset -= 2; + rightOffset1 = 0; + rightOffset2 = 0; + m_pWinIcon->hide(); + frmIconHeight = buttonHeight; + frmIconWidth = buttonWidth; + frmIconOffset = 0; + pIconWidget = m_pUnixIcon; + } + else if ( KMdiMainFrm::frameDecorOfAttachedViews() == KMdi::KDELook ) + { + buttonWidth += 3; + buttonHeight += 3; + heightOffset -= 1; + m_pUnixIcon->hide(); + } + if ( KMdiMainFrm::frameDecorOfAttachedViews() != KMdi::KDELaptopLook ) + { + pIconWidget->setGeometry( frmIconOffset, captionHeight / 2 - frmIconHeight / 2, frmIconWidth, frmIconHeight ); + m_pClose->setGeometry( ( captionWidth - buttonWidth ) - rightOffset1, heightOffset, buttonWidth, buttonHeight ); + m_pMaximize->setGeometry( ( captionWidth - ( buttonWidth * 2 ) ) - rightOffset2, heightOffset, buttonWidth, buttonHeight ); + m_pMinimize->setGeometry( ( captionWidth - ( buttonWidth * 3 ) ) - rightOffset2, heightOffset, buttonWidth, buttonHeight ); + m_pUndock->setGeometry( ( captionWidth - ( buttonWidth * 4 ) ) - rightOffset2, heightOffset, buttonWidth, buttonHeight ); + } + else + { // KDELaptopLook + m_pWinIcon->hide(); + m_pUnixIcon->hide(); + buttonHeight += 5; + heightOffset -= 2; + m_pClose->setGeometry ( 0, heightOffset, 27, buttonHeight ); + m_pMaximize->setGeometry( captionWidth - 27, heightOffset, 27, buttonHeight ); + m_pMinimize->setGeometry( captionWidth - 27 * 2, heightOffset, 27, buttonHeight ); + m_pUndock->setGeometry ( captionWidth - 27 * 3, heightOffset, 27, buttonHeight ); + } + + //Resize the client + if ( !captionOnly && m_pClient ) + { + QSize newClientSize( captionWidth, + height() - ( KMDI_CHILDFRM_DOUBLE_BORDER + captionHeight + KMDI_CHILDFRM_SEPARATOR ) ); + if ( newClientSize != m_pClient->size() ) + { + m_pClient->setGeometry( KMDI_CHILDFRM_BORDER, + m_pCaption->heightHint() + KMDI_CHILDFRM_SEPARATOR + KMDI_CHILDFRM_BORDER, + newClientSize.width(), newClientSize.height() ); + } + } +} + +static bool hasParent( QObject* par, QObject* o ) +{ + while ( o && o != par ) + o = o->parent(); + return o == par; +} + +//============= eventFilter ===============// + +bool KMdiChildFrm::eventFilter( QObject *obj, QEvent *e ) +{ + switch ( e->type() ) + { + case QEvent::Enter: + { + // check if the receiver is really a child of this frame + bool bIsChild = false; + QObject* pObj = obj; + while ( ( pObj != 0L ) && !bIsChild ) + { + bIsChild = ( pObj == this ); + pObj = pObj->parent(); + } + // unset the resize cursor if the cursor moved from the frame into a inner widget + if ( bIsChild ) + unsetResizeCursor(); + } + break; + case QEvent::MouseButtonPress: + { + if ( !hasParent( m_pClient, obj ) ) + { + bool bIsSecondClick = false; + if ( m_timeMeasure.elapsed() <= QApplication::doubleClickInterval() ) + bIsSecondClick = true; // of a possible double click + + if ( !( ( ( obj == m_pWinIcon ) || ( obj == m_pUnixIcon ) ) && bIsSecondClick ) ) + { + // in case we didn't click on the icon button + QFocusEvent* pFE = new QFocusEvent( QFocusEvent::FocusIn ); + QApplication::sendEvent( qApp->mainWidget(), pFE ); + if ( m_pClient ) + { + m_pClient->updateTimeStamp(); + m_pClient->activate(); + } + + if ( ( obj->parent() != m_pCaption ) && ( obj != m_pCaption ) ) + { + QWidget* w = ( QWidget* ) obj; + if ( ( w->focusPolicy() == QWidget::ClickFocus ) || ( w->focusPolicy() == QWidget::StrongFocus ) ) + { + w->setFocus(); + } + } + } + if ( ( obj == m_pWinIcon ) || ( obj == m_pUnixIcon ) ) + { + // in case we clicked on the icon button + if ( m_timeMeasure.elapsed() > QApplication::doubleClickInterval() ) + { + showSystemMenu(); + m_timeMeasure.start(); + } + else + closePressed(); // double click on icon button closes the view + + return true; + } + } + } + break; + case QEvent::Resize: + { + if ( ( ( QWidget* ) obj == m_pClient ) && ( m_state == Normal ) ) + { + QResizeEvent* re = ( QResizeEvent* ) e; + int captionHeight = m_pCaption->heightHint(); + QSize newChildFrmSize( re->size().width() + KMDI_CHILDFRM_DOUBLE_BORDER, + re->size().height() + captionHeight + KMDI_CHILDFRM_SEPARATOR + KMDI_CHILDFRM_DOUBLE_BORDER ); + if ( newChildFrmSize != size() ) + resize( newChildFrmSize ); + } + } + break; + case QEvent::ChildRemoved: + { + // if we lost a child we uninstall ourself as event filter for the lost + // child and its children + QObject* pLostChild = ( ( QChildEvent* ) e )->child(); + if ( ( pLostChild != 0L ) /*&& (pLostChild->inherits("QWidget"))*/ ) + { + QObjectList* list = pLostChild->queryList(); + list->insert( 0, pLostChild ); // add the lost child to the list too, just to save code + QObjectListIt it( *list ); // iterate over all lost child widgets + QObject* obj; + while ( ( obj = it.current() ) != 0 ) + { // for each found object... + QWidget* widg = ( QWidget* ) obj; + ++it; + widg->removeEventFilter( this ); + } + delete list; // delete the list, not the objects + } + } + break; + case QEvent::ChildInserted: + { + // if we got a new child we install ourself as event filter for the new + // child and its children (as we did when we got our client). + // XXX see linkChildren() and focus policy stuff + QObject* pNewChild = ( ( QChildEvent* ) e ) ->child(); + if ( ( pNewChild != 0L ) && ::qt_cast<QWidget*>( pNewChild ) ) + { + QWidget * pNewWidget = static_cast<QWidget*>( pNewChild ); + QObjectList *list = pNewWidget->queryList( "QWidget" ); + list->insert( 0, pNewChild ); // add the new child to the list too, just to save code + QObjectListIt it( *list ); // iterate over all new child widgets + QObject * obj; + while ( ( obj = it.current() ) != 0 ) + { // for each found object... + QWidget * widg = ( QWidget* ) obj; + ++it; + if ( !::qt_cast<QPopupMenu*>( widg ) ) + { + widg->installEventFilter( this ); + } + } + delete list; // delete the list, not the objects + } + } + break; + default: + break; + } + + return false; // standard event processing (see Qt documentation) +} + +//============= raiseAndActivate ===============// + +void KMdiChildFrm::raiseAndActivate() +{ + m_pCaption->setActive( true ); + m_pManager->setTopChild( this, false ); //Do not focus by now... +} + +//============= setMinimumSize ===============// + +void KMdiChildFrm::setMinimumSize ( int minw, int minh ) +{ + QWidget::setMinimumSize( minw, minh ); + if ( m_state == Maximized ) + { + m_pManager->setMinimumSize( minw, minh ); + } +} + +//============= systemMenu ===============// + +QPopupMenu* KMdiChildFrm::systemMenu() const +{ + if ( m_pSystemMenu == 0 ) + return 0; + + m_pSystemMenu->clear(); + + if ( KMdiMainFrm::frameDecorOfAttachedViews() != KMdi::Win95Look ) + { + m_pSystemMenu->insertItem( i18n( "&Restore" ), this, SLOT( restorePressed() ) ); + m_pSystemMenu->insertItem( i18n( "&Move" ), m_pCaption, SLOT( slot_moveViaSystemMenu() ) ); + m_pSystemMenu->insertItem( i18n( "R&esize" ), this, SLOT( slot_resizeViaSystemMenu() ) ); + m_pSystemMenu->insertItem( i18n( "M&inimize" ), this, SLOT( minimizePressed() ) ); + m_pSystemMenu->insertItem( i18n( "M&aximize" ), this, SLOT( maximizePressed() ) ); + if ( state() == Normal ) + m_pSystemMenu->setItemEnabled( m_pSystemMenu->idAt( 0 ), false ); + else if ( state() == Maximized ) + { + m_pSystemMenu->setItemEnabled( m_pSystemMenu->idAt( 1 ), false ); + m_pSystemMenu->setItemEnabled( m_pSystemMenu->idAt( 2 ), false ); + m_pSystemMenu->setItemEnabled( m_pSystemMenu->idAt( 4 ), false ); + } + else if ( state() == Minimized ) + { + m_pSystemMenu->setItemEnabled( m_pSystemMenu->idAt( 2 ), false ); + m_pSystemMenu->setItemEnabled( m_pSystemMenu->idAt( 3 ), false ); + } + } + else + { + if ( state() != Normal ) + m_pSystemMenu->insertItem( i18n( "&Restore" ), this, SLOT( restorePressed() ) ); + if ( state() != Maximized ) + m_pSystemMenu->insertItem( i18n( "&Maximize" ), this, SLOT( maximizePressed() ) ); + if ( state() != Minimized ) + m_pSystemMenu->insertItem( i18n( "&Minimize" ), this, SLOT( minimizePressed() ) ); + if ( state() != Maximized ) + m_pSystemMenu->insertItem( i18n( "M&ove" ), m_pCaption, SLOT( slot_moveViaSystemMenu() ) ); + if ( state() == Normal ) + m_pSystemMenu->insertItem( i18n( "&Resize" ), this, SLOT( slot_resizeViaSystemMenu() ) ); + } + + m_pSystemMenu->insertItem( i18n( "&Undock" ), this, SLOT( undockPressed() ) ); + m_pSystemMenu->insertSeparator(); + m_pSystemMenu->insertItem( i18n( "&Close" ), this, SLOT( closePressed() ) ); + + return m_pSystemMenu; +} + +/** Shows a system menu for child frame windows. */ +void KMdiChildFrm::showSystemMenu() +{ + if ( KMdiMainFrm::frameDecorOfAttachedViews() != KMdi::Win95Look ) + m_pUnixIcon->setDown( false ); + + QPoint popupmenuPosition; + + QRect iconGeom; + if ( KMdiMainFrm::frameDecorOfAttachedViews() == KMdi::Win95Look ) + iconGeom = m_pWinIcon->geometry(); + else + iconGeom = m_pUnixIcon->geometry(); + + popupmenuPosition = QPoint( iconGeom.x(), iconGeom.y() + captionHeight() + KMDI_CHILDFRM_BORDER ); + systemMenu() ->popup( mapToGlobal( popupmenuPosition ) ); +} + +void KMdiChildFrm::switchToMinimizeLayout() +{ + setMinimumWidth( KMDI_CHILDFRM_MIN_WIDTH ); + setFixedHeight( m_pCaption->height() + KMDI_CHILDFRM_DOUBLE_BORDER ); + + m_pMaximize->setPixmap( *m_pMaxButtonPixmap ); + + // temporary use of minimize button for restore function + m_pMinimize->setPixmap( *m_pRestoreButtonPixmap ); + QObject::disconnect( m_pMinimize, SIGNAL( clicked() ), this, SLOT( minimizePressed() ) ); + QObject::connect( m_pMinimize, SIGNAL( clicked() ), this, SLOT( restorePressed() ) ); + + // resizing + resize( 300, minimumHeight() ); + + // positioning + m_pManager->layoutMinimizedChildren(); +} + +void KMdiChildFrm::slot_resizeViaSystemMenu() +{ + grabMouse(); + m_bResizing = true; + m_iResizeCorner = KMDI_RESIZE_BOTTOMLEFT; + setResizeCursor( m_iResizeCorner ); +} + +void KMdiChildFrm::redecorateButtons() +{ + delete m_pMinButtonPixmap; + delete m_pMaxButtonPixmap; + delete m_pRestoreButtonPixmap; + delete m_pCloseButtonPixmap; + delete m_pUndockButtonPixmap; + + if ( KMdiMainFrm::frameDecorOfAttachedViews() == KMdi::Win95Look ) + { + m_pMinButtonPixmap = new QPixmap( win_minbutton ); + m_pMaxButtonPixmap = new QPixmap( win_maxbutton ); + m_pRestoreButtonPixmap = new QPixmap( win_restorebutton ); + m_pCloseButtonPixmap = new QPixmap( win_closebutton ); + m_pUndockButtonPixmap = new QPixmap( win_undockbutton ); + } + else if ( KMdiMainFrm::frameDecorOfAttachedViews() == KMdi::KDE1Look ) + { + m_pMinButtonPixmap = new QPixmap( kde_minbutton ); + m_pMaxButtonPixmap = new QPixmap( kde_maxbutton ); + m_pRestoreButtonPixmap = new QPixmap( kde_restorebutton ); + m_pCloseButtonPixmap = new QPixmap( kde_closebutton ); + m_pUndockButtonPixmap = new QPixmap( kde_undockbutton ); + } + else if ( KMdiMainFrm::frameDecorOfAttachedViews() == KMdi::KDELook ) + { + m_pMinButtonPixmap = new QPixmap( kde2_minbutton ); + m_pMaxButtonPixmap = new QPixmap( kde2_maxbutton ); + m_pRestoreButtonPixmap = new QPixmap( kde2_restorebutton ); + m_pCloseButtonPixmap = new QPixmap( kde2_closebutton ); + m_pUndockButtonPixmap = new QPixmap( kde2_undockbutton ); + } + else + { // kde2laptop look + m_pMinButtonPixmap = new QPixmap( kde2laptop_minbutton ); + m_pMaxButtonPixmap = new QPixmap( kde2laptop_maxbutton ); + m_pRestoreButtonPixmap = new QPixmap( kde2laptop_restorebutton ); + m_pCloseButtonPixmap = new QPixmap( kde2laptop_closebutton ); + m_pUndockButtonPixmap = new QPixmap( kde2laptop_undockbutton ); + } + + m_pUnixIcon->setAutoRaise( true ); + if ( KMdiMainFrm::frameDecorOfAttachedViews() == KMdi::KDE1Look ) + { + m_pMinimize->setAutoRaise( true ); + m_pMaximize->setAutoRaise( true ); + m_pClose->setAutoRaise( true ); + m_pUndock->setAutoRaise( true ); + } + else + { + m_pMinimize->setAutoRaise( false ); + m_pMaximize->setAutoRaise( false ); + m_pClose->setAutoRaise( false ); + m_pUndock->setAutoRaise( false ); + } + + if ( m_pClient && m_pClient->icon() ) + { + m_pWinIcon->setPixmap( *( m_pClient )->icon() ); + m_pUnixIcon->setPixmap( *( m_pClient )->icon() ); + } + else + { + m_pWinIcon->setPixmap( *m_pIconButtonPixmap ); + m_pUnixIcon->setPixmap( *m_pIconButtonPixmap ); + } + m_pClose->setPixmap( *m_pCloseButtonPixmap ); + m_pMinimize->setPixmap( *m_pMinButtonPixmap ); + m_pMaximize->setPixmap( *m_pMaxButtonPixmap ); + m_pUndock->setPixmap( *m_pUndockButtonPixmap ); +} + +QRect KMdiChildFrm::mdiAreaContentsRect() const +{ + QFrame * p = ( QFrame* ) parentWidget(); + if ( p ) + { + return p->contentsRect(); + } + else + { + QRect empty; + return empty; + } +} + +// kate: indent-mode csands; tab-width 4; space-indent off; replace-tabs off; diff --git a/lib/compatibility/kmdi/qextmdi/kmdichildfrm.h b/lib/compatibility/kmdi/qextmdi/kmdichildfrm.h new file mode 100644 index 00000000..58959a42 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmdichildfrm.h @@ -0,0 +1,446 @@ +//---------------------------------------------------------------------------- +// filename : kmdichildfrm.h +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 07/1999 by Szymon Stefanek as part of kvirc +// (an IRC application) +// changes : 09/1999 by Falk Brettschneider to create an +// - 06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// 2000-2003 maintained by the KDevelop project +// patches : */2000 Lars Beikirch (Lars.Beikirch@gmx.net) +// +// copyright : (C) 1999-2003 by Falk Brettschneider +// and +// Szymon Stefanek (stefanek@tin.it) +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program 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. +// +//------------------------------------------------------------------------------ +#ifndef _KMDI_CHILD_FRM_H_ +#define _KMDI_CHILD_FRM_H_ + +#include <qptrlist.h> +#include <qpixmap.h> +#include <qpushbutton.h> +#include <qlabel.h> +#include <qdatetime.h> +#include <qlayout.h> + +#include <qdict.h> + +#include "kmdichildfrmcaption.h" + +class KMdiChildArea; +class KMdiChildView; +class QPopupMenu; +class QToolButton; + +//============================================================================== +/** + * @short Internal class, only used on Win32. + * This class provides a label widget that can process mouse click events. + */ +class KMDI_EXPORT KMdiWin32IconButton : public QLabel +{ + Q_OBJECT +public: + KMdiWin32IconButton( QWidget* parent, const char* name = 0 ); + virtual void mousePressEvent( QMouseEvent* ); + +signals: + void pressed(); +}; + +//============================================================================== +/* some special events, see kmdidefines.h +*/ +//------------------------------------------------------------------------------ +/** + * @short a QCustomEvent for move + * This special event will be useful, to inform view about child frame event. + */ +class KMDI_EXPORT KMdiChildFrmMoveEvent : public QCustomEvent +{ +public: + KMdiChildFrmMoveEvent( QMoveEvent *e ) : QCustomEvent( QEvent::Type( QEvent::User + int( KMdi::EV_Move ) ), e ) {} + +}; + +//------------------------------------------------------------------------------ +/** + * @short a QCustomEvent for begin of dragging + * This special event will be useful, to inform view about child frame event. + */ +class KMDI_EXPORT KMdiChildFrmDragBeginEvent : public QCustomEvent +{ +public: + KMdiChildFrmDragBeginEvent( QMouseEvent *e ) : QCustomEvent( QEvent::Type( QEvent::User + int( KMdi::EV_DragBegin ) ), e ) {} +}; + +//------------------------------------------------------------------------------ +/** + * @short a QCustomEvent for end of dragging + * This special event will be useful, to inform view about child frame event. + */ +class KMDI_EXPORT KMdiChildFrmDragEndEvent : public QCustomEvent +{ +public: + KMdiChildFrmDragEndEvent( QMouseEvent *e ) : QCustomEvent( QEvent::Type( QEvent::User + int( KMdi::EV_DragEnd ) ), e ) {} +}; + +//------------------------------------------------------------------------------ +/** + * @short a QCustomEvent for begin of resizing + * This special event will be useful, to inform view about child frame event. + */ +class KMDI_EXPORT KMdiChildFrmResizeBeginEvent : public QCustomEvent +{ +public: + KMdiChildFrmResizeBeginEvent( QMouseEvent *e ) : QCustomEvent( QEvent::Type( QEvent::User + int( KMdi::EV_ResizeBegin ) ), e ) {} +}; + +//------------------------------------------------------------------------------ +/** + * @short a QCustomEvent for end of resizing + * This special event will be useful, to inform view about child frame event. + */ +class KMDI_EXPORT KMdiChildFrmResizeEndEvent : public QCustomEvent +{ +public: + KMdiChildFrmResizeEndEvent( QMouseEvent *e ) : QCustomEvent( QEvent::Type( QEvent::User + int( KMdi::EV_ResizeEnd ) ), e ) {} +}; + + +class KMdiChildFrmPrivate; +//============================================================================== +/** + * @short Internal class. + * It's an MDI child frame widget. It contains a view widget and a frame caption. Usually you derive from its view. + */ +//------------------------------------------------------------------------------ +class KMDI_EXPORT KMdiChildFrm : public QFrame +{ + friend class KMdiChildArea; + friend class KMdiChildFrmCaption; + + Q_OBJECT + + // attributes +public: + enum MdiWindowState { Normal, Maximized, Minimized }; + //positions same in h and cpp for fast order check + KMdiChildView* m_pClient; + +protected: + KMdiChildArea* m_pManager; + KMdiChildFrmCaption* m_pCaption; + KMdiWin32IconButton* m_pWinIcon; + QToolButton* m_pUnixIcon; + QToolButton* m_pMinimize; + QToolButton* m_pMaximize; + QToolButton* m_pClose; + QToolButton* m_pUndock; + MdiWindowState m_state; + QRect m_restoredRect; + int m_iResizeCorner; + int m_iLastCursorCorner; + bool m_bResizing; + bool m_bDragging; + QPixmap* m_pIconButtonPixmap; + QPixmap* m_pMinButtonPixmap; + QPixmap* m_pMaxButtonPixmap; + QPixmap* m_pRestoreButtonPixmap; + QPixmap* m_pCloseButtonPixmap; + QPixmap* m_pUndockButtonPixmap; + + /** + * Every child frame window has an temporary ID in the Window menu of the child area. + */ + int m_windowMenuID; + + /** + * Imitates a system menu for child frame windows + */ + QPopupMenu* m_pSystemMenu; + + QSize m_oldClientMinSize; + QSize m_oldClientMaxSize; + QLayout::ResizeMode m_oldLayoutResizeMode; + QTime m_timeMeasure; + + // methods +public: + + /** + * Creates a new KMdiChildFrm class. + */ + KMdiChildFrm( KMdiChildArea *parent ); + + /** + * Destroys this KMdiChildFrm + * If a child is still here managed (no recreation was made) it is destroyed too. + */ + ~KMdiChildFrm(); + + /** + * Reparents the widget w to this KMdiChildFrm (if this is not already done) + * Installs an event filter to catch focus events. + * Resizes this mdi child in a way that the child fits perfectly in. + */ + void setClient( KMdiChildView *w, bool bAutomaticResize = false ); + + /** + * Reparents the client widget to 0 (desktop), moves with an offset from the original position + * Removes the event filter. + */ + void unsetClient( QPoint positionOffset = QPoint( 0, 0 ) ); + + /** + * Sets the window icon pointer. + */ + void setIcon( const QPixmap &pxm ); + + /** + * Returns the child frame icon. + */ + QPixmap* icon() const; + + /** + * Enables or disables the close button + */ + void enableClose( bool bEnable ); + + /** + * Sets the caption of this window + */ + void setCaption( const QString& text ); + + /** + * Gets the caption of this mdi child. + */ + const QString& caption() { return m_pCaption->m_szCaption; } + + /** + * Minimizes, Maximizes, or restores the window. + */ + void setState( MdiWindowState state, bool bAnimate = true ); + + /** + * Returns the current state of the window + */ + inline MdiWindowState state() const { return m_state; } + + /** + * Returns the inner client area of the parent of this (which is KMdiChildArea). + */ + QRect mdiAreaContentsRect() const; + + /** + * Returns the geometry that will be restored by calling restore(). + */ + QRect restoreGeometry() const; + + /** + * Sets the geometry that will be restored by calling restore(). + */ + void setRestoreGeometry( const QRect& newRestGeo ); + + /** + * Forces updating the rects of the caption and so... + * It may be useful when setting the mdiCaptionFont of the MdiManager + */ + void updateRects() { resizeEvent( 0 ); } + + /** + * Returns the system menu. + */ + QPopupMenu* systemMenu() const; + + /** + * Returns the caption bar height + */ + inline int captionHeight() const { return m_pCaption->height(); } + + /** + * sets new raise behavior and pixmaps of the buttons depending on the current decoration style + */ + void redecorateButtons(); + + /** + * returns the mouse state "In Drag" + */ + bool isInDrag() const { return m_bDragging; } + + /** + * returns the mouse state "In Resize" + */ + bool isInResize() const { return m_bResizing; } + + /** + * Internally called from the signal focusInEventOccurs. + * It raises the MDI childframe to the top of all other MDI child frames and sets the focus on it. + */ + void raiseAndActivate(); + + /** + * Sets the minimum size of the widget to w by h pixels. + * It extends it's base clase method in a way that the minimum size of + * the child area will be set additionally if the view is maximized. + */ + virtual void setMinimumSize ( int minw, int minh ); + +public slots: + + void slot_resizeViaSystemMenu(); + +protected: + + /** + * Reimplemented from the base class. + * Resizes the captionbar, relayouts the position of the system buttons, + * and calls resize for its embedded KMdiChildView with the proper size + */ + virtual void resizeEvent( QResizeEvent * ); + + /** + * Reimplemented from the base class. + * Detects if the mouse is on the edge of window and what resize cursor must be set. + * Calls KMdiChildFrm::resizeWindow if it is in m_bResizing. + */ + virtual void mouseMoveEvent( QMouseEvent *e ); + + /** + * Reimplemented from the base class. + * Colours the caption, raises the childfrm widget and + * turns to resize mode if it is on the edge (resize-sensitive area) + */ + virtual void mousePressEvent( QMouseEvent *e ); + + /** + * Reimplemented from the base class. + * Sets a normal cursor and leaves the resize mode. + */ + virtual void mouseReleaseEvent( QMouseEvent * ); + + /** + * Reimplemented from the base class. + * give its child view the chance to notify a childframe move... that's why it sends + * a KMdiChildMovedEvent to the embedded KMdiChildView . + */ + virtual void moveEvent( QMoveEvent* me ); + + /** + * Reimplemented from the base class. If not in resize mode, it sets the mouse cursor to normal appearance. + */ + virtual void leaveEvent( QEvent * ); + + /** + * Reimplemented from the base class. + * In addition, the following are caught + * -the client's mousebutton press events which raises and activates the childframe + * -the client's resize event which resizes this widget as well + */ + virtual bool eventFilter( QObject*, QEvent* ); + + /** + * Calculates the new geometry from the new mouse position given as parameters + * and calls KMdiChildFrm::setGeometry + */ + void resizeWindow( int resizeCorner, int x, int y ); + + /** + * Override the cursor appearance depending on the widget corner given as parameter + */ + void setResizeCursor( int resizeCorner ); + + /** + * Changes from the resize cursor to the normal (previous) cursor + */ + void unsetResizeCursor(); + + /** + * That means to show a mini window showing the childframe's caption bar, only. + * It cannot be resized. + */ + virtual void switchToMinimizeLayout(); + + /** + * Does the actual resize. Called from various places but from resizeEvent in general. + */ + void doResize(); + + /** + * Does the actual resize, like doResize() but skips resize of the client if \a captionOnly is true. + * @todo: merge with doResize() + */ + void doResize( bool captionOnly ); + +protected slots: + + /** + * Handles a click on the Maximize button + */ + void maximizePressed(); + + /** + * Handles a click on the Restore (Normalize) button + */ + void restorePressed(); + + /** + * Handles a click on the Minimize button. + */ + void minimizePressed(); + + /** + * Handles a click on the Close button. + */ + void closePressed(); + + /** + * Handles a click on the Undock (Detach) button + */ + void undockPressed(); + + /** + * Shows a system menu for child frame windows. + */ + void showSystemMenu(); + +protected: + + /** + * Restore the focus policies for _all_ widgets in the view using the list given as parameter. + * Install the event filter for all direct child widgets of this. (See KMdiChildFrm::eventFilter) + */ + void linkChildren( QDict<FocusPolicy>* pFocPolDict ); + + /** + * Backups all focus policies of _all_ child widgets in the MDI childview since they get lost during a reparent. + * Remove all event filters for all direct child widgets of this. (See KMdiChildFrm::eventFilter) + */ + QDict<QWidget::FocusPolicy>* unlinkChildren(); + + /** + * Calculates the corner id for the resize cursor. The return value can be tested for: + * KMDI_RESIZE_LEFT, KMDI_RESIZE_RIGHT, KMDI_RESIZE_TOP, KMDI_RESIZE_BOTTOM + * or an OR'd variant of them for the corners. + */ + int getResizeCorner( int ax, int ay ); + +private: + KMdiChildFrmPrivate *d; +}; + +#endif //_KMDICHILDFRM_H_ + +// kate: space-indent off; replace-tabs off; tab-width 4; indent-mode csands; diff --git a/lib/compatibility/kmdi/qextmdi/kmdichildfrmcaption.cpp b/lib/compatibility/kmdi/qextmdi/kmdichildfrmcaption.cpp new file mode 100644 index 00000000..815d07d4 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmdichildfrmcaption.cpp @@ -0,0 +1,322 @@ +//---------------------------------------------------------------------------- +// filename : kmdichildfrmcaption.cpp +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 07/1999 by Szymon Stefanek as part of kvirc +// (an IRC application) +// changes : 09/1999 by Falk Brettschneider to create an +// - 06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// 2000-2003 maintained by the KDevelop project +// +// copyright : (C) 1999-2003 by Szymon Stefanek (stefanek@tin.it) +// and +// Falk Brettschneider +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program 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. +// +//---------------------------------------------------------------------------- + +#include "kmdichildfrmcaption.h" +#include "kmdichildfrmcaption.moc" + +#include <qpainter.h> +#include <qapplication.h> +#include <qcursor.h> +#include <qtoolbutton.h> +#include <qpopupmenu.h> + +#include "kmdidefines.h" +#include "kmdichildfrm.h" +#include "kmdichildarea.h" +#include "kmdimainfrm.h" +#include <klocale.h> +#include <iostream> + +#ifdef Q_WS_WIN +//TODO: one day gradient can be added for win98/winnt5+ +// ask system properties on windows +#ifndef SPI_GETGRADIENTCAPTIONS +# define SPI_GETGRADIENTCAPTIONS 0x1008 +#endif +#ifndef COLOR_GRADIENTACTIVECAPTION +# define COLOR_GRADIENTACTIVECAPTION 27 +#endif +#ifndef COLOR_GRADIENTINACTIVECAPTION +# define COLOR_GRADIENTINACTIVECAPTION 28 +#endif +#endif +//#endif + +////////////////////////////////////////////////////////////////////////////// +// Class : KMdiChildFrmCaption +// Purpose : An MDI label that draws the title +// +// +////////////////////////////////////////////////////////////////////////////// + +//============== KMdiChildFrmCaption =============// + +KMdiChildFrmCaption::KMdiChildFrmCaption( KMdiChildFrm *parent ) + : QWidget( parent, "kmdi_childfrmcaption" ) +{ + m_szCaption = i18n( "Unnamed" ); + m_bActive = false; + m_pParent = parent; + setBackgroundMode( NoBackground ); + setFocusPolicy( NoFocus ); + m_bChildInDrag = false; +} + +//============== ~KMdiChildFrmCaption =============// + +KMdiChildFrmCaption::~KMdiChildFrmCaption() +{} + +//============= mousePressEvent ==============// + +void KMdiChildFrmCaption::mousePressEvent( QMouseEvent *e ) +{ + if ( e->button() == LeftButton ) + { + setMouseTracking( false ); + if ( KMdiMainFrm::frameDecorOfAttachedViews() != KMdi::Win95Look ) + { + QApplication::setOverrideCursor( Qt::sizeAllCursor, true ); + } + m_pParent->m_bDragging = true; + m_offset = mapToParent( e->pos() ); + } + else if ( e->button() == RightButton ) + { + m_pParent->systemMenu()->popup( mapToGlobal( e->pos() ) ); + } +} + +//============= mouseReleaseEvent ============// + +void KMdiChildFrmCaption::mouseReleaseEvent( QMouseEvent *e ) +{ + if ( e->button() == LeftButton ) + { + if ( KMdiMainFrm::frameDecorOfAttachedViews() != KMdi::Win95Look ) + QApplication::restoreOverrideCursor(); + + releaseMouse(); + if ( m_pParent->m_bDragging ) + { + m_pParent->m_bDragging = false; + if ( m_bChildInDrag ) + { + //notify child view + KMdiChildFrmDragEndEvent ue( e ); + if ( m_pParent->m_pClient != 0L ) + QApplication::sendEvent( m_pParent->m_pClient, &ue ); + + m_bChildInDrag = false; + } + } + } +} + +//============== mouseMoveEvent =============// +void KMdiChildFrmCaption::mouseMoveEvent( QMouseEvent *e ) +{ + if ( !m_pParent->m_bDragging ) + return ; + + if ( !m_bChildInDrag ) + { + //notify child view + KMdiChildFrmDragBeginEvent ue( e ); + if ( m_pParent->m_pClient != 0L ) + QApplication::sendEvent( m_pParent->m_pClient, &ue ); + + m_bChildInDrag = true; + } + + QPoint relMousePosInChildArea = m_pParent->m_pManager->mapFromGlobal( e->globalPos() ); + + // mouse out of child area? stop child frame dragging + if ( !m_pParent->m_pManager->rect().contains( relMousePosInChildArea ) ) + { + if ( relMousePosInChildArea.x() < 0 ) + relMousePosInChildArea.rx() = 0; + + if ( relMousePosInChildArea.y() < 0 ) + relMousePosInChildArea.ry() = 0; + + if ( relMousePosInChildArea.x() > m_pParent->m_pManager->width() ) + relMousePosInChildArea.rx() = m_pParent->m_pManager->width(); + + if ( relMousePosInChildArea.y() > m_pParent->m_pManager->height() ) + relMousePosInChildArea.ry() = m_pParent->m_pManager->height(); + } + QPoint mousePosInChildArea = relMousePosInChildArea - m_offset; + + // set new child frame position + parentWidget() ->move( mousePosInChildArea ); +} + +//=============== setActive ===============// + +void KMdiChildFrmCaption::setActive( bool bActive ) +{ + if ( m_bActive == bActive ) + return ; + + // Ensure the icon's pixmap has the correct bg color + m_pParent->m_pWinIcon->setBackgroundColor( bActive ? + m_pParent->m_pManager->m_captionActiveBackColor : + m_pParent->m_pManager->m_captionInactiveBackColor ); + m_pParent->m_pUnixIcon->setBackgroundColor( bActive ? + m_pParent->m_pManager->m_captionActiveBackColor : + m_pParent->m_pManager->m_captionInactiveBackColor ); + + m_bActive = bActive; + repaint( false ); +} + +//=============== setCaption ===============// + +void KMdiChildFrmCaption::setCaption( const QString& text ) +{ + m_szCaption = text; + repaint( false ); +} + +//============== heightHint ===============// + +int KMdiChildFrmCaption::heightHint() +{ + int hint = m_pParent->m_pManager->m_captionFontLineSpacing + 3; + if ( KMdiMainFrm::frameDecorOfAttachedViews() == KMdi::Win95Look ) + { + if ( hint < 18 ) + hint = 18; + } + else if ( KMdiMainFrm::frameDecorOfAttachedViews() == KMdi::KDE1Look ) + { + if ( hint < 20 ) + hint = 20; + } + else if ( KMdiMainFrm::frameDecorOfAttachedViews() == KMdi::KDELook ) + { + if ( hint < 16 ) + hint = 16; + } + else + { // kde2laptop look + hint -= 4; + if ( hint < 14 ) + hint = 14; + } + return hint; +} + +//=============== paintEvent ==============// + +void KMdiChildFrmCaption::paintEvent( QPaintEvent * ) +{ + QPainter p( this ); + QRect r = rect(); + p.setFont( m_pParent->m_pManager->m_captionFont ); + + if ( m_bActive ) + { + p.fillRect( r, m_pParent->m_pManager->m_captionActiveBackColor ); + p.setPen( m_pParent->m_pManager->m_captionActiveForeColor ); + } + else + { + p.fillRect( r, m_pParent->m_pManager->m_captionInactiveBackColor ); + p.setPen( m_pParent->m_pManager->m_captionInactiveForeColor ); + } + + //Shift the text after the icon + if ( KMdiMainFrm::frameDecorOfAttachedViews() == KMdi::Win95Look ) + r.setLeft( r.left() + m_pParent->icon() ->width() + 3 ); + else if ( KMdiMainFrm::frameDecorOfAttachedViews() == KMdi::KDE1Look ) + r.setLeft( r.left() + 22 ); + else if ( KMdiMainFrm::frameDecorOfAttachedViews() == KMdi::KDELook ) + r.setLeft( r.left() + m_pParent->icon() ->width() + 3 ); + else // kde2laptop look + r.setLeft( r.left() + 30 ); + + int captionWidthForText = width() - 4 * m_pParent->m_pClose->width() - m_pParent->icon() ->width() - 5; + QString text = abbreviateText( m_szCaption, captionWidthForText ); + p.drawText( r, AlignVCenter | AlignLeft | SingleLine, text ); + +} + + +QString KMdiChildFrmCaption::abbreviateText( QString origStr, int maxWidth ) +{ + QFontMetrics fm = fontMetrics(); + int actualWidth = fm.width( origStr ); + + int realLetterCount = origStr.length(); + int newLetterCount; + + if ( actualWidth != 0 ) + newLetterCount = ( maxWidth * realLetterCount ) / actualWidth; + else + newLetterCount = realLetterCount; // should be 0 anyway + + int w = maxWidth + 1; + QString s = origStr; + + if ( newLetterCount <= 0 ) + s = ""; + + while ( ( w > maxWidth ) && ( newLetterCount >= 1 ) ) + { + if ( newLetterCount < realLetterCount ) + { + if ( newLetterCount > 3 ) + s = origStr.left( newLetterCount / 2 ) + "..." + origStr.right( newLetterCount / 2 ); + else + { + if ( newLetterCount > 1 ) + s = origStr.left( newLetterCount ) + ".."; + else + s = origStr.left( 1 ); + } + } + QFontMetrics fm = fontMetrics(); + w = fm.width( s ); + newLetterCount--; + } + return s; +} + +//============= mouseDoubleClickEvent ===========// + +void KMdiChildFrmCaption::mouseDoubleClickEvent( QMouseEvent * ) +{ + m_pParent->maximizePressed(); +} + +//============= slot_moveViaSystemMenu ===========// + +void KMdiChildFrmCaption::slot_moveViaSystemMenu() +{ + setMouseTracking( true ); + grabMouse(); + + if ( KMdiMainFrm::frameDecorOfAttachedViews() != KMdi::Win95Look ) + QApplication::setOverrideCursor( Qt::sizeAllCursor, true ); + + m_pParent->m_bDragging = true; + m_offset = mapFromGlobal( QCursor::pos() ); +} + +// kate: space-indent off; replace-tabs off; indent-mode csands; tab-width 4; diff --git a/lib/compatibility/kmdi/qextmdi/kmdichildfrmcaption.h b/lib/compatibility/kmdi/qextmdi/kmdichildfrmcaption.h new file mode 100644 index 00000000..158f76b0 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmdichildfrmcaption.h @@ -0,0 +1,145 @@ +//---------------------------------------------------------------------------- +// filename : kmdichildfrmcaption.h +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 07/1999 by Szymon Stefanek as part of kvirc +// (an IRC application) +// changes : 09/1999 by Falk Brettschneider to create an +// - 06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// 2000-2003 maintained by the KDevelop project +// +// copyright : (C) 1999-2003 by Falk Brettschneider +// and +// Szymon Stefanek (stefanek@tin.it) +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program 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. +// +//---------------------------------------------------------------------------- +#ifndef _KMDI_CHILD_FRM_CAPTION_H_ +#define _KMDI_CHILD_FRM_CAPTION_H_ + +#include <qwidget.h> + +#include "kmdidefines.h" + +class KMdiChildFrm; + + +class KMdiChildFrmCaptionPrivate; + +/** +* @short Internal class. +* +* It's the caption bar of a child frame widget. +*/ +class KMDI_EXPORT KMdiChildFrmCaption : public QWidget +{ + Q_OBJECT +public: + /** + * Constructor + */ + KMdiChildFrmCaption( KMdiChildFrm *parent ); + + /** + * Destructor + */ + ~KMdiChildFrmCaption(); + + /** + * Repaint the caption bar in active background colors + */ + void setActive( bool bActive ); + + /** + * Repaint with a new caption bar title + */ + void setCaption( const QString& text ); + + /** + * Returns the caption bar height depending on the used font + */ + int heightHint(); + +public slots: + /** + * Grabs the mouse, a move cursor, sets a move indicator variable to true and keeps the global mouse position in mind + */ + void slot_moveViaSystemMenu(); + +protected: + /** + * Draws the caption bar and its title using the settings + */ + virtual void paintEvent( QPaintEvent *e ); + + /** + * The same as KMdiChildFrmCaption::slot_moveViaSystemMenu + */ + virtual void mousePressEvent( QMouseEvent * ); + + /** + * Calls maximizePressed of the parent widget ( KMdiChildFrm ) + */ + virtual void mouseDoubleClickEvent( QMouseEvent * ); + + /** + * Restore the normal mouse cursor, set the state variable back to 'not moving' + */ + virtual void mouseReleaseEvent( QMouseEvent * ); + + /** + * Checks if out of move range of the KMdiChildArea and calls KMdiChildFrm::move + */ + virtual void mouseMoveEvent( QMouseEvent *e ); + + /** + * Computes a new abbreviated string from a given string depending on a given maximum width + * @TODO Replace with a call to a KStringHandler function instead of rolling our own + */ + QString abbreviateText( QString origStr, int maxWidth ); + + // attributes +public: + /** + * the title string shown in the caption bar + */ + QString m_szCaption; + +protected: // Protected attributes + /** + * parent widget + */ + KMdiChildFrm *m_pParent; + + /** + * state variable indicating whether activated or not activated + */ + bool m_bActive; + + /** + * the position offset related to its parent widget (internally used for translating mouse move positions + */ + QPoint m_offset; + + /** + * True if the child knows that it is currently being dragged. + */ + bool m_bChildInDrag; + +private: + KMdiChildFrmCaptionPrivate *d; +}; + +#endif //_KMDICAPTION_H_ + +// kate: space-indent off; replace-tabs off; indent-mode csands; tab-width 4; diff --git a/lib/compatibility/kmdi/qextmdi/kmdichildview.cpp b/lib/compatibility/kmdi/qextmdi/kmdichildview.cpp new file mode 100644 index 00000000..f09cbb3e --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmdichildview.cpp @@ -0,0 +1,773 @@ +//---------------------------------------------------------------------------- +// filename : kmdichildview.cpp +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 07/1999 by Szymon Stefanek as part of kvirc +// (an IRC application) +// changes : 09/1999 by Falk Brettschneider to create a +// -06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// 2000-2003 maintained by the KDevelop project +// patches : 02/2000 by Massimo Morin (mmorin@schedsys.com) +// */2000 by Lars Beikirch (Lars.Beikirch@gmx.net) +// 02/2001 by Eva Brucherseifer (eva@rt.e-technik.tu-darmstadt.de) +// 01/2003 by Jens Zurheide (jens.zurheide@gmx.de) +// +// copyright : (C) 1999-2003 by Szymon Stefanek (stefanek@tin.it) +// and +// Falk Brettschneider +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program 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. +// +//---------------------------------------------------------------------------- + +#include "kmdichildview.h" +#include "kmdichildview.moc" + +#include <qdatetime.h> +#include <qobjectlist.h> + +#include "kmdimainfrm.h" +#include "kmdichildfrm.h" +#include "kmdidefines.h" +#include <kdebug.h> +#include <klocale.h> +#include <qiconset.h> + +//============ KMdiChildView ============// + +KMdiChildView::KMdiChildView( const QString& caption, QWidget* parentWidget, const char* name, WFlags f ) + : QWidget( parentWidget, name, f ) + , m_focusedChildWidget( 0L ) + , m_firstFocusableChildWidget( 0L ) + , m_lastFocusableChildWidget( 0L ) + , m_stateChanged( true ) + , m_bToolView( false ) + , m_bInterruptActivation( false ) + , m_bMainframesActivateViewIsPending( false ) + , m_bFocusInEventIsPending( false ) + , m_trackChanges( 0 ) +{ + setGeometry( 0, 0, 0, 0 ); // reset + if ( caption != 0L ) + m_szCaption = caption; + else + m_szCaption = i18n( "Unnamed" ); + + m_sTabCaption = m_szCaption; + setFocusPolicy( ClickFocus ); + installEventFilter( this ); + + // store the current time + updateTimeStamp(); +} + + +//============ KMdiChildView ============// + +KMdiChildView::KMdiChildView( QWidget* parentWidget, const char* name, WFlags f ) + : QWidget( parentWidget, name, f ) + , m_focusedChildWidget( 0L ) + , m_firstFocusableChildWidget( 0L ) + , m_lastFocusableChildWidget( 0L ) + , m_stateChanged( true ) + , m_bToolView( false ) + , m_bInterruptActivation( false ) + , m_bMainframesActivateViewIsPending( false ) + , m_bFocusInEventIsPending( false ) +{ + setGeometry( 0, 0, 0, 0 ); // reset + m_szCaption = i18n( "Unnamed" ); + m_sTabCaption = m_szCaption; + setFocusPolicy( ClickFocus ); + installEventFilter( this ); + + // store the current time + updateTimeStamp(); +} + +//============ ~KMdiChildView ============// + +KMdiChildView::~KMdiChildView() +{ + kdDebug( 760 ) << k_funcinfo << endl; +} + +void KMdiChildView::trackIconAndCaptionChanges( QWidget *view ) +{ + m_trackChanges = view; +} + + +//============== internal geometry ==============// + +QRect KMdiChildView::internalGeometry() const +{ + if ( mdiParent() ) + { // is attached + // get the client area coordinates inside the MDI child frame + QRect posInFrame = geometry(); + // map these values to the parent of the MDI child frame + // (this usually is the MDI child area) and return + QPoint ptTopLeft = mdiParent() ->mapToParent( posInFrame.topLeft() ); + QSize sz = size(); + return QRect( ptTopLeft, sz ); + } + else + { + QRect geo = geometry(); + QRect frameGeo = externalGeometry(); + return QRect( frameGeo.x(), frameGeo.y(), geo.width(), geo.height() ); + // return geometry(); + } +} + +//============== set internal geometry ==============// + +void KMdiChildView::setInternalGeometry( const QRect& newGeometry ) +{ + if ( mdiParent() ) + { // is attached + // retrieve the frame size + QRect geo = internalGeometry(); + QRect frameGeo = externalGeometry(); + int nFrameSizeTop = geo.y() - frameGeo.y(); + int nFrameSizeLeft = geo.x() - frameGeo.x(); + + // create the new geometry that is accepted by the QWidget::setGeometry() method + QRect newGeoQt; + newGeoQt.setX( newGeometry.x() - nFrameSizeLeft ); + newGeoQt.setY( newGeometry.y() - nFrameSizeTop ); + + newGeoQt.setWidth( newGeometry.width() + nFrameSizeLeft + KMDI_CHILDFRM_DOUBLE_BORDER / 2 ); + newGeoQt.setHeight( newGeometry.height() + nFrameSizeTop + KMDI_CHILDFRM_DOUBLE_BORDER / 2 ); + // newGeoQt.setWidth(newGeometry.width()+KMDI_MDI_CHILDFRM_DOUBLE_BORDER); + // newGeoQt.setHeight(newGeometry.height()+mdiParent()->captionHeight()+KMDI_MDI_CHILDFRM_DOUBLE_BORDER); + + // set the geometry + mdiParent()->setGeometry( newGeoQt ); + } + else + { + // retrieve the frame size + QRect geo = internalGeometry(); + QRect frameGeo = externalGeometry(); + int nFrameSizeTop = geo.y() - frameGeo.y(); + int nFrameSizeLeft = geo.x() - frameGeo.x(); + + // create the new geometry that is accepted by the QWidget::setGeometry() method + QRect newGeoQt; + + newGeoQt.setX( newGeometry.x() - nFrameSizeLeft ); + newGeoQt.setY( newGeometry.y() - nFrameSizeTop ); + + newGeoQt.setWidth( newGeometry.width() ); + newGeoQt.setHeight( newGeometry.height() ); + + // set the geometry + setGeometry( newGeoQt ); + } +} + +//============== external geometry ==============// + +QRect KMdiChildView::externalGeometry() const +{ + return mdiParent() ? mdiParent()->frameGeometry() : frameGeometry(); +} + +//============== set external geometry ==============// + +void KMdiChildView::setExternalGeometry( const QRect& newGeometry ) +{ + if ( mdiParent() ) + { // is attached + mdiParent() ->setGeometry( newGeometry ); + } + else + { + // retrieve the frame size + QRect geo = internalGeometry(); + QRect frameGeo = externalGeometry(); + int nTotalFrameWidth = frameGeo.width() - geo.width(); + int nTotalFrameHeight = frameGeo.height() - geo.height(); + int nFrameSizeTop = geo.y() - frameGeo.y(); + int nFrameSizeLeft = geo.x() - frameGeo.x(); + + // create the new geometry that is accepted by the QWidget::setGeometry() method + // not attached => the window system makes the frame + QRect newGeoQt; + newGeoQt.setX( newGeometry.x() + nFrameSizeLeft ); + newGeoQt.setY( newGeometry.y() + nFrameSizeTop ); + newGeoQt.setWidth( newGeometry.width() - nTotalFrameWidth ); + newGeoQt.setHeight( newGeometry.height() - nTotalFrameHeight ); + + // set the geometry + setGeometry( newGeoQt ); + } +} + +//============== minimize ==============// + +void KMdiChildView::minimize( bool bAnimate ) +{ + if ( mdiParent() ) + { + if ( !isMinimized() ) + { + mdiParent() ->setState( KMdiChildFrm::Minimized, bAnimate ); + } + } + else + showMinimized(); +} + +void KMdiChildView::showMinimized() +{ + emit isMinimizedNow(); + QWidget::showMinimized(); +} + +//slot: +void KMdiChildView::minimize() +{ + minimize( true ); +} + +//============= maximize ==============// + +void KMdiChildView::maximize( bool bAnimate ) +{ + if ( mdiParent() ) + { + if ( !isMaximized() ) + { + mdiParent() ->setState( KMdiChildFrm::Maximized, bAnimate ); + emit mdiParentNowMaximized( true ); + } + } + else + showMaximized(); +} + +void KMdiChildView::showMaximized() +{ + emit isMaximizedNow(); + QWidget::showMaximized(); +} + +//slot: +void KMdiChildView::maximize() +{ + maximize( true ); +} + +//============== restoreGeometry ================// + +QRect KMdiChildView::restoreGeometry() +{ + if ( mdiParent() ) + return mdiParent() ->restoreGeometry(); + else //FIXME not really supported, may be we must use Windows or X11 funtions + return geometry(); +} + +//============== setRestoreGeometry ================// + +void KMdiChildView::setRestoreGeometry( const QRect& newRestGeo ) +{ + if ( mdiParent() ) + mdiParent()->setRestoreGeometry( newRestGeo ); +} + +//============== attach ================// + +void KMdiChildView::attach() +{ + emit attachWindow( this, true ); +} + +//============== detach =================// + +void KMdiChildView::detach() +{ + emit detachWindow( this, true ); +} + +//=============== isMinimized ? =================// + +bool KMdiChildView::isMinimized() const +{ + if ( mdiParent() ) + return ( mdiParent()->state() == KMdiChildFrm::Minimized ); + else + return QWidget::isMinimized(); +} + +//============== isMaximized ? ==================// + +bool KMdiChildView::isMaximized() const +{ + if ( mdiParent() ) + return ( mdiParent()->state() == KMdiChildFrm::Maximized ); + else + return QWidget::isMaximized(); +} + +//============== restore ================// + +void KMdiChildView::restore() +{ + if ( mdiParent() ) + { + if ( isMaximized() ) + emit mdiParentNowMaximized( false ); + + if ( isMinimized() || isMaximized() ) + mdiParent()->setState( KMdiChildFrm::Normal ); + } + else + showNormal(); +} + +void KMdiChildView::showNormal() +{ + emit isRestoredNow(); + QWidget::showNormal(); +} + +//=============== youAreAttached ============// + +void KMdiChildView::youAreAttached( KMdiChildFrm *lpC ) +{ + lpC->setCaption( m_szCaption ); + emit isAttachedNow(); +} + +//================ youAreDetached =============// + +void KMdiChildView::youAreDetached() +{ + setCaption( m_szCaption ); + + setTabCaption( m_sTabCaption ); + if ( myIconPtr() ) + setIcon( *( myIconPtr() ) ); + + setFocusPolicy( QWidget::StrongFocus ); + + emit isDetachedNow(); +} + +//================ setCaption ================// +// this set the caption of only the window +void KMdiChildView::setCaption( const QString& szCaption ) +{ + // this will work only for window + m_szCaption = szCaption; + if ( mdiParent() ) + mdiParent() ->setCaption( m_szCaption ); + else //have to call the parent one + QWidget::setCaption( m_szCaption ); + + emit windowCaptionChanged( m_szCaption ); +} + +//============== closeEvent ================// + +void KMdiChildView::closeEvent( QCloseEvent *e ) +{ + e->ignore(); //we ignore the event , and then close later if needed. + emit childWindowCloseRequest( this ); +} + +//================ myIconPtr =================// + +QPixmap* KMdiChildView::myIconPtr() +{ + return 0; +} + +//============= focusInEvent ===============// + +void KMdiChildView::focusInEvent( QFocusEvent *e ) +{ + QWidget::focusInEvent( e ); + + // every widget get a focusInEvent when a popup menu is opened!?! -> maybe bug of QT + if ( e && ( ( e->reason() ) == QFocusEvent::Popup ) ) + return ; + + + m_bFocusInEventIsPending = true; + activate(); + m_bFocusInEventIsPending = false; + + emit gotFocus( this ); +} + +//============= activate ===============// + +void KMdiChildView::activate() +{ + // avoid circularity + static bool s_bActivateIsPending = false; + if ( s_bActivateIsPending ) + return ; + + s_bActivateIsPending = true; + + // raise the view and push the taskbar button + if ( !m_bMainframesActivateViewIsPending ) + emit focusInEventOccurs( this ); + + // if this method was called directly, check if the mainframe wants that we interrupt + if ( m_bInterruptActivation ) + m_bInterruptActivation = false; + else + { + if ( !m_bFocusInEventIsPending ) + setFocus(); + + kdDebug( 760 ) << k_funcinfo << endl; + emit activated( this ); + } + + if ( m_focusedChildWidget != 0L ) + m_focusedChildWidget->setFocus(); + else + { + if ( m_firstFocusableChildWidget != 0L ) + { + m_firstFocusableChildWidget->setFocus(); + m_focusedChildWidget = m_firstFocusableChildWidget; + } + } + s_bActivateIsPending = false; +} + +//============= focusOutEvent ===============// + +void KMdiChildView::focusOutEvent( QFocusEvent* e ) +{ + QWidget::focusOutEvent( e ); + emit lostFocus( this ); +} + +//============= resizeEvent ===============// + +void KMdiChildView::resizeEvent( QResizeEvent* e ) +{ + QWidget::resizeEvent( e ); + + if ( m_stateChanged ) + { + m_stateChanged = false; + if ( isMaximized() ) + { //maximized + emit isMaximizedNow(); + } + else if ( isMinimized() ) + { //minimized + emit isMinimizedNow(); + } + else + { //is restored + emit isRestoredNow(); + } + } +} + +void KMdiChildView::slot_childDestroyed() +{ + // do what we do if a child is removed + + // if we lost a child we uninstall ourself as event filter for the lost + // child and its children + const QObject * pLostChild = QObject::sender(); + if ( pLostChild && ( pLostChild->isWidgetType() ) ) + { + QObjectList* list = ( ( QObject* ) ( pLostChild ) ) ->queryList( "QWidget" ); + list->insert( 0, pLostChild ); // add the lost child to the list too, just to save code + QObjectListIt it( *list ); // iterate over all lost child widgets + QObject* obj; + while ( ( obj = it.current() ) != 0 ) + { // for each found object... + QWidget * widg = ( QWidget* ) obj; + ++it; + widg->removeEventFilter( this ); + if ( m_firstFocusableChildWidget == widg ) + m_firstFocusableChildWidget = 0L; // reset first widget + + if ( m_lastFocusableChildWidget == widg ) + m_lastFocusableChildWidget = 0L; // reset last widget + + if ( m_focusedChildWidget == widg ) + m_focusedChildWidget = 0L; // reset focused widget + } + delete list; // delete the list, not the objects + } +} + +//============= eventFilter ===============// +bool KMdiChildView::eventFilter( QObject *obj, QEvent *e ) +{ + if ( e->type() == QEvent::KeyPress && isAttached() ) + { + QKeyEvent* ke = ( QKeyEvent* ) e; + if ( ke->key() == Qt::Key_Tab ) + { + QWidget* w = ( QWidget* ) obj; + FocusPolicy wfp = w->focusPolicy(); + if ( wfp == QWidget::StrongFocus || wfp == QWidget::TabFocus || w->focusPolicy() == QWidget::WheelFocus ) + { + if ( m_lastFocusableChildWidget != 0 ) + { + if ( w == m_lastFocusableChildWidget ) + { + if ( w != m_firstFocusableChildWidget ) + m_firstFocusableChildWidget->setFocus(); + } + } + } + } + } + else if ( e->type() == QEvent::FocusIn ) + { + if ( obj->isWidgetType() ) + { + QObjectList * list = queryList( "QWidget" ); + if ( list->find( obj ) != -1 ) + m_focusedChildWidget = ( QWidget* ) obj; + + delete list; // delete the list, not the objects + } + if ( !isAttached() ) + { // is toplevel, for attached views activation is done by main frame event filter + static bool m_bActivationIsPending = false; + if ( !m_bActivationIsPending ) + { + m_bActivationIsPending = true; + activate(); // sets the focus + m_bActivationIsPending = false; + } + } + } + else if ( e->type() == QEvent::ChildRemoved ) + { + // if we lost a child we uninstall ourself as event filter for the lost + // child and its children + QObject * pLostChild = ( ( QChildEvent* ) e ) ->child(); + if ( ( pLostChild != 0L ) && ( pLostChild->isWidgetType() ) ) + { + QObjectList * list = pLostChild->queryList( "QWidget" ); + list->insert( 0, pLostChild ); // add the lost child to the list too, just to save code + QObjectListIt it( *list ); // iterate over all lost child widgets + QObject * o; + while ( ( o = it.current() ) != 0 ) + { // for each found object... + QWidget * widg = ( QWidget* ) o; + ++it; + widg->removeEventFilter( this ); + FocusPolicy wfp = widg->focusPolicy(); + if ( wfp == QWidget::StrongFocus || wfp == QWidget::TabFocus || widg->focusPolicy() == QWidget::WheelFocus ) + { + if ( m_firstFocusableChildWidget == widg ) + m_firstFocusableChildWidget = 0L; // reset first widget + + if ( m_lastFocusableChildWidget == widg ) + m_lastFocusableChildWidget = 0L; // reset last widget + } + } + delete list; // delete the list, not the objects + } + } + else if ( e->type() == QEvent::ChildInserted ) + { + // if we got a new child and we are attached to the MDI system we + // install ourself as event filter for the new child and its children + // (as we did when we were added to the MDI system). + QObject * pNewChild = ( ( QChildEvent* ) e ) ->child(); + if ( ( pNewChild != 0L ) && ( pNewChild->isWidgetType() ) ) + { + QWidget * pNewWidget = ( QWidget* ) pNewChild; + if ( pNewWidget->testWFlags( Qt::WType_Dialog | Qt::WShowModal ) ) + return false; + QObjectList *list = pNewWidget->queryList( "QWidget" ); + list->insert( 0, pNewChild ); // add the new child to the list too, just to save code + QObjectListIt it( *list ); // iterate over all new child widgets + QObject * o; + while ( ( o = it.current() ) != 0 ) + { // for each found object... + QWidget * widg = ( QWidget* ) o; + ++it; + widg->installEventFilter( this ); + connect( widg, SIGNAL( destroyed() ), this, SLOT( slot_childDestroyed() ) ); + FocusPolicy wfp = widg->focusPolicy(); + if ( wfp == QWidget::StrongFocus || wfp == QWidget::TabFocus || widg->focusPolicy() == QWidget::WheelFocus ) + { + if ( m_firstFocusableChildWidget == 0 ) + m_firstFocusableChildWidget = widg; // first widge + + m_lastFocusableChildWidget = widg; // last widget + } + } + delete list; // delete the list, not the objects + } + } + else + { + if ( e->type() == QEvent::IconChange ) + { + // qDebug("KMDiChildView:: QEvent:IconChange intercepted\n"); + if ( obj == this ) + iconUpdated( this, icon() ? ( *icon() ) : QPixmap() ); + else if ( obj == m_trackChanges ) + setIcon( m_trackChanges->icon() ? ( *( m_trackChanges->icon() ) ) : QPixmap() ); + } + if ( e->type() == QEvent::CaptionChange ) + { + if ( obj == this ) + captionUpdated( this, caption() ); + } + } + + return false; // standard event processing +} + +/** Switches interposing in event loop of all current child widgets off. */ +void KMdiChildView::removeEventFilterForAllChildren() +{ + QObjectList* list = queryList( "QWidget" ); + QObjectListIt it( *list ); // iterate over all child widgets + QObject* obj; + while ( ( obj = it.current() ) != 0 ) + { // for each found object... + QWidget* widg = ( QWidget* ) obj; + ++it; + widg->removeEventFilter( this ); + } + delete list; // delete the list, not the objects +} + +QWidget* KMdiChildView::focusedChildWidget() +{ + return m_focusedChildWidget; +} + +void KMdiChildView::setFirstFocusableChildWidget( QWidget* firstFocusableChildWidget ) +{ + m_firstFocusableChildWidget = firstFocusableChildWidget; +} + +void KMdiChildView::setLastFocusableChildWidget( QWidget* lastFocusableChildWidget ) +{ + m_lastFocusableChildWidget = lastFocusableChildWidget; +} + +/** Set a new value of the task bar button caption */ +void KMdiChildView::setTabCaption ( const QString& stbCaption ) +{ + m_sTabCaption = stbCaption; + emit tabCaptionChanged( m_sTabCaption ); +} + +void KMdiChildView::setMDICaption ( const QString& caption ) +{ + setCaption( caption ); + setTabCaption( caption ); +} + +/** sets an ID */ +void KMdiChildView::setWindowMenuID( int id ) +{ + m_windowMenuID = id; +} + +//============= slot_clickedInWindowMenu ===============// + +/** called if someone click on the "Window" menu item for this child frame window */ +void KMdiChildView::slot_clickedInWindowMenu() +{ + updateTimeStamp(); + emit clickedInWindowMenu( m_windowMenuID ); +} + +//============= slot_clickedInDockMenu ===============// + +/** called if someone click on the "Dock/Undock..." menu item for this child frame window */ +void KMdiChildView::slot_clickedInDockMenu() +{ + emit clickedInDockMenu( m_windowMenuID ); +} + +//============= setMinimumSize ===============// + +void KMdiChildView::setMinimumSize( int minw, int minh ) +{ + QWidget::setMinimumSize( minw, minh ); + if ( mdiParent() && mdiParent()->state() != KMdiChildFrm::Minimized ) + { + mdiParent() ->setMinimumSize( minw + KMDI_CHILDFRM_DOUBLE_BORDER, + minh + KMDI_CHILDFRM_DOUBLE_BORDER + KMDI_CHILDFRM_SEPARATOR + mdiParent() ->captionHeight() ); + } +} + +//============= setMaximumSize ===============// + +void KMdiChildView::setMaximumSize( int maxw, int maxh ) +{ + if ( mdiParent() && mdiParent()->state() == KMdiChildFrm::Normal ) + { + int w = maxw + KMDI_CHILDFRM_DOUBLE_BORDER; + if ( w > QWIDGETSIZE_MAX ) + w = QWIDGETSIZE_MAX; + + int h = maxh + KMDI_CHILDFRM_DOUBLE_BORDER + KMDI_CHILDFRM_SEPARATOR + mdiParent() ->captionHeight(); + if ( h > QWIDGETSIZE_MAX ) + h = QWIDGETSIZE_MAX; + + mdiParent()->setMaximumSize( w, h ); + } + QWidget::setMaximumSize( maxw, maxh ); +} + +//============= show ===============// + +void KMdiChildView::show() +{ + if ( mdiParent() ) + mdiParent()->show(); + + QWidget::show(); +} + +//============= hide ===============// + +void KMdiChildView::hide() +{ + if ( mdiParent() ) + mdiParent()->hide(); + + QWidget::hide(); +} + +//============= raise ===============// + +void KMdiChildView::raise() +{ + if ( mdiParent() ) //TODO Check Z-order + mdiParent()->raise(); + + QWidget::raise(); +} + +// kate: space-indent off; replace-tabs off; indent-mode csands; tab-width 4; diff --git a/lib/compatibility/kmdi/qextmdi/kmdichildview.h b/lib/compatibility/kmdi/qextmdi/kmdichildview.h new file mode 100644 index 00000000..fda0b95b --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmdichildview.h @@ -0,0 +1,615 @@ +//---------------------------------------------------------------------------- +// filename : kmdichildview.h +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 07/1999 by Szymon Stefanek as part of kvirc +// (an IRC application) +// changes : 09/1999 by Falk Brettschneider to create an +// - 06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// 2000-2003 maintained by the KDevelop project +// patches : 02/2000 by Massimo Morin (mmorin@schedsys.com) +// */2000 by Lars Beikirch (Lars.Beikirch@gmx.net) +// 02/2001 by Eva Brucherseifer (eva@rt.e-technik.tu-darmstadt.de) +// 01/2003 by Jens Zurheide (jens.zurheide@gmx.de) +// +// copyright : (C) 1999-2003 by Falk Brettschneider +// and +// Szymon Stefanek (stefanek@tin.it) +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program 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. +// +//---------------------------------------------------------------------------- +#ifndef _KMDI_CHILD_VIEW_H_ +#define _KMDI_CHILD_VIEW_H_ + +#include <qwidget.h> +#include <qpixmap.h> +#include <qrect.h> +#include <qapplication.h> +#include <qdatetime.h> + +#include "kmdichildfrm.h" + +class KMdiChildViewPrivate; + +/** + * @short Base class for all your special view windows. + * + * Base class for all MDI view widgets. KMdi stores additional information in this class + * to handle the attach/detach mechanism and such things. + * + * All such windows 'lives' attached to a KMdiChildFrm widget + * managed by KMdiChildArea, or detached (managed by the window manager.) + * So remember that the KMdiChildView::parent pointer may change, and may be 0L, too. + * + * There are 2 possibilities for you to put your widgets under MDI control: + * + * Either you inherit all the views from KMdiChildView: + * \code + * class MyMdiWidget : public KMdiChildView + * { .... }; + * ... + * MyMdiWidget w; + * mainframe->addWindow(w, flags); + * \endcode + * + * or you wrap them by a KMdiChildView somehow like this: + * + * \code + * void DocViewMan::addKMdiFrame(QWidget* pNewView, bool bShow, const QPixmap& icon) + * { + * // cover it by a KMdi childview and add that MDI system + * KMdiChildView* pMDICover = new KMdiChildView( pNewView->caption()); + * pMDICover->setIcon(icon); + * m_MDICoverList.append( pMDICover); + * QBoxLayout* pLayout = new QHBoxLayout( pMDICover, 0, -1, "layout"); + * pNewView->reparent( pMDICover, QPoint(0,0)); + * pLayout->addWidget( pNewView); + * pMDICover->setName( pNewView->name()); + * // captions + * QString shortName = pNewView->caption(); + * int length = shortName.length(); + * shortName = shortName.right(length - (shortName.findRev('/') +1)); + * pMDICover->setTabCaption( shortName); + * pMDICover->setCaption(pNewView->caption()); + * + * // fake a viewActivated to update the currentEditView/currentBrowserView pointers _before_ adding to MDI control + * slot_viewActivated( pMDICover); + * + * // take it under MDI mainframe control (note: this triggers also a setFocus()) + * int flags; + * if (bShow) { + * flags = KMdi::StandardAdd; + * } + * else { + * flags = KMdi::Hide; + * } + * // set the accelerators for Toplevel MDI mode (each toplevel window needs its own accels + * connect( m_pParent, SIGNAL(childViewIsDetachedNow(QWidget*)), this, SLOT(initKeyAccel(QWidget*)) ); + * + * m_pParent->addWindow( pMDICover, flags); + * // correct the default settings of KMdi ('cause we haven't a tab order for subwidget focuses) + * pMDICover->setFirstFocusableChildWidget(0L); + * pMDICover->setLastFocusableChildWidget(0L); + * } + * \endcode + * + */ + +class KMDI_EXPORT KMdiChildView : public QWidget +{ + friend class KMdiMainFrm; + friend class KMdiChildFrm; + Q_OBJECT + + // attributes +protected: + /** + * See KMdiChildView::caption + */ + QString m_szCaption; + + /** + * See KMdiChildView::tabCaption + */ + QString m_sTabCaption; + + /** + * See KMdiChildView::focusedChildWidget + */ + QWidget* m_focusedChildWidget; + + /** + * See KMdiChildView::setFirstFocusableChildWidget + */ + QWidget* m_firstFocusableChildWidget; + + /** + * See KMdiChildView::setLastFocusableChildWidget + */ + QWidget* m_lastFocusableChildWidget; + + /** + * Every child view window has an temporary ID in the Window menu of the main frame. + */ + int m_windowMenuID; + + /** + * Holds a temporary information about if the MDI view state has changed but is not processed yet (pending state). + * For example it could be that a 'maximize' is pending, if this variable is true. + */ + bool m_stateChanged; + + /** + * Holds the time when this view was activated (not only displayed) for the last time. + */ + QDateTime m_time; + +private: + /** + * Internally used as indicator whether this KMdiChildView is treated as document view or as tool view. + */ + bool m_bToolView; + + /** + * Internally used by KMdiMainFrm to store a temporary information that the method + * activate() is unnecessary and that it can by escaped. + * This saves from unnecessary calls when activate is called directly. + */ + bool m_bInterruptActivation; + + /** + * Internally used to prevent cycles between KMdiMainFrm::activateView() and KMdiChildView::activate(). + */ + bool m_bMainframesActivateViewIsPending; + + /** + * Internally used to check if there is a focus in event pending + */ + bool m_bFocusInEventIsPending; + + // methods +public: + /** + * Constructor + */ + KMdiChildView( const QString& caption, QWidget* parentWidget = 0L, const char* name = 0L, WFlags f = 0 ); + + /** + * Constructor + * sets "Unnamed" as default caption + */ + KMdiChildView( QWidget* parentWidget = 0L, const char* name = 0L, WFlags f = 0 ); + + /** + * Destructor + */ + ~KMdiChildView(); + + /** + * This method does the same as focusInEvent(). That's why it is a replacement for the setFocus() call. It makes + * sense if you for instance want to focus (I mean raise and activate) this view although the real focus is + * in another toplevel widget. focusInEvent() will never get called in that case and your setFocus() call for this + * widget would fail without any effect. + * Use this method with caution, it always raises the view and pushes the taskbar button. Also when the focus is + * still on another MDI view in the same toplevel window where this is located! + */ + void activate(); + + /** + * Memorizes the first focusable child widget of this widget + */ + void setFirstFocusableChildWidget( QWidget* ); + + /** + * Memorizes the last focusable child widget of this widget + */ + void setLastFocusableChildWidget( QWidget* ); + + /** + * Returns the current focused child widget of this widget + */ + QWidget* focusedChildWidget(); + + /** + * Returns true if the MDI view is a child window within the MDI mainframe widget + * or false if the MDI view is in toplevel mode + */ + bool isAttached() const { return ( mdiParent() != 0L ); } + + /** + * Returns the caption of the child window (different from the caption on the button in the taskbar) + */ + const QString& caption() const { return m_szCaption; } + + /** + * Returns the caption of the button on the taskbar + */ + const QString& tabCaption() const { return m_sTabCaption; } + + /** + * Sets the window caption string... + * Calls updateButton on the taskbar button if it has been set. + */ + virtual void setCaption( const QString& szCaption ); + + /** + * Sets the caption of the button referring to this window + */ + virtual void setTabCaption( const QString& caption ); + + /** + * Sets the caption of both the window and the button on the taskbar + */ + virtual void setMDICaption( const QString &caption ); + + /** + * Returns the KMdiChildFrm parent widget (or 0 if the window is not attached) + */ + KMdiChildFrm *mdiParent() const; + + /** + * Tells if the window is minimized when attached to the Mdi manager, + * or if it is VISIBLE when 'floating'. + */ + bool isMinimized() const; + + /** + * Tells if the window is minimized when attached to the Mdi manager, + * otherwise returns false. + */ + bool isMaximized() const; + + /** + * Returns the geometry of this MDI child window as QWidget::geometry() does. + */ + QRect internalGeometry() const; + + /** + * Sets the geometry of the client area of this MDI child window. The + * top left position of the argument is the position of the top left point + * of the client area in its parent coordinates and the arguments width + * and height is the width and height of the client area. Please note: This + * differs from the behavior of QWidget::setGeometry()! + */ + void setInternalGeometry( const QRect& newGeomety ); + + /** + * Returns the frame geometry of this window or of the parent if there is any... + */ + QRect externalGeometry() const; + + /** + * Sets the geometry of the frame of this MDI child window. The top left + * position of the argument is the position of the top left point of the + * frame in its parent coordinates and the arguments width and height is + * the width and height of the widget frame. Please note: This differs + * from the behavior of QWidget::setGeometry()! + */ + void setExternalGeometry( const QRect& newGeomety ); + + /** + * You should override this function in the derived class. + */ + virtual QPixmap* myIconPtr(); + + /** + * Minimizes this window when it is attached to the Mdi manager. + * Otherwise has no effect + */ + virtual void minimize( bool bAnimate ); + + /** + * Maximizes this window when it is attached to the Mdi manager. + * Otherwise has no effect + */ + virtual void maximize( bool bAnimate ); + + /** + * Returns the geometry that will be restored by calling restore(). + */ + QRect restoreGeometry(); + + /** + * Sets the geometry that will be restored by calling restore(). + */ + void setRestoreGeometry( const QRect& newRestGeo ); + + /** + * Switches interposing in event loop of all current child widgets off. + */ + void removeEventFilterForAllChildren(); + + /** + * Internally used for setting an ID for the 'Window' menu entry + */ + void setWindowMenuID( int id ); + + /** + * Sets the minimum size of the widget to w by h pixels. + * It extends it base clase method in a way that the minimum size of + * its childframe (if there is one) will be set, additionally. + */ + virtual void setMinimumSize ( int minw, int minh ); + + /** + * Sets the maximum size of the widget to w by h pixels. + * It extends it base clase method in a way that the maximum size of + * its childframe (if there is one) will be set, additionally. + */ + virtual void setMaximumSize ( int maxw, int maxh ); + + /** + * Returns if this is added as MDI tool-view + */ + inline bool isToolView() const { return m_bToolView; } + + /** + * Remember the current time + */ + inline void updateTimeStamp() + { + m_time.setDate( QDate::currentDate() ); + m_time.setTime( QTime::currentTime() ); + } + + /** + * Recall a previously remembered time, i.e. the value of m_time + */ + inline const QDateTime& getTimeStamp() const { return m_time; } + +public slots: + /** + * Attaches this window to the Mdi manager. + * It calls the KMdiMainFrm attachWindow function , so if you have a pointer + * to this KMdiMainFrm you'll be faster calling that function. + */ + virtual void attach(); + + /** + * Detaches this window from the Mdi manager. + * It calls the KMdiMainFrm detachWindow function , so if you have a pointer + * to this KMdiMainFrm you'll be faster calling that function. + */ + virtual void detach(); + + /** + * Mimimizes the MDI view. If attached, the covering childframe widget is minimized (only a mini widget + * showing the caption bar and the system buttons will remain visible). If detached, it will use the + * minimize of the underlying system ( QWidget::showMinimized ). + */ + virtual void minimize(); + + /** + * Maximizes the MDI view. If attached, this widget will fill the whole MDI view area widget. The system buttons + * move to the main menubar (if set by KMdiMainFrm::setMenuForSDIModeSysButtons ). + * If detached, it will use the minimize of the underlying system ( QWidget::showMaximized ). + */ + virtual void maximize(); + + /** + * Restores this window to its normal size. Also known as 'normalize'. + */ + virtual void restore(); + + /** + * Internally called, if KMdiMainFrm::attach is called. + * Actually, only the caption of the covering childframe is set. + */ + virtual void youAreAttached( KMdiChildFrm *lpC ); + + /** + * Internally called, if KMdiMainFrm::detach is called. + * Some things for going toplevel will be done here. + */ + virtual void youAreDetached(); + + /** + * Called if someone click on the "Window" menu item for this child frame window + */ + virtual void slot_clickedInWindowMenu(); + + /** + * Called if someone click on the "Dock/Undock..." menu item for this child frame window + */ + virtual void slot_clickedInDockMenu(); + + /** + * Calls QWidget::show but also for it's parent widget if attached + */ + virtual void show(); + + /** + * Calls QWidget::hide() or it's parent widget hide() if attached + */ + virtual void hide(); + + /** + * Calls QWidget::raise() or it's parent widget raise() if attached + */ + virtual void raise(); + + /** + * Overridden from its base class method. Emits a signal KMdiChildView::isMinimizedNow , additionally. + * Note that this method is not used by an external windows manager call on system minimizing. + */ + virtual void showMinimized(); + + /** + * Overridden from its base class method. Emits a signal KMdiChildView::isMaximizedNow , additionally. + * Note that this method is not used by an external windows manager call on system maximizing. + */ + virtual void showMaximized(); + + /** + * Overridden from its base class method. Emits a signal KMdiChildView::isRestoredNow , additionally. + * Note that this method is not used by an external windows manager call on system normalizing. + */ + virtual void showNormal(); + + +protected: + /** + * Ignores the event and calls KMdiMainFrm::childWindowCloseRequest instead. This is because the + * mainframe has control over the views. Therefore the MDI view has to request the mainframe for a close. + */ + virtual void closeEvent( QCloseEvent *e ); + + /** + * It only catches QEvent::KeyPress events there. If a Qt::Key_Tab is pressed, the internal MDI focus + * handling is called. That means if the last focusable child widget of this is called, it will jump to the + * first focusable child widget of this. + * See KMdiChildView::setFirstFocusableChildWidget and KMdiChildView::lastFirstFocusableChildWidget + */ + virtual bool eventFilter( QObject *obj, QEvent *e ); + + /** + * If attached, the childframe will be activated and the MDI taskbar button will be pressed. Additionally, the + * memorized old focused child widget of this is focused again. + * Sends the focusInEventOccurs signal before changing the focus and the + * gotFocus signal after changing the focus. + */ + virtual void focusInEvent( QFocusEvent *e ); + + /** + * Send the lostFocus signal + */ + virtual void focusOutEvent( QFocusEvent *e ); + + /** + * Internally used for the minimize/maximize/restore mechanism when in attach mode. + */ + virtual void resizeEvent( QResizeEvent *e ); + + void trackIconAndCaptionChanges( QWidget *view ); + +protected slots: + void slot_childDestroyed(); + +signals: + /** + * Internally used by KMdiChildView::attach to send it as command to the mainframe. + */ + void attachWindow( KMdiChildView*, bool ); + + /** + * Internally used by KMdiChildView::detach to send it as command to the mainframe. + */ + void detachWindow( KMdiChildView*, bool ); + + /** + * Is sent when this MDI child view is going to receive focus (before actually changing the focus). + * Internally used to send information to the mainframe that this MDI child view is focused. + * See KMdiChildView::focusInEvent + */ + void focusInEventOccurs( KMdiChildView* ); + + /** + * Is sent when this MDI child has received the focus (after actually changing the focus). + * See KMdiChildView::focusInEvent + */ + void gotFocus( KMdiChildView* ); + + /** + * Is sent when this MDI child was set to the activate view of all MDI views (after actually changing the focus). + * See KMdiChildView::activate + */ + void activated( KMdiChildView* ); + + /** Is sent when this MDI child view has lost the focus (after actually changing the focus). + * See KMdiChildView::focusOutEvent + */ + void lostFocus( KMdiChildView* ); + + /** Is sent when this MDI child view was deactivated (after actually changing the focus). + * See KMdiChildView::focusOutEvent + */ + void deactivated( KMdiChildView* ); + + /** + * Internally used to send information to the mainframe that this MDI child view wants to be closed. + * See KMdiChildView::closeEvent and KMdiMainFrm::closeWindow + */ + void childWindowCloseRequest( KMdiChildView* ); + + /** + * Emitted when the window caption is changed via KMdiChildView::setCaption or KMdiChildView::setMDICaption + */ + void windowCaptionChanged( const QString& ); + + /** + * Emitted when the window caption is changed via KMdiChildView::setTabCaption or KMdiChildView::setMDICaption + */ + void tabCaptionChanged( const QString& ); + + /** + * Internally used to send information to the mainframe that this MDI view is maximized now. + * Usually, the mainframe switches system buttons. + */ + void mdiParentNowMaximized( bool ); + + /** + * Is automatically emitted when slot_clickedInWindowMenu is called + */ + void clickedInWindowMenu( int ); + + /** + * Is automatically emitted when slot_clickedInDockMenu is called + */ + void clickedInDockMenu( int ); + + /** + * Signals this has been maximized + */ + void isMaximizedNow(); + + /** + * Signals this has been minimized + */ + void isMinimizedNow(); + + /** + * Signals this has been restored (normalized) + */ + void isRestoredNow(); + + /** + * Signals this has been attached + */ + void isAttachedNow(); + + /** + * Signals this has been detached + */ + void isDetachedNow(); + + void iconUpdated( QWidget*, QPixmap ); + void captionUpdated( QWidget*, const QString& ); + + +private: + KMdiChildViewPrivate *d; + QWidget *m_trackChanges; +}; + +inline KMdiChildFrm *KMdiChildView::mdiParent() const +{ + QWidget * pw = parentWidget(); + if ( pw != 0L ) + if ( pw->inherits( "KMdiChildFrm" ) ) + return ( KMdiChildFrm * ) pw; + return 0L; +} + +#endif //_KMDICHILDVIEW_H_ + +// kate: space-indent off; replace-tabs off; indent-mode csands; tab-width 4; diff --git a/lib/compatibility/kmdi/qextmdi/kmdidefines.h b/lib/compatibility/kmdi/qextmdi/kmdidefines.h new file mode 100644 index 00000000..50343235 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmdidefines.h @@ -0,0 +1,117 @@ +//---------------------------------------------------------------------------- +// filename : kmdidefines.h +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 07/1999 by Szymon Stefanek as part of kvirc +// (an IRC application) +// changes : 09/1999 by Falk Brettschneider to create an +// stand-alone Qt extension set of +// classes and a Qt-based library +// 2000-2003 maintained by the KDevelop project +// +// copyright : (C) 1999-2003 by Falk Brettschneider +// and +// Szymon Stefanek (stefanek@tin.it) +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program 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. +// +//---------------------------------------------------------------------------- +#ifndef _KMDI_DEFINES_H_ +#define _KMDI_DEFINES_H_ + +#include <kdelibs_export.h> + +#define KMDI_CHILDFRM_SEPARATOR 2 +#define KMDI_CHILDFRM_BORDER 4 +#define KMDI_CHILDFRM_DOUBLE_BORDER 8 +#define KMDI_CHILDFRM_MIN_WIDTH 130 + +//---------------------------------------------------------------------------- +/** +* @short A namespace for the KMDI library +*/ +namespace KMdi +{ + /** extent Qt events + @see QCustomEvent, QEvent::User + \code + bool B_MyWidget::event( QEvent* e) { + if( e->type() == QEvent::Type(QEvent::User + int(KMdi::EV_Move))) { + ... + } + ... + } + \endcode + */ + enum EventType { + EV_Move=1, + EV_DragBegin, + EV_DragEnd, + EV_ResizeBegin, + EV_ResizeEnd + }; + + /** + * During KMdiMainFrm::addWindow the enum AddWindowFlags is used to determine how the view is initialy being added to the MDI system + */ + enum AddWindowFlags { + /** + * standard is: show normal, attached, visible, document view (not toolview). Maximize, Minimize, Hide adds + * appropriately. Detach adds a view that appears toplevel, ToolWindow adds the view as tool view. + * That means it is stay-on-top and toplevel. UseKMdiSizeHint should use the restore geometry of the + * latest current top childframe but is not supported yet. + */ + StandardAdd = 0, + Maximize = 1, + Minimize = 2, + Hide = 4, + Detach = 8, + ToolWindow = 16, + UseKMdiSizeHint = 32, + AddWindowFlags = 0xff + }; + + enum FrameDecor { + Win95Look = 0, + KDE1Look = 1, + KDELook = 2, + KDELaptopLook = 3 + }; + + enum MdiMode { + UndefinedMode = 0, + ToplevelMode = 1, + ChildframeMode = 2, + TabPageMode = 3, + IDEAlMode = 4 + }; + + enum TabWidgetVisibility { + AlwaysShowTabs = 0, + ShowWhenMoreThanOneTab = 1, + NeverShowTabs = 2 + }; + + /** + * The style of the toolview tabs + * \since 3.3 + */ + enum ToolviewStyle { + /** Show only icons on the toolview tabs. The visible toolviews contain both the icon and text. */ + IconOnly = 0, + /** Show only the text description on the toolview tabs. */ + TextOnly = 1, + /** Show both the icon and description on the toolview tabs. */ + TextAndIcon = 3 + }; +} //namespace + +#endif //_KMDIDEFINES_H_ diff --git a/lib/compatibility/kmdi/qextmdi/kmdidockcontainer.cpp b/lib/compatibility/kmdi/qextmdi/kmdidockcontainer.cpp new file mode 100644 index 00000000..c1b1b03a --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmdidockcontainer.cpp @@ -0,0 +1,856 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Christoph Cullmann <cullmann@kde.org> + Copyright (C) 2002,2003 Joseph Wenninger <jowenn@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 version 2 as published by the Free Software Foundation. + + 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 "kmdimainfrm.h" +#include "kmdidockcontainer.h" +#include "kmdidockcontainer.moc" + +#include "kdockwidget_private.h" + +#include <qwidgetstack.h> +#include <qlayout.h> +#include <qtimer.h> +#include <qtooltip.h> +#include <kmultitabbar.h> +#include <kglobalsettings.h> + +#include <kdebug.h> +#include <kiconloader.h> +#include <kapplication.h> +#include <kconfig.h> +#include <klocale.h> + +//TODO: Well, this is already defined in kdeui/kdockwidget.cpp +static const char* const kmdi_not_close_xpm[] = + { + "5 5 2 1", + "# c black", + ". c None", + "#####", + "#...#", + "#...#", + "#...#", + "#####" + }; + +KMdiDockContainer::KMdiDockContainer( QWidget *parent, QWidget *win, int position, int flags ) + : QWidget( parent ), KDockContainer() +{ + m_tabSwitching = false; + m_block = false; + m_inserted = -1; + m_mainWin = win; + oldtab = -1; + mTabCnt = 0; + m_position = position; + m_previousTab = -1; + m_separatorPos = 17; + m_movingState = NotMoving; + m_startEvent = 0; + kdDebug( 760 ) << k_funcinfo << endl; + + QBoxLayout *l; + m_horizontal = ( ( position == KDockWidget::DockTop ) || ( position == KDockWidget::DockBottom ) ); + + + if ( m_horizontal ) + l = new QVBoxLayout( this ); //vertical layout for top and bottom docks + else + l = new QHBoxLayout( this ); //horizontal layout for left and right docks + + l->setAutoAdd( false ); + + m_tb = new KMultiTabBar( m_horizontal ? KMultiTabBar::Horizontal : KMultiTabBar::Vertical, this ); + + m_tb->setStyle( KMultiTabBar::KMultiTabBarStyle( flags ) ); + m_tb->showActiveTabTexts( true ); + + KMultiTabBar::KMultiTabBarPosition kmtbPos; + switch( position ) + { + case KDockWidget::DockLeft: + kmtbPos = KMultiTabBar::Left; + break; + case KDockWidget::DockRight: + kmtbPos = KMultiTabBar::Right; + break; + case KDockWidget::DockTop: + kmtbPos = KMultiTabBar::Top; + break; + case KDockWidget::DockBottom: + kmtbPos = KMultiTabBar::Bottom; + break; + default: + kmtbPos = KMultiTabBar::Right; + break; + } + m_tb->setPosition( kmtbPos ); + + m_ws = new QWidgetStack( this ); + + m_ws->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); + + //layout the tabbar + if ( position == KDockWidget::DockLeft || position == KDockWidget::DockTop ) + { + //add the tabbar then the widget stack + l->add( m_tb ); + l->add( m_ws ); + } + else + { + //add the widget stack then the tabbar + l->add( m_ws ); + l->add( m_tb ); + } + + l->activate(); + m_ws->hide(); + +} + +void KMdiDockContainer::setStyle( int style ) +{ + if ( m_tb ) + m_tb->setStyle( KMultiTabBar::KMultiTabBarStyle( style ) ); +} + +KMdiDockContainer::~KMdiDockContainer() +{ + QMap<KDockWidget*, int>::iterator it; + while ( m_map.count() ) + { + it = m_map.begin(); + KDockWidget *w = it.key(); + if ( m_overlapButtons.contains( w ) ) + { + ( static_cast<KDockWidgetHeader*>( w->getHeader()->qt_cast( "KDockWidgetHeader" ) ) )->removeButton( m_overlapButtons[w] ); + m_overlapButtons.remove( w ); + } + m_map.remove( w ); + w->undock(); + } + deactivated( this ); +} + + +void KMdiDockContainer::init() +{ + kdDebug( 760 ) << k_funcinfo << endl; + if ( !m_horizontal ) + { + kdDebug( 760 ) << k_funcinfo << "Horizontal tabbar. Setting forced fixed width." << endl; + parentDockWidget()->setForcedFixedWidth( m_tb->width() ); + activateOverlapMode( m_tb->width() ); + } + else + { + kdDebug( 760 ) << k_funcinfo << "Vertical tabbar. Setting forced fixed height." << endl; + parentDockWidget()->setForcedFixedHeight( m_tb->height() ); + activateOverlapMode( m_tb->height() ); + } + + // try to restore splitter size + if ( parentDockWidget() && parentDockWidget()->parent() ) + { + KDockSplitter * sp = static_cast<KDockSplitter*>( parentDockWidget()->parent()->qt_cast( "KDockSplitter" ) ); + if ( sp ) + sp->setSeparatorPosX( m_separatorPos ); + } +} + +KDockWidget* KMdiDockContainer::parentDockWidget() +{ + return ( ( KDockWidget* ) parent() ); +} + +void KMdiDockContainer::insertWidget ( KDockWidget *dwdg, QPixmap pixmap, const QString &text, int & ) +{ + kdDebug( 760 ) << k_funcinfo << "Adding a dockwidget to the dock container" << endl; + KDockWidget* w = dwdg; + int tab; + bool alreadyThere = m_map.contains( w ); + + if ( alreadyThere ) + { + tab = m_map[ w ]; + if ( m_ws->addWidget( w, tab ) != tab ) + kdDebug( 760 ) << "ERROR COULDN'T READD WIDGET" << endl; + + kdDebug( 760 ) << k_funcinfo << "Readded widget " << dwdg << endl; + } + else + { + tab = m_ws->addWidget( w ); + m_map.insert( w, tab ); + m_revMap.insert( tab, w ); + + if ( ( ( KDockWidget* ) parentWidget() ) ->mayBeShow() ) + ( ( KDockWidget* ) parentWidget() ) ->dockBack(); + + if ( w->getHeader()->qt_cast( "KDockWidgetHeader" ) ) + { + kdDebug( 760 ) << k_funcinfo << "The dockwidget we're adding has a header" << endl; + kdDebug( 760 ) << k_funcinfo << "Adding our overlap mode button to it" << endl; + + KDockWidgetHeader *hdr = static_cast<KDockWidgetHeader*>( w->getHeader()->qt_cast( "KDockWidgetHeader" ) ); + KDockButton_Private *btn = new KDockButton_Private( hdr, "OverlapButton" ); + + QToolTip::add( btn, i18n( "Switch between overlap and side by side mode", "Overlap" ) ); + + btn->setToggleButton( true ); + btn->setPixmap( const_cast< const char** >( kmdi_not_close_xpm ) ); + hdr->addButton( btn ); + m_overlapButtons.insert( w, btn ); + btn->setOn( !isOverlapMode() ); + + connect( btn, SIGNAL( clicked() ), this, SLOT( changeOverlapMode() ) ); + } + + m_tb->appendTab( pixmap.isNull() ? SmallIcon( "misc" ) : pixmap, tab, w->tabPageLabel() ); + m_tb->tab( tab )->installEventFilter( this ); + kdDebug( 760 ) << k_funcinfo << "Added tab with label " << w->tabPageLabel() << + " to the tabbar" << endl; + + connect( m_tb->tab( tab ), SIGNAL( clicked( int ) ), this, SLOT( tabClicked( int ) ) ); + + mTabCnt++; + m_inserted = tab; + int dummy = 0; + KDockContainer::insertWidget( w, pixmap, text, dummy ); + itemNames.append( w->name() ); + tabCaptions.insert( w->name(), w->tabPageLabel() ); + tabTooltips.insert( w->name(), w->toolTipString() ); + } + + //FB m_ws->raiseWidget(tab); +} + + +bool KMdiDockContainer::eventFilter( QObject *obj, QEvent *event ) +{ + switch ( event->type() ) + { + case QEvent::MouseButtonPress: + { + KMultiTabBarTab* kmtbTab = dynamic_cast<KMultiTabBarTab*>( obj ); + if ( !obj ) + { + kdDebug(760) << k_funcinfo << "Got a mouse button press but we have no tab" << endl; + break; + } + + KDockWidget* w = m_revMap[ dynamic_cast<KMultiTabBarTab*>( obj )->id() ]; + if ( !w ) + { + kdDebug(760) << k_funcinfo << "Got a mouse button press but we have no widget" << endl; + break; + } + + if ( !w->getHeader() ) + { + kdDebug(760) << k_funcinfo << "Got a mouse button press but we have no header" << endl; + break; + } + + KDockWidgetHeader *hdr = static_cast<KDockWidgetHeader*>( w->getHeader()->qt_cast( "KDockWidgetHeader" ) ); + if ( !hdr ) + { + kdDebug(760) << "Wrong header type in KMdiDockContainer::eventFilter" << endl; + break; + } + + m_dockManager = w->dockManager(); + m_dragPanel = hdr->dragPanel(); + + if ( m_dragPanel ) + m_movingState = WaitingForMoveStart; + + delete m_startEvent; + m_startEvent = new QMouseEvent( * ( ( QMouseEvent* ) event ) ); + } + break; + case QEvent::MouseButtonRelease: + if ( m_movingState == Moving ) + { + m_movingState = NotMoving; + QApplication::postEvent( m_dragPanel, new QMouseEvent( * ( ( QMouseEvent* ) event ) ) ); + delete m_startEvent; + m_startEvent = 0; + } + case QEvent::MouseMove: + if ( m_movingState == WaitingForMoveStart ) + { + QPoint p( ( ( QMouseEvent* ) event )->pos() - m_startEvent->pos() ); + if ( p.manhattanLength() > KGlobalSettings::dndEventDelay() ) + { + m_dockManager->eventFilter( m_dragPanel, m_startEvent ); + m_dockManager->eventFilter( m_dragPanel, event ); + m_movingState = Moving; + } + } + else if ( m_movingState == Moving ) + m_dockManager->eventFilter( m_dragPanel, event ); + + break; + default: + break; + + } + return false; + +} + +void KMdiDockContainer::showWidget( KDockWidget *w ) +{ + if ( !m_map.contains( w ) ) + return ; + + int id = m_map[ w ]; + m_tb->setTab( id, true ); + tabClicked( id ); +} + +void KMdiDockContainer::changeOverlapMode() +{ + const KDockButton_Private * btn = dynamic_cast<const KDockButton_Private*>( sender() ); + + if ( !btn ) + return ; + + if ( !btn->isOn() ) + { + kdDebug( 760 ) << k_funcinfo << "Activating overlap mode" << endl; + if ( !m_horizontal ) + activateOverlapMode( m_tb->width() ); + else + activateOverlapMode( m_tb->height() ); + + } + else + { + kdDebug( 760 ) << k_funcinfo << "Deactivating overlap mode" << endl; + deactivateOverlapMode(); + } + + QMap<KDockWidget*, KDockButton_Private*>::iterator it; + for ( it = m_overlapButtons.begin(); it != m_overlapButtons.end(); ++it ) + it.data()->setOn( !isOverlapMode() ); +} + +void KMdiDockContainer::hideIfNeeded() +{ + if ( itemNames.count() == 0 ) + { + kdDebug( 760 ) << k_funcinfo << "Hiding the dock container" << endl; + ( ( KDockWidget* ) parentWidget() )->undock(); + } +} + +void KMdiDockContainer::removeWidget( KDockWidget* dwdg ) +{ + KDockWidget * w = dwdg; + if ( !m_map.contains( w ) ) + return; //we don't have this widget in our container + + kdDebug( 760 ) << k_funcinfo << endl; + //lower the tab. ( TODO: needed? ) + int id = m_map[ w ]; + if ( m_tb->isTabRaised( id ) ) + { + m_tb->setTab( id, false ); + tabClicked( id ); + } + + m_tb->removeTab( id ); + m_ws->removeWidget( w ); + m_map.remove( w ); + m_revMap.remove( id ); + if ( m_overlapButtons.contains( w ) ) + { + ( static_cast<KDockWidgetHeader*>( w->getHeader() ->qt_cast( "KDockWidgetHeader" ) ) )->removeButton( m_overlapButtons[ w ] ); + m_overlapButtons.remove( w ); + } + KDockContainer::removeWidget( w ); + itemNames.remove( w->name() ); + tabCaptions.remove( w->name() ); + tabTooltips.remove( w->name() ); + hideIfNeeded(); +} + +void KMdiDockContainer::undockWidget( KDockWidget *dwdg ) +{ + KDockWidget * w = dwdg; + + if ( !m_map.contains( w ) ) + return ; + + int id = m_map[ w ]; + if ( m_tb->isTabRaised( id ) ) + { + kdDebug( 760 ) << k_funcinfo << "Widget has been undocked, setting tab down" << endl; + m_tb->setTab( id, false ); + tabClicked( id ); + } +} + +void KMdiDockContainer::tabClicked( int t ) +{ + bool call_makeVisible = !m_tabSwitching; + m_tabSwitching = true; + if ( m_tb->isTabRaised( t ) ) + { + kdDebug( 760 ) << k_funcinfo << "Tab " << t << " was just activated" << endl; + if ( m_ws->isHidden() ) + { + kdDebug( 760 ) << k_funcinfo << "Showing widgetstack for tab just clicked" << endl; + m_ws->show(); + parentDockWidget()->restoreFromForcedFixedSize(); + } + + if ( !m_ws->widget( t ) ) + { + kdDebug( 760 ) << k_funcinfo << "Widget tab was clicked for is not in our stack" << endl; + kdDebug( 760 ) << k_funcinfo << "Docking it back in" << endl; + m_revMap[t]->manualDock( parentDockWidget(), KDockWidget::DockCenter, 20 ); + if ( call_makeVisible ) + m_revMap[t]->makeDockVisible(); + m_tabSwitching = false; + emit activated( this ); + return ; + } + + if ( m_ws->widget( t ) ) + { + m_ws->raiseWidget( t ); + KDockWidget * tmpDw = static_cast<KDockWidget*>( m_ws->widget( t )->qt_cast( "KDockWidget" ) ); + if ( tmpDw ) + { + if ( tmpDw->getWidget() ) + tmpDw->getWidget()->setFocus(); + } + else + kdDebug( 760 ) << k_funcinfo << "Something really weird is going on" << endl; + } + else + kdDebug( 760 ) << k_funcinfo << "We have no widget to handle in our stack." << endl; + + if ( oldtab != t ) + m_tb->setTab( oldtab, false ); + + m_tabSwitching = true; + oldtab = t; + emit activated( this ); + } + else + { + kdDebug( 760 ) << k_funcinfo << "Tab " << t << " was just deactiviated" << endl; + // try save splitter position + if ( parentDockWidget() && parentDockWidget()->parent() ) + { + KDockSplitter * sp = static_cast<KDockSplitter*>( parentDockWidget()->parent()->qt_cast( "KDockSplitter" ) ); + if ( sp ) + m_separatorPos = sp->separatorPos(); + } + m_previousTab = t; + // oldtab=-1; + if ( m_block ) + return ; + emit deactivated( this ); + m_block = true; + if ( m_ws->widget( t ) ) + { + // ((KDockWidget*)m_ws->widget(t))->undock(); + } + m_block = false; + m_ws->hide (); + + + kdDebug( 760 ) << k_funcinfo << "Fixed Width:" << m_tb->width() << endl; + if ( !m_horizontal ) + parentDockWidget()->setForcedFixedWidth( m_tb->width() ); // strange why it worked before at all + else + parentDockWidget()->setForcedFixedHeight( m_tb->height() ); // strange why it worked before at all + } + m_tabSwitching = false; +} + +void KMdiDockContainer::setToolTip ( KDockWidget* w, QString &s ) +{ + kdDebug( 760 ) << k_funcinfo << "Setting tooltip '" << s << "' for widget " << w << endl; + int tabId = m_map[w]; + KMultiTabBarTab *mbTab = m_tb->tab( tabId ); + QToolTip::remove( mbTab ); + QToolTip::add( mbTab, s ); +} + +void KMdiDockContainer::setPixmap( KDockWidget* widget , const QPixmap& pixmap ) +{ + int id = m_ws->id( widget ); + if ( id == -1 ) + return ; + KMultiTabBarTab *tab = m_tb->tab( id ); + tab->setIcon( pixmap.isNull() ? SmallIcon( "misc" ) : pixmap ); +} + +void KMdiDockContainer::save( QDomElement& dockEl ) +{ + QDomDocument doc = dockEl.ownerDocument(); + QDomElement el; + el = doc.createElement( "name" ); + el.appendChild( doc.createTextNode( QString( "%1" ).arg( parent() ->name() ) ) ); + dockEl.appendChild( el ); + el = doc.createElement( "overlapMode" ); + el.appendChild( doc.createTextNode( isOverlapMode() ? "true" : "false" ) ); + dockEl.appendChild( el ); + QPtrList<KMultiTabBarTab>* tl = m_tb->tabs(); + QPtrListIterator<KMultiTabBarTab> it( *tl ); + QStringList::Iterator it2 = itemNames.begin(); + int i = 0; + for ( ;it.current() != 0;++it, ++it2 ) + { + el = doc.createElement( "child" ); + el.setAttribute( "pos", QString( "%1" ).arg( i ) ); + QString s = tabCaptions[ *it2 ]; + if ( !s.isEmpty() ) + { + el.setAttribute( "tabCaption", s ); + } + s = tabTooltips[ *it2 ]; + if ( !s.isEmpty() ) + { + el.setAttribute( "tabTooltip", s ); + } + el.appendChild( doc.createTextNode( *it2 ) ); + dockEl.appendChild( el ); + if ( m_tb->isTabRaised( it.current() ->id() ) ) + { + QDomElement el2 = doc.createElement( "raised" ); + el2.appendChild( doc.createTextNode( m_ws->widget( it.current() ->id() ) ->name() ) ); + el.appendChild( el2 ); + } + ++i; + } + + +} + +void KMdiDockContainer::load( QDomElement& dockEl ) +{ + QString raise; + + for ( QDomNode n = dockEl.firstChild();!n.isNull();n = n.nextSibling() ) + { + QDomElement el = n.toElement(); + if ( el.isNull() ) + continue; + if ( el.tagName() == "overlapMode" ) + { + if ( el.attribute( "overlapMode" ) != "false" ) + activateOverlapMode( m_tb->width() ); + else + deactivateOverlapMode(); + } + else if ( el.tagName() == "child" ) + { + KDockWidget * dw = ( ( KDockWidget* ) parent() ) ->dockManager() ->getDockWidgetFromName( el.text() ); + if ( dw ) + { + if ( el.hasAttribute( "tabCaption" ) ) + { + dw->setTabPageLabel( el.attribute( "tabCaption" ) ); + } + if ( el.hasAttribute( "tabTooltip" ) ) + { + dw->setToolTipString( el.attribute( "tabTooltip" ) ); + } + dw->manualDock( ( KDockWidget* ) parent(), KDockWidget::DockCenter ); + } + } + } + + QPtrList<KMultiTabBarTab>* tl = m_tb->tabs(); + QPtrListIterator<KMultiTabBarTab> it1( *tl ); + m_ws->hide(); + if ( !m_horizontal ) + parentDockWidget()->setForcedFixedWidth( m_tb->width() ); + else + parentDockWidget()->setForcedFixedHeight( m_tb->height() ); + + for ( ;it1.current() != 0;++it1 ) + m_tb->setTab( it1.current() ->id(), false ); + + kapp->syncX(); + m_delayedRaise = -1; + + for ( QMap<KDockWidget*, KDockButton_Private*>::iterator it = m_overlapButtons.begin(); + it != m_overlapButtons.end();++it ) + it.data() ->setOn( !isOverlapMode() ); + + if ( !raise.isEmpty() ) + { + for ( QMap<KDockWidget*, int>::iterator it = m_map.begin();it != m_map.end();++it ) + { + if ( it.key() ->name() == raise ) + { + m_delayedRaise = it.data(); + QTimer::singleShot( 0, this, SLOT( delayedRaise() ) ); + kdDebug( 760 ) << k_funcinfo << "raising " << it.key()->name() << endl; + break; + } + } + + } + if ( m_delayedRaise == -1 ) + QTimer::singleShot( 0, this, SLOT( init() ) ); +} + +void KMdiDockContainer::save( KConfig* cfg, const QString& group_or_prefix ) +{ + QString grp = cfg->group(); + cfg->deleteGroup( group_or_prefix + QString( "::%1" ).arg( parent() ->name() ) ); + cfg->setGroup( group_or_prefix + QString( "::%1" ).arg( parent() ->name() ) ); + + if ( isOverlapMode() ) + cfg->writeEntry( "overlapMode", "true" ); + else + cfg->writeEntry( "overlapMode", "false" ); + + // try to save the splitter position + if ( parentDockWidget() && parentDockWidget() ->parent() ) + { + KDockSplitter * sp = static_cast<KDockSplitter*>( parentDockWidget() -> + parent() ->qt_cast( "KDockSplitter" ) ); + if ( sp ) + cfg->writeEntry( "separatorPos", m_separatorPos ); + } + + QPtrList<KMultiTabBarTab>* tl = m_tb->tabs(); + QPtrListIterator<KMultiTabBarTab> it( *tl ); + QStringList::Iterator it2 = itemNames.begin(); + int i = 0; + for ( ;it.current() != 0;++it, ++it2 ) + { + // cfg->writeEntry(QString("widget%1").arg(i),m_ws->widget(it.current()->id())->name()); + cfg->writeEntry( QString( "widget%1" ).arg( i ), ( *it2 ) ); + QString s = tabCaptions[ *it2 ]; + if ( !s.isEmpty() ) + { + cfg->writeEntry( QString( "widget%1-tabCaption" ).arg( i ), s ); + } + s = tabTooltips[ *it2 ]; + if ( !s.isEmpty() ) + { + cfg->writeEntry( QString( "widget%1-tabTooltip" ).arg( i ), s ); + } + // kdDebug(760)<<"****************************************Saving: "<<m_ws->widget(it.current()->id())->name()<<endl; + if ( m_tb->isTabRaised( it.current() ->id() ) ) + cfg->writeEntry( m_ws->widget( it.current() ->id() ) ->name(), true ); + ++i; + } + cfg->sync(); + cfg->setGroup( grp ); + +} + +void KMdiDockContainer::load( KConfig* cfg, const QString& group_or_prefix ) +{ + QString grp = cfg->group(); + cfg->setGroup( group_or_prefix + QString( "::%1" ).arg( parent() ->name() ) ); + + if ( cfg->readEntry( "overlapMode" ) != "false" ) + activateOverlapMode( m_tb->width() ); + else + deactivateOverlapMode(); + + m_separatorPos = cfg->readNumEntry( "separatorPos", 18 ); + + int i = 0; + QString raise; + while ( true ) + { + QString dwn = cfg->readEntry( QString( "widget%1" ).arg( i ) ); + if ( dwn.isEmpty() ) + break; + kdDebug( 760 ) << k_funcinfo << "configuring dockwidget :" << dwn << endl; + KDockWidget *dw = ( ( KDockWidget* ) parent() ) ->dockManager() ->getDockWidgetFromName( dwn ); + if ( dw ) + { + QString s = cfg->readEntry( QString( "widget%1-tabCaption" ).arg( i ) ); + if ( !s.isEmpty() ) + { + dw->setTabPageLabel( s ); + } + s = cfg->readEntry( QString( "widget%1-tabTooltip" ).arg( i ) ); + if ( !s.isEmpty() ) + { + dw->setToolTipString( s ); + } + dw->manualDock( ( KDockWidget* ) parent(), KDockWidget::DockCenter ); + } + if ( cfg->readBoolEntry( dwn, false ) ) + raise = dwn; + i++; + + } + + QPtrList<KMultiTabBarTab>* tl = m_tb->tabs(); + QPtrListIterator<KMultiTabBarTab> it1( *tl ); + m_ws->hide(); + if ( !m_horizontal ) + parentDockWidget() ->setForcedFixedWidth( m_tb->width() ); + else + parentDockWidget() ->setForcedFixedHeight( m_tb->height() ); + for ( ;it1.current() != 0;++it1 ) + { + m_tb->setTab( it1.current() ->id(), false ); + } + kapp->syncX(); + m_delayedRaise = -1; + + for ( QMap<KDockWidget*, KDockButton_Private*>::iterator it = m_overlapButtons.begin(); + it != m_overlapButtons.end();++it ) + it.data() ->setOn( !isOverlapMode() ); + + if ( !raise.isEmpty() ) + { + for ( QMap<KDockWidget*, int>::iterator it = m_map.begin();it != m_map.end();++it ) + { + if ( it.key() ->name() == raise ) + { + /* tabClicked(it.data()); + m_tb->setTab(it.data(),true); + tabClicked(it.data()); + m_ws->raiseWidget(it.key()); + kapp->sendPostedEvents(); + kapp->syncX();*/ + + m_delayedRaise = it.data(); + QTimer::singleShot( 0, this, SLOT( delayedRaise() ) ); + kdDebug( 760 ) << k_funcinfo << "raising" << it.key() ->name() << endl; + break; + } + } + + } + if ( m_delayedRaise == -1 ) + QTimer::singleShot( 0, this, SLOT( init() ) ); + cfg->setGroup( grp ); + +} + +void KMdiDockContainer::delayedRaise() +{ + m_tb->setTab( m_delayedRaise, true ); + tabClicked( m_delayedRaise ); +} + +void KMdiDockContainer::collapseOverlapped() +{ + //don't collapse if we're switching tabs + if ( m_tabSwitching ) + return; + + if ( isOverlapMode() ) + { + QPtrList<KMultiTabBarTab>* tl = m_tb->tabs(); + QPtrListIterator<KMultiTabBarTab> it( *tl ); + for ( ;it.current();++it ) + { + if ( it.current()->isOn() ) + { + kdDebug( 760 ) << k_funcinfo << "lowering tab with id " << ( *it )->id() << endl; + it.current()->setState( false ); + tabClicked( ( *it )->id() ); + } + } + } +} + +void KMdiDockContainer::toggle() +{ + kdDebug( 760 ) << k_funcinfo << endl; + + if ( m_tb->isTabRaised( oldtab ) ) + { + kdDebug( 760 ) << k_funcinfo << "lowering tab" << endl; + m_tb->setTab( oldtab, false ); + tabClicked( oldtab ); + KMdiMainFrm *mainFrm = dynamic_cast<KMdiMainFrm*>( m_mainWin ); + if ( mainFrm && mainFrm->activeWindow() ) + mainFrm->activeWindow()->setFocus(); + } + else + { + kdDebug( 760 ) << k_funcinfo << "raising tab" << endl; + if ( m_tb->tab( m_previousTab ) == 0 ) + { + if ( m_tb->tabs() ->count() == 0 ) + return ; + + m_previousTab = m_tb->tabs() ->getFirst() ->id(); + } + m_tb->setTab( m_previousTab, true ); + tabClicked( m_previousTab ); + } +} + +void KMdiDockContainer::prevToolView() +{ + kdDebug( 760 ) << k_funcinfo << endl; + QPtrList<KMultiTabBarTab>* tabs = m_tb->tabs(); + int pos = tabs->findRef( m_tb->tab( oldtab ) ); + + if ( pos == -1 ) + return ; + + pos--; + if ( pos < 0 ) + pos = tabs->count() - 1; + + KMultiTabBarTab *tab = tabs->at( pos ); + if ( !tab ) + return ; //can never happen here, but who knows + + m_tb->setTab( tab->id(), true ); + tabClicked( tab->id() ); +} + +void KMdiDockContainer::nextToolView() +{ + kdDebug( 760 ) << k_funcinfo << endl; + QPtrList<KMultiTabBarTab>* tabs = m_tb->tabs(); + int pos = tabs->findRef( m_tb->tab( oldtab ) ); + + if ( pos == -1 ) + return ; + + pos++; + if ( pos >= ( int ) tabs->count() ) + pos = 0; + + KMultiTabBarTab *tab = tabs->at( pos ); + if ( !tab ) + return ; //can never happen here, but who knows + + m_tb->setTab( tab->id(), true ); + tabClicked( tab->id() ); +} + +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; diff --git a/lib/compatibility/kmdi/qextmdi/kmdidockcontainer.h b/lib/compatibility/kmdi/qextmdi/kmdidockcontainer.h new file mode 100644 index 00000000..917dac4d --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmdidockcontainer.h @@ -0,0 +1,167 @@ + /* This file is part of the KDE project + Copyright (C) 2002 Christoph Cullmann <cullmann@kde.org> + Copyright (C) 2002,2003 Joseph Wenninger <jowenn@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 version 2 as published by the Free Software Foundation. + + 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. +*/ + +#ifndef _KMDI_DOCK_CONTAINER_ +#define _KMDI_DOCK_CONTAINER_ + +#include <qwidget.h> +#include <qstringlist.h> +#include <kdockwidget.h> +#include <qmap.h> +#include <qdom.h> + +# include <kdockwidget_p.h> + +#include <qpushbutton.h> + +class QWidgetStack; +class KMultiTabBar; +class KDockButton_Private; + +class KMDI_EXPORT KMdiDockContainer: public QWidget, public KDockContainer +{ + Q_OBJECT + +public: + KMdiDockContainer( QWidget *parent, QWidget *win, int position, int flags ); + virtual ~KMdiDockContainer(); + + /** Get the KDockWidget that is our parent */ + KDockWidget *parentDockWidget(); + + /** + * Add a widget to this container + * \param w the KDockWidget we are adding + */ + virtual void insertWidget ( KDockWidget *w, QPixmap, const QString &, int & ); + + /** + * Show a widget. + * + * The widget has to belong to this container otherwise + * it will not be shown + * \param w the KDockWidget to show + */ + virtual void showWidget ( KDockWidget *w ); + + /** + * Set the tooltip for the widget. + * Currently, this method does nothing + */ + virtual void setToolTip ( KDockWidget *, QString & ); + + /** + * Set the pixmap for the widget. + */ + virtual void setPixmap( KDockWidget* widget, const QPixmap& pixmap ); + + /** + * Undock the widget from the container. + */ + virtual void undockWidget( KDockWidget* dwdg ); + + /** + * Remove a widget from the container. The caller of this function + * is responsible for deleting the widget + */ + virtual void removeWidget( KDockWidget* ); + + /** + * Hide the the dock container if the number of items is 0 + */ + void hideIfNeeded(); + + /** + * Save the config using a KConfig object + * + * The combination of the group_or_prefix variable and the parent + * dockwidget's name will be the group the configuration is saved in + * \param group_or_prefix the prefix to append to the parent dockwidget's name + */ + virtual void save( KConfig *, const QString& group_or_prefix ); + + /** + * Load the config using a KConfig object + * + * The combination of the group_or_prefix variable and the parent + * dockwidget's name will be the group the configuration is loaded from + * \param group_or_prefix the prefix to append to the parent dockwidget's name + */ + virtual void load( KConfig *, const QString& group_or_prefix ); + + /** + * Save the config to a QDomElement + */ + virtual void save( QDomElement& ); + + /** + * Load the config from a QDomElement + */ + virtual void load( QDomElement& ); + + /** + * Set the style for the tabbar + */ + void setStyle( int ); + +protected: + bool eventFilter( QObject*, QEvent* ); + +public slots: + void init(); + void collapseOverlapped(); + void toggle(); + void nextToolView(); + void prevToolView(); +protected slots: + void tabClicked( int ); + void delayedRaise(); + void changeOverlapMode(); +private: + QWidget *m_mainWin; + QWidgetStack *m_ws; + KMultiTabBar *m_tb; + int mTabCnt; + int oldtab; + int m_previousTab; + int m_position; + int m_separatorPos; + QMap<KDockWidget*, int> m_map; + QMap<int, KDockWidget*> m_revMap; + QMap<KDockWidget*, KDockButton_Private*> m_overlapButtons; + QStringList itemNames; + QMap<QString, QString> tabCaptions; + QMap<QString, QString> tabTooltips; + int m_inserted; + int m_delayedRaise; + bool m_horizontal; + bool m_block; + bool m_tabSwitching; + QObject *m_dragPanel; + KDockManager *m_dockManager; + QMouseEvent *m_startEvent; + enum MovingState {NotMoving = 0, WaitingForMoveStart, Moving} m_movingState; +signals: + void activated( KMdiDockContainer* ); + void deactivated( KMdiDockContainer* ); +}; + +#endif + +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; diff --git a/lib/compatibility/kmdi/qextmdi/kmdidocumentviewtabwidget.cpp b/lib/compatibility/kmdi/qextmdi/kmdidocumentviewtabwidget.cpp new file mode 100644 index 00000000..8b88fb2c --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmdidocumentviewtabwidget.cpp @@ -0,0 +1,152 @@ +//---------------------------------------------------------------------------- +// +// This program 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. +// +//---------------------------------------------------------------------------- + +#include <ktabbar.h> +#include <kpopupmenu.h> +#include "kmdidocumentviewtabwidget.h" + +KMdiDocumentViewTabWidget::KMdiDocumentViewTabWidget( QWidget* parent, const char* name ) : KTabWidget( parent, name ) +{ + m_visibility = KMdi::ShowWhenMoreThanOneTab; + tabBar() ->hide(); +#ifndef Q_WS_WIN //todo + + setHoverCloseButton( true ); +#endif + + connect( this, SIGNAL( closeRequest( QWidget* ) ), this, SLOT( closeTab( QWidget* ) ) ); +} + +KMdiDocumentViewTabWidget::~KMdiDocumentViewTabWidget() +{} + +void KMdiDocumentViewTabWidget::closeTab( QWidget* w ) +{ + w->close(); +} +void KMdiDocumentViewTabWidget::addTab ( QWidget * child, const QString & label ) +{ + KTabWidget::addTab( child, label ); + showPage( child ); + maybeShow(); +} + +void KMdiDocumentViewTabWidget::addTab ( QWidget * child, const QIconSet & iconset, const QString & label ) +{ + KTabWidget::addTab( child, iconset, label ); + showPage( child ); + maybeShow(); +} + +void KMdiDocumentViewTabWidget::addTab ( QWidget * child, QTab * tab ) +{ + KTabWidget::addTab( child, tab ); + showPage( child ); + maybeShow(); +} + +void KMdiDocumentViewTabWidget::insertTab ( QWidget * child, const QString & label, int index ) +{ + KTabWidget::insertTab( child, label, index ); + showPage( child ); + maybeShow(); + tabBar() ->repaint(); +} + +void KMdiDocumentViewTabWidget::insertTab ( QWidget * child, const QIconSet & iconset, const QString & label, int index ) +{ + KTabWidget::insertTab( child, iconset, label, index ); + showPage( child ); + maybeShow(); + tabBar() ->repaint(); +} + +void KMdiDocumentViewTabWidget::insertTab ( QWidget * child, QTab * tab, int index ) +{ + KTabWidget::insertTab( child, tab, index ); + showPage( child ); + maybeShow(); + tabBar() ->repaint(); +} + +void KMdiDocumentViewTabWidget::removePage ( QWidget * w ) +{ + KTabWidget::removePage( w ); + maybeShow(); +} + +void KMdiDocumentViewTabWidget::updateIconInView( QWidget *w, QPixmap icon ) +{ + changeTab( w, icon, tabLabel( w ) ); +} + +void KMdiDocumentViewTabWidget::updateCaptionInView( QWidget *w, const QString &caption ) +{ + changeTab( w, caption ); +} + +void KMdiDocumentViewTabWidget::maybeShow() +{ + if ( m_visibility == KMdi::AlwaysShowTabs ) + { + tabBar() ->show(); + if ( cornerWidget() ) + { + if ( count() == 0 ) + cornerWidget() ->hide(); + else + cornerWidget() ->show(); + } + } + + if ( m_visibility == KMdi::ShowWhenMoreThanOneTab ) + { + if ( count() < 2 ) + tabBar() ->hide(); + if ( count() > 1 ) + tabBar() ->show(); + if ( cornerWidget() ) + { + if ( count() < 2 ) + cornerWidget() ->hide(); + else + cornerWidget() ->show(); + } + } + + if ( m_visibility == KMdi::NeverShowTabs ) + { + tabBar() ->hide(); + } +} + +void KMdiDocumentViewTabWidget::setTabWidgetVisibility( KMdi::TabWidgetVisibility visibility ) +{ + m_visibility = visibility; + maybeShow(); +} + +void KMdiDocumentViewTabWidget::moveTab( int from, int to ) +{ + emit initiateTabMove( from, to ); + KTabWidget::moveTab( from, to ); +} + +KMdi::TabWidgetVisibility KMdiDocumentViewTabWidget::tabWidgetVisibility( ) +{ + return m_visibility; +} + + +#ifndef NO_INCLUDE_MOCFILES +#include "kmdidocumentviewtabwidget.moc" +#endif + +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; + diff --git a/lib/compatibility/kmdi/qextmdi/kmdidocumentviewtabwidget.h b/lib/compatibility/kmdi/qextmdi/kmdidocumentviewtabwidget.h new file mode 100644 index 00000000..b745bfa3 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmdidocumentviewtabwidget.h @@ -0,0 +1,123 @@ +//---------------------------------------------------------------------------- +// +// This program 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. +// +//---------------------------------------------------------------------------- + +#ifndef _KMDI_DOCUMENT_VIEW_TAB_WIDGET_H_ +#define _KMDI_DOCUMENT_VIEW_TAB_WIDGET_H_ + +#include <ktabwidget.h> +#include <kmdidefines.h> + +class KPopupMenu; + +//KDE4: Add a d pointer +/** + * A reimplementation of KTabWidget for KMDI + */ +class KMDI_EXPORT KMdiDocumentViewTabWidget: + public KTabWidget +{ + Q_OBJECT +public: + KMdiDocumentViewTabWidget( QWidget* parent, const char* name = 0 ); + ~KMdiDocumentViewTabWidget(); + + /** + * Add a tab into the tabwidget + * \sa QTabWidget + * \sa KTabWidget + */ + virtual void addTab ( QWidget * child, const QString & label ); + + /** + * Add a tab into the tabwidget + * \sa QTabWidget + * \sa KTabWidget + */ + virtual void addTab ( QWidget * child, const QIconSet & iconset, const QString & label ); + + /** + * Add a tab into the tabwidget + * \sa QTabWidget + * \sa KTabWidget + */ + virtual void addTab ( QWidget * child, QTab * tab ); + + /** + * Insert a tab into the tabwidget with a label + * \sa QTabWidget + * \sa KTabWidget + */ + virtual void insertTab ( QWidget * child, const QString & label, int index = -1 ); + + /** + * Inserts a tab into the tabwidget with an icon and label + * \sa QTabWidget + * \sa KTabWidget + */ + virtual void insertTab ( QWidget * child, const QIconSet & iconset, const QString & label, int index = -1 ); + + /** + * Inserts a tab into the tabwidget + * \sa QTabWidget + * \sa KTabWidget + */ + virtual void insertTab ( QWidget * child, QTab * tab, int index = -1 ); + + /** + * Removes the tab from the tabwidget + * \sa QTabWidget + * \sa KTabWidget + */ + virtual void removePage ( QWidget * w ); + + /** + * Set the tab widget's visibility and then make the change + * to match the new setting + */ + KMdi::TabWidgetVisibility tabWidgetVisibility(); + + /** Get the tab widget's visibility */ + void setTabWidgetVisibility( KMdi::TabWidgetVisibility ); + +private slots: + + /** Close the tab specified by w */ + void closeTab( QWidget* w ); + + /** Moves a tab. Reimplemented for internal reasons. */ + void moveTab( int from, int to ); + +public slots: + + /** Change the icon for the tab */ + void updateIconInView( QWidget*, QPixmap ); + + /** Change the caption for the tab */ + void updateCaptionInView( QWidget*, const QString& ); + +private: + + /** + * Determine whether or not we should show the tab bar + * The tab bar is hidden if it's determined that it should be hidden + * and shown if it's determined that it should be shown + */ + void maybeShow(); + + KMdi::TabWidgetVisibility m_visibility; + +signals: + void initiateTabMove(int, int); +}; + + + +#endif +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; + diff --git a/lib/compatibility/kmdi/qextmdi/kmdifocuslist.cpp b/lib/compatibility/kmdi/qextmdi/kmdifocuslist.cpp new file mode 100644 index 00000000..c5a7578c --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmdifocuslist.cpp @@ -0,0 +1,75 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Joseph Wenninger <jowenn@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 version 2 as published by the Free Software Foundation. + + 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 "kmdifocuslist.h" +#include "kmdifocuslist.moc" +#include <qobjectlist.h> +#include <kdebug.h> + +KMdiFocusList::KMdiFocusList( QObject *parent ) : QObject( parent ) +{} + +KMdiFocusList::~KMdiFocusList() +{} + +void KMdiFocusList::addWidgetTree( QWidget* w ) +{ + //this method should never be called twice on the same hierarchy + m_list.insert( w, w->focusPolicy() ); + w->setFocusPolicy( QWidget::ClickFocus ); + kdDebug( 760 ) << "KMdiFocusList::addWidgetTree: adding toplevel" << endl; + connect( w, SIGNAL( destroyed( QObject * ) ), this, SLOT( objectHasBeenDestroyed( QObject* ) ) ); + QObjectList *l = w->queryList( "QWidget" ); + QObjectListIt it( *l ); + QObject *obj; + while ( ( obj = it.current() ) != 0 ) + { + QWidget * wid = ( QWidget* ) obj; + m_list.insert( wid, wid->focusPolicy() ); + wid->setFocusPolicy( QWidget::ClickFocus ); + kdDebug( 760 ) << "KMdiFocusList::addWidgetTree: adding widget" << endl; + connect( wid, SIGNAL( destroyed( QObject * ) ), this, SLOT( objectHasBeenDestroyed( QObject* ) ) ); + ++it; + } + delete l; +} + +void KMdiFocusList::restore() +{ +#if (QT_VERSION-0 >= 0x030200) + for ( QMap<QWidget*, QWidget::FocusPolicy>::const_iterator it = m_list.constBegin();it != m_list.constEnd();++it ) + { +#else + for ( QMap<QWidget*, QWidget::FocusPolicy>::iterator it = m_list.begin();it != m_list.end();++it ) + { +#endif + it.key() ->setFocusPolicy( it.data() ); + } + m_list.clear(); +} + + +void KMdiFocusList::objectHasBeenDestroyed( QObject * o ) +{ + if ( !o || !o->isWidgetType() ) + return ; + QWidget *w = ( QWidget* ) o; + m_list.remove( w ); +} + +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; diff --git a/lib/compatibility/kmdi/qextmdi/kmdifocuslist.h b/lib/compatibility/kmdi/qextmdi/kmdifocuslist.h new file mode 100644 index 00000000..fbc178d1 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmdifocuslist.h @@ -0,0 +1,42 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Joseph Wenninger <jowenn@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 version 2 as published by the Free Software Foundation. + + 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. +*/ +#ifndef KMDI_FOCUS_LIST +#define KMDI_FOCUS_LIST + +#include <qobject.h> +#include <qmap.h> +#include <qwidget.h> +#include <kdelibs_export.h> + +class KMDI_EXPORT KMdiFocusList: public QObject +{ + Q_OBJECT +public: + KMdiFocusList( QObject *parent ); + ~KMdiFocusList(); + void addWidgetTree( QWidget* ); + void restore(); +protected slots: + void objectHasBeenDestroyed( QObject* ); +private: + QMap<QWidget*, QWidget::FocusPolicy> m_list; + +}; + +#endif +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; diff --git a/lib/compatibility/kmdi/qextmdi/kmdiguiclient.cpp b/lib/compatibility/kmdi/qextmdi/kmdiguiclient.cpp new file mode 100644 index 00000000..ec00ec78 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmdiguiclient.cpp @@ -0,0 +1,320 @@ +/* This file is part of the KDE libraries + Copyright (C) 2003 Joseph Wenninger <jowenn@kde.org> + based on ktoolbarhandler.cpp: Copyright (C) 2002 Simon Hausmann <hausmann@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 version 2 as published by the Free Software Foundation. + + 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 "kmdiguiclient.h" +#include "kmdiguiclient.moc" + +#include <qpopupmenu.h> +#include <kapplication.h> +#include <kconfig.h> +#include <ktoolbar.h> +#include <kmainwindow.h> +#include <klocale.h> +#include <kaction.h> +#include <qstring.h> +#include <assert.h> +#include <kdebug.h> +#include <kdockwidget.h> +#include <kdeversion.h> +#include "kmdimainfrm.h" +#include "kmditoolviewaccessor.h" +#include "kmditoolviewaccessor_p.h" +namespace +{ +const char *actionListName = "show_kmdi_document_tool_view_actions"; + +const char *guiDescription = "" + "<!DOCTYPE kpartgui><kpartgui name=\"KMDIViewActions\">" + "<MenuBar>" + " <Menu name=\"view\">" + " <ActionList name=\"%1\" />" + " </Menu>" + "</MenuBar>" + "</kpartgui>"; + +const char *resourceFileName = "kmdiviewactions.rc"; + +} + + +using namespace KMDIPrivate; + + + +ToggleToolViewAction::ToggleToolViewAction( const QString& text, const KShortcut& cut, KDockWidget *dw, KMdiMainFrm *mdiMainFrm, + QObject* parent, const char* name ) + : KToggleAction( text, cut, parent, name ), m_dw( dw ), m_mdiMainFrm( mdiMainFrm ) +{ + if ( m_dw ) + { + connect( this, SIGNAL( toggled( bool ) ), this, SLOT( slotToggled( bool ) ) ); + connect( m_dw->dockManager(), SIGNAL( change() ), this, SLOT( anDWChanged() ) ); + connect( m_dw, SIGNAL( destroyed() ), this, SLOT( slotWidgetDestroyed() ) ); + setChecked( m_dw->mayBeHide() ); + } +} + + +ToggleToolViewAction::~ToggleToolViewAction() +{ + unplugAll(); +} + +void ToggleToolViewAction::anDWChanged() +{ + if ( isChecked() && m_dw->mayBeShow() ) + setChecked( false ); + else if ( ( !isChecked() ) && m_dw->mayBeHide() ) + setChecked( true ); + else if ( isChecked() && ( m_dw->parentDockTabGroup() && + ( ( static_cast<KDockWidget*>( m_dw->parentDockTabGroup() -> + parent() ->qt_cast( "KDockWidget" ) ) ) ->mayBeShow() ) ) ) + setChecked( false ); +} + + +void ToggleToolViewAction::slotToggled( bool t ) +{ + // m_mw->mainDock->setDockSite( KDockWidget::DockCorner ); + + if ( ( !t ) && m_dw->mayBeHide() ) + m_dw->undock(); + else + if ( t && m_dw->mayBeShow() ) + m_mdiMainFrm->makeDockVisible( m_dw ); + + // m_mw->mainDock->setDockSite( KDockWidget::DockNone ); +} + +void ToggleToolViewAction::slotWidgetDestroyed() +{ + disconnect( m_dw->dockManager(), SIGNAL( change() ), this, SLOT( anDWChanged() ) ); + disconnect( this, SIGNAL( toggled( bool ) ), 0, 0 ); + unplugAll(); + deleteLater(); +} + + +KMDIGUIClient::KMDIGUIClient( KMdiMainFrm* mdiMainFrm, bool showMDIModeAction, const char* name ) : QObject( mdiMainFrm, name ), + KXMLGUIClient( mdiMainFrm ) +{ + m_mdiMode = KMdi::ChildframeMode; + m_mdiMainFrm = mdiMainFrm; + connect( mdiMainFrm->guiFactory(), SIGNAL( clientAdded( KXMLGUIClient * ) ), + this, SLOT( clientAdded( KXMLGUIClient * ) ) ); + + /* re-use an existing resource file if it exists. can happen if the user launches the + * toolbar editor */ + /* + setXMLFile( resourceFileName ); + */ + + if ( domDocument().documentElement().isNull() ) + { + + QString completeDescription = QString::fromLatin1( guiDescription ) + .arg( actionListName ); + + setXML( completeDescription, false /*merge*/ ); + } + + if ( actionCollection() ->kaccel() == 0 ) + actionCollection() ->setWidget( mdiMainFrm ); + m_toolMenu = new KActionMenu( i18n( "Tool &Views" ), actionCollection(), "kmdi_toolview_menu" ); + if ( showMDIModeAction ) + { + m_mdiModeAction = new KSelectAction( i18n( "MDI Mode" ), 0, actionCollection() ); + QStringList modes; + modes << i18n( "&Toplevel Mode" ) << i18n( "C&hildframe Mode" ) << i18n( "Ta&b Page Mode" ) << i18n( "I&DEAl Mode" ); + m_mdiModeAction->setItems( modes ); + connect( m_mdiModeAction, SIGNAL( activated( int ) ), this, SLOT( changeViewMode( int ) ) ); + } + else + m_mdiModeAction = 0; + + connect( m_mdiMainFrm, SIGNAL( mdiModeHasBeenChangedTo( KMdi::MdiMode ) ), + this, SLOT( mdiModeHasBeenChangedTo( KMdi::MdiMode ) ) ); + + m_gotoToolDockMenu = new KActionMenu( i18n( "Tool &Docks" ), actionCollection(), "kmdi_tooldock_menu" ); + m_gotoToolDockMenu->insert( new KAction( i18n( "Switch Top Dock" ), ALT + CTRL + SHIFT + Key_T, this, SIGNAL( toggleTop() ), + actionCollection(), "kmdi_activate_top" ) ); + m_gotoToolDockMenu->insert( new KAction( i18n( "Switch Left Dock" ), ALT + CTRL + SHIFT + Key_L, this, SIGNAL( toggleLeft() ), + actionCollection(), "kmdi_activate_left" ) ); + m_gotoToolDockMenu->insert( new KAction( i18n( "Switch Right Dock" ), ALT + CTRL + SHIFT + Key_R, this, SIGNAL( toggleRight() ), + actionCollection(), "kmdi_activate_right" ) ); + m_gotoToolDockMenu->insert( new KAction( i18n( "Switch Bottom Dock" ), ALT + CTRL + SHIFT + Key_B, this, SIGNAL( toggleBottom() ), + actionCollection(), "kmdi_activate_bottom" ) ); + m_gotoToolDockMenu->insert( new KActionSeparator( actionCollection(), "kmdi_goto_menu_separator" ) ); + m_gotoToolDockMenu->insert( new KAction( i18n( "Previous Tool View" ), ALT + CTRL + Key_Left, m_mdiMainFrm, SLOT( prevToolViewInDock() ), + actionCollection(), "kmdi_prev_toolview" ) ); + m_gotoToolDockMenu->insert( new KAction( i18n( "Next Tool View" ), ALT + CTRL + Key_Right, m_mdiMainFrm, SLOT( nextToolViewInDock() ), + actionCollection(), "kmdi_next_toolview" ) ); + + actionCollection() ->readShortcutSettings( "Shortcuts", kapp->config() ); +} + +KMDIGUIClient::~KMDIGUIClient() +{ + + // actionCollection()->writeShortcutSettings( "KMDI Shortcuts", kapp->config() ); + for ( uint i = 0;i < m_toolViewActions.count();i++ ) + disconnect( m_toolViewActions.at( i ), 0, this, 0 ); + + m_toolViewActions.setAutoDelete( false ); + m_toolViewActions.clear(); + m_documentViewActions.setAutoDelete( false ); + m_documentViewActions.clear(); +} + +void KMDIGUIClient::changeViewMode( int id ) +{ + switch ( id ) + { + case 0: + m_mdiMainFrm->switchToToplevelMode(); + break; + case 1: + m_mdiMainFrm->switchToChildframeMode(); + break; + case 2: + m_mdiMainFrm->switchToTabPageMode(); + break; + case 3: + m_mdiMainFrm->switchToIDEAlMode(); + break; + default: + Q_ASSERT( 0 ); + } +} + +void KMDIGUIClient::setupActions() +{ + if ( !factory() || !m_mdiMainFrm ) + return ; + + // BarActionBuilder builder( actionCollection(), m_mainWindow, m_toolBars ); + + // if ( !builder.needsRebuild() ) + // return; + + + unplugActionList( actionListName ); + + // m_actions.setAutoDelete( true ); + // m_actions.clear(); + // m_actions.setAutoDelete( false ); + + // m_actions = builder.create(); + + // m_toolBars = builder.toolBars(); + + // m_toolViewActions.append(new KAction( "TESTKMDIGUICLIENT", QString::null, 0, + // this, SLOT(blah()),actionCollection(),"nothing")); + + QPtrList<KAction> addList; + if ( m_toolViewActions.count() < 3 ) + for ( uint i = 0;i < m_toolViewActions.count();i++ ) + addList.append( m_toolViewActions.at( i ) ); + else + addList.append( m_toolMenu ); + if ( m_mdiMode == KMdi::IDEAlMode ) + addList.append( m_gotoToolDockMenu ); + if ( m_mdiModeAction ) + addList.append( m_mdiModeAction ); + kdDebug( 760 ) << "KMDIGUIClient::setupActions: plugActionList" << endl; + plugActionList( actionListName, addList ); + + // connectToActionContainers(); +} + +void KMDIGUIClient::addToolView( KMdiToolViewAccessor* mtva ) +{ + kdDebug( 760 ) << "*****void KMDIGUIClient::addToolView(KMdiToolViewAccessor* mtva)*****" << endl; + // kdDebug()<<"name: "<<mtva->wrappedWidget()->name()<<endl; + QString aname = QString( "kmdi_toolview_" ) + mtva->wrappedWidget() ->name(); + + // try to read the action shortcut + KShortcut sc; + KConfig *cfg = kapp->config(); + QString _grp = cfg->group(); + cfg->setGroup( "Shortcuts" ); + // if ( cfg->hasKey( aname ) ) + sc = KShortcut( cfg->readEntry( aname, "" ) ); + cfg->setGroup( _grp ); + KAction *a = new ToggleToolViewAction( i18n( "Show %1" ).arg( mtva->wrappedWidget() ->caption() ), + /*QString::null*/sc, dynamic_cast<KDockWidget*>( mtva->wrapperWidget() ), + m_mdiMainFrm, actionCollection(), aname.latin1() ); +#if KDE_IS_VERSION(3,2,90) + + ( ( ToggleToolViewAction* ) a ) ->setCheckedState( i18n( "Hide %1" ).arg( mtva->wrappedWidget() ->caption() ) ); +#endif + + connect( a, SIGNAL( destroyed( QObject* ) ), this, SLOT( actionDeleted( QObject* ) ) ); + m_toolViewActions.append( a ); + m_toolMenu->insert( a ); + mtva->d->action = a; + + setupActions(); +} + +void KMDIGUIClient::actionDeleted( QObject* a ) +{ + m_toolViewActions.remove( static_cast<KAction*>( a ) ); + /* if (!m_toolMenu.isNull()) m_toolMenu->remove(static_cast<KAction*>(a));*/ + setupActions(); +} + + +void KMDIGUIClient::clientAdded( KXMLGUIClient *client ) +{ + if ( client == this ) + setupActions(); +} + + +void KMDIGUIClient::mdiModeHasBeenChangedTo( KMdi::MdiMode mode ) +{ + kdDebug( 760 ) << "KMDIGUIClient::mdiModeHasBennChangeTo" << endl; + m_mdiMode = mode; + if ( m_mdiModeAction ) + { + switch ( mode ) + { + case KMdi::ToplevelMode: + m_mdiModeAction->setCurrentItem( 0 ); + break; + case KMdi::ChildframeMode: + m_mdiModeAction->setCurrentItem( 1 ); + break; + case KMdi::TabPageMode: + m_mdiModeAction->setCurrentItem( 2 ); + break; + case KMdi::IDEAlMode: + m_mdiModeAction->setCurrentItem( 3 ); + break; + default: + Q_ASSERT( 0 ); + } + } + setupActions(); + +} + + +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; diff --git a/lib/compatibility/kmdi/qextmdi/kmdiguiclient.h b/lib/compatibility/kmdi/qextmdi/kmdiguiclient.h new file mode 100644 index 00000000..a52db681 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmdiguiclient.h @@ -0,0 +1,146 @@ +/* This file is part of the KDE libraries + Copyright (C) 2003 Joseph Wenninger + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + 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. +*/ + +#ifndef KMDIGUICLIENT_H +#define KMDIGUICLIENT_H + +#include <qobject.h> +#include <qguardedptr.h> +#include <kxmlguiclient.h> +#include <kaction.h> +#include "kmdidefines.h" + +class KMainWindow; +class KToolBar; +class KMdiToolViewAccessor; +class KMdiMainFrm; +class KDockWidget; + +namespace KMDIPrivate +{ + +/** + * A class derived from KXMLGUIClient that handles the various + * KMDI modes + */ +class KMDI_EXPORT KMDIGUIClient : public QObject, + public KXMLGUIClient +{ + Q_OBJECT +public: + + KMDIGUIClient( KMdiMainFrm *mdiMainFrm, bool showMDIModeAction, const char *name = 0 ); + virtual ~KMDIGUIClient(); + + /** + * Add a new tool view to this KMDIGUIClient. Reads the shortcut + * for the tool view from the KMDI application's config file and also + * adds a ToggleToolViewAction so that the visibility of the toolviews + * can be turned on and off + */ + void addToolView( KMdiToolViewAccessor* ); + +private slots: + + /** + * The XMLGUIClient factory has added an XMLGUI client. Plug our actions + * in if we're the client that's been added. + */ + void clientAdded( KXMLGUIClient *client ); + /** + * Plug in the various toggle actions we have into the tool views menu + */ + void setupActions(); + + /** + * Change the view mode. This will automatically change the view mode + * of the KMdiMainFrm associated with this KMDIGUIClient + */ + void changeViewMode( int id ); + + /** + * One of our tool view toggle actions has been deleted. Redo the + * tool views menu + */ + void actionDeleted( QObject* ); + + /** + * Updates the action that lets the user change the MDI mode to the + * correct value based on the current mode + */ + void mdiModeHasBeenChangedTo( KMdi::MdiMode ); + +signals: + /** Toggle the top tool dock */ + void toggleTop(); + + /** Toggle the left tool dock */ + void toggleLeft(); + + /** Toggle the right tool dock */ + void toggleRight(); + + /** Toggle the bottom tool dock */ + void toggleBottom(); + +private: + class KMDIGUIClientPrivate; + KMDIGUIClientPrivate *d; + KMdi::MdiMode m_mdiMode; + + QGuardedPtr<KMdiMainFrm> m_mdiMainFrm; + QPtrList<KAction> m_toolViewActions; + QPtrList<KAction> m_documentViewActions; + + KActionMenu *m_docMenu; + KActionMenu *m_toolMenu; + KSelectAction *m_mdiModeAction; + + KActionMenu *m_gotoToolDockMenu; +}; + +/** + * A KToggleAction specifically for toggling the showing + * or the hiding of a KMDI tool view + */ +class KMDI_EXPORT ToggleToolViewAction: public KToggleAction +{ + Q_OBJECT +public: + + ToggleToolViewAction( const QString& text, const KShortcut& cut = KShortcut(), KDockWidget *dw = 0, KMdiMainFrm *mdiMainFrm = 0, + QObject* parent = 0, const char* name = 0 ); + + virtual ~ToggleToolViewAction(); + +private: + + KDockWidget *m_dw; + KMdiMainFrm *m_mdiMainFrm; +protected slots: + + void slotToggled( bool ); + void anDWChanged(); + void slotWidgetDestroyed(); +}; + + +} + +#endif +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; diff --git a/lib/compatibility/kmdi/qextmdi/kmdiiterator.h b/lib/compatibility/kmdi/qextmdi/kmdiiterator.h new file mode 100644 index 00000000..6bb6f7ea --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmdiiterator.h @@ -0,0 +1,51 @@ +//---------------------------------------------------------------------------- +// filename : kmdiiterator.h +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 02/2000 by Massimo Morin +// changes : 02/2000 by Falk Brettschneider to create an +// - 06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// 2000-2003 maintained by the KDevelop project +// +// copyright : (C) 1999-2003 by Massimo Morin (mmorin@schedsys.com) +// and +// Falk Brettschneider +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program 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. +// +//---------------------------------------------------------------------------- + +#ifndef _KMDIITERATOR_H_ +#define _KMDIITERATOR_H_ + + +template <class Item> +class KMdiIterator +{ +public: + virtual ~KMdiIterator() {} + + virtual void first() = 0; + virtual void last() = 0; + virtual void next() = 0; + virtual void prev() = 0; + virtual bool isDone() const = 0; + virtual Item currentItem() const = 0; + +protected: + KMdiIterator() {} +} +; + +#endif // _KMDIITERATOR_H_ +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; + diff --git a/lib/compatibility/kmdi/qextmdi/kmdilistiterator.h b/lib/compatibility/kmdi/qextmdi/kmdilistiterator.h new file mode 100644 index 00000000..110fae7e --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmdilistiterator.h @@ -0,0 +1,61 @@ +//---------------------------------------------------------------------------- +// filename : kmdilistiterator.h +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 02/2000 by Massimo Morin +// changes : 02/2000 by Falk Brettschneider to create an +// - 06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// 2000-2003 maintained by the KDevelop project +// +// copyright : (C) 1999-2003 by Massimo Morin (mmorin@schedsys.com) +// and +// Falk Brettschneider +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program 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. +// +//---------------------------------------------------------------------------- + +#ifndef _KMDILISTITERATOR_H_ +#define _KMDILISTITERATOR_H_ + +#include <kmdiiterator.h> + +template <class I> +class QPtrList; +template <class I> +class QPtrListIterator; + +template <class Item> +class KMdiListIterator : public KMdiIterator<Item*> +{ +public: + KMdiListIterator( QPtrList<Item>& list ) + { + m_iterator = new QPtrListIterator<Item>( list ); + } + + virtual void first() { m_iterator->toFirst(); } + virtual void last() { m_iterator->toLast(); } + virtual void next() { ++( *m_iterator ); } + virtual void prev() { --( *m_iterator ); } + virtual bool isDone() const { return m_iterator->current() == NULL; } + virtual Item* currentItem() const { return m_iterator->current(); } + + virtual ~KMdiListIterator() { delete m_iterator; } + +private: + QPtrListIterator<Item> *m_iterator; +}; + +#endif // _KMDILISTITERATOR_H_ +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; + diff --git a/lib/compatibility/kmdi/qextmdi/kmdimainfrm.cpp b/lib/compatibility/kmdi/qextmdi/kmdimainfrm.cpp new file mode 100644 index 00000000..449ce6f9 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmdimainfrm.cpp @@ -0,0 +1,2941 @@ +//---------------------------------------------------------------------------- +// filename : kmdimainfrm.cpp +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 07/1999 by Szymon Stefanek as part of kvirc +// (an IRC application) +// changes : 09/1999 by Falk Brettschneider to create an +// - 06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// 2000-2003 maintained by the KDevelop project +// patches : 02/2000 by Massimo Morin (mmorin@schedsys.com) +// */2000 by Lars Beikirch (Lars.Beikirch@gmx.net) +// 01/2003 by Jens Zurheide (jens.zurheide@gmx.de) +// +// copyright : (C) 1999-2003 by Szymon Stefanek (stefanek@tin.it) +// and +// Falk Brettschneider +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program 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. +// +//---------------------------------------------------------------------------- + + +/* + * ATTENTION: please do you part to try to make this file legible. It's + * extremely hard to read already. Especially follow the indenting rules. + */ +#include "config.h" + +#include <assert.h> + +#include <qcursor.h> +#include <qclipboard.h> +#include <qobjectlist.h> +#include <qpopupmenu.h> +#include <qmenubar.h> + +#include <kmenubar.h> +#include <kapplication.h> +#include <kdebug.h> +#include <kdeversion.h> +#include <qtabwidget.h> +#include <klocale.h> + +#include <kiconloader.h> +#include <kmdidockcontainer.h> + + +#include <qtoolbutton.h> +#include <qdockarea.h> +#include <qlayout.h> +#include <qtimer.h> +#include <qtextstream.h> +#include <qstring.h> +#include <qmap.h> +#include <qvaluelist.h> + +#include "kmdimainfrm.h" +#include "kmditaskbar.h" +#include "kmdichildfrm.h" +#include "kmdichildarea.h" +#include "kmdichildview.h" +#include "kmdidockcontainer.h" +#include "kmditoolviewaccessor_p.h" +#include "kmdifocuslist.h" +#include "kmdidocumentviewtabwidget.h" +#include "kmdiguiclient.h" + +#include "win_undockbutton.xpm" +#include "win_minbutton.xpm" +#include "win_restorebutton.xpm" +#include "win_closebutton.xpm" +#include "kde_undockbutton.xpm" +#include "kde_minbutton.xpm" +#include "kde_restorebutton.xpm" +#include "kde_closebutton.xpm" +#include "kde2_undockbutton.xpm" +#include "kde2_minbutton.xpm" +#include "kde2_restorebutton.xpm" +#include "kde2_closebutton.xpm" +#include "kde2laptop_undockbutton.xpm" +#include "kde2laptop_minbutton.xpm" +#include "kde2laptop_restorebutton.xpm" +#include "kde2laptop_closebutton.xpm" +#include "kde2laptop_closebutton_menu.xpm" + +#ifdef Q_WS_X11 +#ifndef NO_KDE +#include <X11/X.h> // schroder +#include <X11/Xlib.h> // schroder +#endif + +#ifdef KeyRelease +/* I hate the defines in the X11 header files. Get rid of one of them */ +#undef KeyRelease +#endif + +#ifdef KeyPress +/* I hate the defines in the X11 header files. Get rid of one of them */ +#undef KeyPress +#endif +#endif // Q_WS_X11 && ! K_WS_QTONLY + +using namespace KParts; + +KMdi::FrameDecor KMdiMainFrm::m_frameDecoration = KMdi::KDELook; + +class KMdiMainFrmPrivate +{ +public: + KMdiMainFrmPrivate() : focusList( 0 ) + { + for ( int i = 0;i < 4;i++ ) + { + activeDockPriority[ i ] = 0; + m_styleIDEAlMode = 0; + m_toolviewStyle = 0; + } + } + ~KMdiMainFrmPrivate() + {} + KMdiDockContainer* activeDockPriority[ 4 ]; + KMdiFocusList *focusList; + int m_styleIDEAlMode; + int m_toolviewStyle; + KAction *closeWindowAction; +}; + +//============ constructor ============// +KMdiMainFrm::KMdiMainFrm( QWidget* parentWidget, const char* name, KMdi::MdiMode mdiMode, WFlags flags ) + : KParts::DockMainWindow( parentWidget, name, flags ) + , m_mdiMode( KMdi::UndefinedMode ) + , m_pMdi( 0L ) + , m_pTaskBar( 0L ) + , m_pDocumentViews( 0L ) + , m_pCurrentWindow( 0L ) + , m_pWindowPopup( 0L ) + , m_pTaskBarPopup( 0L ) + , m_pWindowMenu( 0L ) + , m_pDockMenu( 0L ) + , m_pMdiModeMenu( 0L ) + , m_pPlacingMenu( 0L ) + , m_pMainMenuBar( 0L ) + , m_pUndockButtonPixmap( 0L ) + , m_pMinButtonPixmap( 0L ) + , m_pRestoreButtonPixmap( 0L ) + , m_pCloseButtonPixmap( 0L ) + , m_pUndock( 0L ) + , m_pMinimize( 0L ) + , m_pRestore( 0L ) + , m_pClose( 0L ) + , m_bMaximizedChildFrmMode( false ) + , m_oldMainFrmHeight( 0 ) + , m_oldMainFrmMinHeight( 0 ) + , m_oldMainFrmMaxHeight( 0 ) + , m_bSDIApplication( false ) + , m_pDockbaseAreaOfDocumentViews( 0L ) + , m_pTempDockSession( 0L ) + , m_bClearingOfWindowMenuBlocked( false ) + , m_pDragEndTimer( 0L ) + , m_bSwitching( false ) + , m_leftContainer( 0 ) + , m_rightContainer( 0 ) + , m_topContainer( 0 ) + , m_bottomContainer( 0 ) + , d( new KMdiMainFrmPrivate() ) + , m_mdiGUIClient( 0 ) + , m_managedDockPositionMode( false ) + , m_documentTabWidget( 0 ) +{ + kdDebug(760) << k_funcinfo << endl; + // Create the local lists of windows + m_pDocumentViews = new QPtrList<KMdiChildView>; + m_pDocumentViews->setAutoDelete( false ); + m_pToolViews = new QMap<QWidget*, KMdiToolViewAccessor*>; + + // This seems to be needed (re-check it after Qt2.0 comed out) + setFocusPolicy( ClickFocus ); + + // create the central widget + createMdiManager(); + + // cover KMdi's childarea by a dockwidget + m_pDockbaseAreaOfDocumentViews = createDockWidget( "mdiAreaCover", QPixmap(), 0L, "mdi_area_cover" ); + m_pDockbaseAreaOfDocumentViews->setDockWindowTransient( this, true ); + m_pDockbaseAreaOfDocumentViews->setEnableDocking( KDockWidget::DockNone ); + m_pDockbaseAreaOfDocumentViews->setDockSite( KDockWidget::DockCorner ); + m_pDockbaseAreaOfDocumentViews->setWidget( m_pMdi ); + // set this dock to main view + setView( m_pDockbaseAreaOfDocumentViews ); + setMainDockWidget( m_pDockbaseAreaOfDocumentViews ); + + // Apply options for the MDI manager + applyOptions(); + + m_pTaskBarPopup = new QPopupMenu( this, "taskbar_popup_menu" ); + m_pWindowPopup = new QPopupMenu( this, "window_popup_menu" ); + + m_pWindowMenu = new QPopupMenu( this, "window_menu" ); + m_pWindowMenu->setCheckable( true ); + QObject::connect( m_pWindowMenu, SIGNAL( aboutToShow() ), this, SLOT( fillWindowMenu() ) ); + + m_pDockMenu = new QPopupMenu( this, "dock_menu" ); + m_pDockMenu->setCheckable( true ); + + m_pMdiModeMenu = new QPopupMenu( this, "mdimode_menu" ); + m_pMdiModeMenu->setCheckable( true ); + + m_pPlacingMenu = new QPopupMenu( this, "placing_menu" ); + + d->closeWindowAction = new KAction(i18n("&Close"), +#ifdef Q_WS_WIN + CTRL|Key_F4, +#else + 0, +#endif + this, SLOT(closeActiveView()), actionCollection(), "window_close"); + + // the MDI view taskbar + createTaskBar(); + + // this is only a hack, but prevents us from crash because the buttons are otherwise + // not created before we switch the modes where we need them !!! + setMenuForSDIModeSysButtons( menuBar() ); + + switch ( mdiMode ) + { + case KMdi::IDEAlMode: + kdDebug(760) << k_funcinfo << "Switching to IDEAl mode" << endl; + switchToIDEAlMode(); + break; + case KMdi::TabPageMode: + kdDebug(760) << k_funcinfo << "Switching to tab page mode" << endl; + switchToTabPageMode(); + break; + case KMdi::ToplevelMode: + kdDebug(760) << k_funcinfo << "Switching to top level mode" << endl; + switchToToplevelMode(); + break; + default: + m_mdiMode = KMdi::ChildframeMode; + kdDebug(760) << k_funcinfo << "Switching to child frame mode" << endl; + break; + } + + // drag end timer + m_pDragEndTimer = new QTimer(); + connect( m_pDragEndTimer, SIGNAL( timeout() ), this, SLOT( dragEndTimeOut() ) ); + connect( guiFactory(), SIGNAL( clientAdded( KXMLGUIClient* ) ), + this, SLOT( verifyToplevelHeight() ) ); + connect( guiFactory(), SIGNAL( clientRemoved( KXMLGUIClient* ) ), + this, SLOT( verifyToplevelHeight() ) ); +} + +void KMdiMainFrm::verifyToplevelHeight() +{ + if ( m_mdiMode != KMdi::ToplevelMode ) + return; + + //kdDebug(760) << k_funcinfo << endl; + int topDockHeight = topDock() ? topDock()->height() : 0; + int menuBarHeight = hasMenuBar() ? menuBar()->height() : 0; + setFixedHeight( topDockHeight + menuBarHeight ); + resize( width(), height() ); +} + +void KMdiMainFrm::setStandardMDIMenuEnabled( bool showModeMenu ) +{ + m_mdiGUIClient = new KMDIPrivate::KMDIGUIClient( this, showModeMenu ); + connect( m_mdiGUIClient, SIGNAL( toggleTop() ), this, SIGNAL( toggleTop() ) ); + connect( m_mdiGUIClient, SIGNAL( toggleLeft() ), this, SIGNAL( toggleLeft() ) ); + connect( m_mdiGUIClient, SIGNAL( toggleRight() ), this, SIGNAL( toggleRight() ) ); + connect( m_mdiGUIClient, SIGNAL( toggleBottom() ), this, SIGNAL( toggleBottom() ) ); + + if ( m_mdiMode == KMdi::IDEAlMode ) + { + if ( m_topContainer ) + connect( this, SIGNAL( toggleTop() ), m_topContainer->getWidget(), SLOT( toggle() ) ); + if ( m_leftContainer ) + connect( this, SIGNAL( toggleLeft() ), m_leftContainer->getWidget(), SLOT( toggle() ) ); + if ( m_rightContainer ) + connect( this, SIGNAL( toggleRight() ), m_rightContainer->getWidget(), SLOT( toggle() ) ); + if ( m_bottomContainer ) + connect( this, SIGNAL( toggleBottom() ), m_bottomContainer->getWidget(), SLOT( toggle() ) ); + } + + emit mdiModeHasBeenChangedTo( m_mdiMode ); +} + +//============ ~KMdiMainFrm ============// +KMdiMainFrm::~KMdiMainFrm() +{ + //save the children first to a list, as removing invalidates our iterator + QValueList<KMdiChildView*> children; + for ( KMdiChildView * w = m_pDocumentViews->first();w;w = m_pDocumentViews->next() ) + children.append( w ); + + // safely close the windows so properties are saved... + QValueListIterator<KMdiChildView*> childIt; + for ( childIt = children.begin(); childIt != children.end(); ++childIt ) + { + closeWindow( *childIt, false ); // without re-layout taskbar! + } + + emit lastChildViewClosed(); + delete m_pDocumentViews; + delete m_pToolViews; + m_pToolViews = 0; + delete m_pDragEndTimer; + + delete m_pUndockButtonPixmap; + delete m_pMinButtonPixmap; + delete m_pRestoreButtonPixmap; + delete m_pCloseButtonPixmap; + + //deletes added for Release-Version-Pop-Up-WinMenu-And-Go-Out-Problem + delete m_pDockMenu; + delete m_pMdiModeMenu; + delete m_pPlacingMenu; + delete m_pTaskBarPopup; + delete m_pWindowPopup; + delete m_pWindowMenu; + delete m_mdiGUIClient; + delete m_pTempDockSession; + m_mdiGUIClient = 0; + delete d; + d = 0; +} + +//============ applyOptions ============// +//FIXME something wrong with this function. dunno what though +void KMdiMainFrm::applyOptions() +{ + QPtrListIterator<KMdiChildView> it( *m_pDocumentViews ); + for ( ; ( *it ); ++it ) + { + QWidget* childFrame = 0L; + if ( ( *it )->mdiParent() ) + { + kdDebug(760) << k_funcinfo << "using child view's mdi parent for resize hack" << endl; + childFrame = ( *it )->mdiParent(); + } + else + { + kdDebug(760) << k_funcinfo << "using child view for resize hack" << endl; + childFrame = ( *it ); + } + + int w = childFrame->width(); + int h = childFrame->height(); + childFrame->resize( w + 1, h + 1 ); + childFrame->resize( w - 1, h - 1 ); + } +} + +//============ createMdiManager ============// +void KMdiMainFrm::createMdiManager() +{ + kdDebug(760) << k_funcinfo << "creating MDI manager" << endl; + m_pMdi = new KMdiChildArea( this ); + setCentralWidget( m_pMdi ); + QObject::connect( m_pMdi, SIGNAL( nowMaximized( bool ) ), + this, SLOT( setEnableMaximizedChildFrmMode( bool ) ) ); + QObject::connect( m_pMdi, SIGNAL( noMaximizedChildFrmLeft( KMdiChildFrm* ) ), + this, SLOT( switchOffMaximizeModeForMenu( KMdiChildFrm* ) ) ); + QObject::connect( m_pMdi, SIGNAL( sysButtonConnectionsMustChange( KMdiChildFrm*, KMdiChildFrm* ) ), + this, SLOT( updateSysButtonConnections( KMdiChildFrm*, KMdiChildFrm* ) ) ); + QObject::connect( m_pMdi, SIGNAL( popupWindowMenu( QPoint ) ), + this, SLOT( popupWindowMenu( QPoint ) ) ); + QObject::connect( m_pMdi, SIGNAL( lastChildFrmClosed() ), + this, SIGNAL( lastChildFrmClosed() ) ); +} + +//============ createTaskBar ==============// +void KMdiMainFrm::createTaskBar() +{ + m_pTaskBar = new KMdiTaskBar( this, QMainWindow::DockBottom ); + m_pTaskBar->installEventFilter( this ); +} + +void KMdiMainFrm::slot_toggleTaskBar() +{ + if ( !m_pTaskBar ) + return; + m_pTaskBar->switchOn( !m_pTaskBar->isSwitchedOn() ); +} + +void KMdiMainFrm::resizeEvent( QResizeEvent *e ) +{ + if ( ( m_mdiMode == KMdi::ToplevelMode ) && !parentWidget() ) + { + if ( e->oldSize().height() != e->size().height() ) + return ; + } + KParts::DockMainWindow::resizeEvent( e ); + if ( !m_mdiGUIClient ) + return ; + setSysButtonsAtMenuPosition(); +} + +//================ setMinimumSize ===============// + +void KMdiMainFrm::setMinimumSize( int minw, int minh ) +{ + if ( ( m_mdiMode == KMdi::ToplevelMode ) && !parentWidget() ) + return ; + DockMainWindow::setMinimumSize( minw, minh ); +} + +//================ wrapper ===============// + +KMdiChildView* KMdiMainFrm::createWrapper( QWidget *view, const QString& name, const QString& shortName ) +{ + Q_ASSERT( view ); // if this assert fails, then some part didn't return a widget. Fix the part ;) + + KMdiChildView* pMDICover = new KMdiChildView( name /*caption*/, 0L /*parent*/, + name.latin1() ); + QBoxLayout* pLayout = new QHBoxLayout( pMDICover, 0, -1, "layout" ); + view->reparent( pMDICover, QPoint( 0, 0 ) ); + pLayout->addWidget( view ); + // pMDICover->setName(name); + pMDICover->setTabCaption( shortName ); + pMDICover->setCaption( name ); + + const QPixmap* wndIcon = view->icon(); + if ( wndIcon ) + pMDICover->setIcon( *wndIcon ); + + pMDICover->trackIconAndCaptionChanges( view ); + return pMDICover; +} + +//================ addWindow ===============// + +void KMdiMainFrm::addWindow( KMdiChildView* pWnd, int flags ) +{ + addWindow( pWnd, flags, -1 ); +} + +void KMdiMainFrm::addWindow( KMdiChildView* pWnd, int flags, int index ) +{ + if ( windowExists( pWnd, AnyView ) ) //already added + return; + + if ( flags & KMdi::ToolWindow ) + { + addToolWindow( pWnd ); + // some kind of cascading + pWnd->move( m_pMdi->mapToGlobal( m_pMdi->getCascadePoint() ) ); + + return ; + } + + d->closeWindowAction->setEnabled(true); + + // common connections used when under MDI control + QObject::connect( pWnd, SIGNAL( clickedInWindowMenu( int ) ), this, SLOT( windowMenuItemActivated( int ) ) ); + QObject::connect( pWnd, SIGNAL( focusInEventOccurs( KMdiChildView* ) ), this, SLOT( activateView( KMdiChildView* ) ) ); + QObject::connect( pWnd, SIGNAL( childWindowCloseRequest( KMdiChildView* ) ), this, SLOT( childWindowCloseRequest( KMdiChildView* ) ) ); + QObject::connect( pWnd, SIGNAL( attachWindow( KMdiChildView*, bool ) ), this, SLOT( attachWindow( KMdiChildView*, bool ) ) ); + QObject::connect( pWnd, SIGNAL( detachWindow( KMdiChildView*, bool ) ), this, SLOT( detachWindow( KMdiChildView*, bool ) ) ); + QObject::connect( pWnd, SIGNAL( clickedInDockMenu( int ) ), this, SLOT( dockMenuItemActivated( int ) ) ); + QObject::connect( pWnd, SIGNAL( activated( KMdiChildView* ) ), this, SIGNAL( viewActivated( KMdiChildView* ) ) ); + QObject::connect( pWnd, SIGNAL( deactivated( KMdiChildView* ) ), this, SIGNAL( viewDeactivated( KMdiChildView* ) ) ); + + if ( index == -1 ) + m_pDocumentViews->append( pWnd ); + else + m_pDocumentViews->insert( index, pWnd ); + + if ( m_pTaskBar ) + { + KMdiTaskBarButton* but = m_pTaskBar->addWinButton( pWnd ); + QObject::connect( pWnd, SIGNAL( tabCaptionChanged( const QString& ) ), but, SLOT( setNewText( const QString& ) ) ); + } + + // embed the view depending on the current MDI mode + if ( m_mdiMode == KMdi::TabPageMode || m_mdiMode == KMdi::IDEAlMode ) + { + QPixmap pixmap; + if ( pWnd->icon() ) + pixmap = *( pWnd->icon() ); + + m_documentTabWidget->insertTab( pWnd, pixmap, pWnd->tabCaption(), index ); + + connect( pWnd, SIGNAL( iconUpdated( QWidget*, QPixmap ) ), m_documentTabWidget, SLOT( updateIconInView( QWidget*, QPixmap ) ) ); + connect( pWnd, SIGNAL( captionUpdated( QWidget*, const QString& ) ), m_documentTabWidget, SLOT( updateCaptionInView( QWidget*, const QString& ) ) ); + } + else + { + if ( ( flags & KMdi::Detach ) || ( m_mdiMode == KMdi::ToplevelMode ) ) + { + detachWindow( pWnd, !( flags & KMdi::Hide ) ); + emit childViewIsDetachedNow( pWnd ); // fake it because detach won't call it in this case of addWindow-to-MDI + } + else + attachWindow( pWnd, !( flags & KMdi::Hide ), flags & KMdi::UseKMdiSizeHint ); + + if ( ( m_bMaximizedChildFrmMode && ( !m_bSDIApplication && ( flags & KMdi::Detach ) ) + && m_mdiMode != KMdi::ToplevelMode ) || ( flags & KMdi::Maximize ) ) + { + if ( !pWnd->isMaximized() ) + pWnd->maximize(); + } + + if ( !m_bSDIApplication || ( flags & KMdi::Detach ) ) + { + if ( flags & KMdi::Minimize ) + pWnd->minimize(); + + if ( !( flags & KMdi::Hide ) ) + { + if ( pWnd->isAttached() ) + pWnd->mdiParent()->show(); + else + pWnd->show(); + } + } + } +} + +//============ addWindow ============// +void KMdiMainFrm::addWindow( KMdiChildView* pWnd, QRect rectNormal, int flags ) +{ + addWindow( pWnd, flags ); + if ( m_bMaximizedChildFrmMode && pWnd->isAttached() ) + pWnd->setRestoreGeometry( rectNormal ); + else + pWnd->setGeometry( rectNormal ); +} + +//============ addWindow ============// +void KMdiMainFrm::addWindow( KMdiChildView* pWnd, QPoint pos, int flags ) +{ + addWindow( pWnd, flags ); + if ( m_bMaximizedChildFrmMode && pWnd->isAttached() ) + pWnd->setRestoreGeometry( QRect( pos, pWnd->restoreGeometry().size() ) ); + else + pWnd->move( pos ); +} + + + +KMdiToolViewAccessor *KMdiMainFrm::createToolWindow() +{ + return new KMdiToolViewAccessor( this ); +} + + +void KMdiMainFrm::deleteToolWindow( QWidget* pWnd ) +{ + if ( m_pToolViews->contains( pWnd ) ) + deleteToolWindow( ( *m_pToolViews ) [ pWnd ] ); +} + +void KMdiMainFrm::deleteToolWindow( KMdiToolViewAccessor *accessor ) +{ + delete accessor; +} + +//============ addWindow ============// +KMdiToolViewAccessor *KMdiMainFrm::addToolWindow( QWidget* pWnd, KDockWidget::DockPosition pos, QWidget* pTargetWnd, + int percent, const QString& tabToolTip, const QString& tabCaption ) +{ + QWidget* tvta = pWnd; + KDockWidget* pDW = dockManager->getDockWidgetFromName( pWnd->name() ); + if ( pDW ) + { + // probably readDockConfig already created the widgetContainer, use that + pDW->setWidget( pWnd ); + + if ( pWnd->icon() ) + pDW->setPixmap( *pWnd->icon() ); + + pDW->setTabPageLabel( ( tabCaption == 0 ) ? pWnd->caption() : tabCaption ); + pDW->setToolTipString( tabToolTip ); + dockManager->removeFromAutoCreateList( pDW ); + pWnd = pDW; + } + + QRect r = pWnd->geometry(); + + KMdiToolViewAccessor *mtva = new KMdiToolViewAccessor( this, pWnd, tabToolTip, ( tabCaption == 0 ) ? pWnd->caption() : tabCaption ); + m_pToolViews->insert( tvta, mtva ); + + if ( pos == KDockWidget::DockNone ) + { + mtva->d->widgetContainer->setEnableDocking( KDockWidget::DockNone ); + mtva->d->widgetContainer->reparent( this, Qt::WType_TopLevel | Qt::WType_Dialog, r.topLeft(), true ); //pToolView->isVisible()); + } + else //add and dock the toolview as a dockwidget view + mtva->place( pos, pTargetWnd, percent ); + + + return mtva; +} + +//============ attachWindow ============// +void KMdiMainFrm::attachWindow( KMdiChildView *pWnd, bool bShow, bool bAutomaticResize ) +{ + pWnd->installEventFilter( this ); + + // decide whether window shall be cascaded + bool bCascade = false; + QApplication::sendPostedEvents(); + QRect frameGeo = pWnd->frameGeometry(); + QPoint topLeftScreen = pWnd->mapToGlobal( QPoint( 0, 0 ) ); + QPoint topLeftMdiChildArea = m_pMdi->mapFromGlobal( topLeftScreen ); + QRect childAreaGeo = m_pMdi->geometry(); + if ( topLeftMdiChildArea.x() < 0 || topLeftMdiChildArea.y() < 0 || + ( topLeftMdiChildArea.x() + frameGeo.width() > childAreaGeo.width() ) || + ( topLeftMdiChildArea.y() + frameGeo.height() > childAreaGeo.height() ) ) + { + bCascade = true; + } + + // create frame and insert child view + KMdiChildFrm *lpC = new KMdiChildFrm( m_pMdi ); + pWnd->hide(); + if ( !bCascade ) + lpC->move( topLeftMdiChildArea ); + + lpC->setClient( pWnd, bAutomaticResize ); + lpC->setFocus(); + pWnd->youAreAttached( lpC ); + if ( ( m_mdiMode == KMdi::ToplevelMode ) && !parentWidget() ) + { + setMinimumHeight( m_oldMainFrmMinHeight ); + setMaximumHeight( m_oldMainFrmMaxHeight ); + resize( width(), m_oldMainFrmHeight ); + m_oldMainFrmHeight = 0; + switchToChildframeMode(); + } + + m_pMdi->manageChild( lpC, false, bCascade ); + if ( m_pMdi->topChild() && m_pMdi->topChild() ->isMaximized() ) + { + QRect r = lpC->geometry(); + lpC->setGeometry( -lpC->m_pClient->x(), -lpC->m_pClient->y(), + m_pMdi->width() + KMDI_CHILDFRM_DOUBLE_BORDER, + m_pMdi->height() + lpC->captionHeight() + KMDI_CHILDFRM_SEPARATOR + KMDI_CHILDFRM_DOUBLE_BORDER ); + lpC->setRestoreGeometry( r ); + } + + if ( bShow ) + { + lpC->show(); + } + +#undef FocusIn + QFocusEvent fe( QEvent::FocusIn ); + QApplication::sendEvent( pWnd, &fe ); + + m_pCurrentWindow = pWnd; // required for checking the active item +} + +//============= detachWindow ==============// +void KMdiMainFrm::detachWindow( KMdiChildView *pWnd, bool bShow ) +{ + if ( pWnd->isAttached() ) + { + pWnd->removeEventFilter( this ); + pWnd->youAreDetached(); + // this is only if it was attached and you want to detach it + if ( pWnd->parent() ) + { + KMdiChildFrm * lpC = pWnd->mdiParent(); + if ( lpC ) + { + if ( lpC->icon() ) + { + QPixmap pixm( *( lpC->icon() ) ); + pWnd->setIcon( pixm ); + } + QString capt( lpC->caption() ); + if ( !bShow ) + lpC->hide(); + lpC->unsetClient( m_undockPositioningOffset ); + m_pMdi->destroyChildButNotItsView( lpC, false ); //Do not focus the new top child , we loose focus... + pWnd->setCaption( capt ); + } + } + } + else + { + if ( pWnd->size().isEmpty() || ( pWnd->size() == QSize( 1, 1 ) ) ) + { + if ( m_pCurrentWindow ) + { + pWnd->setGeometry( QRect( m_pMdi->getCascadePoint( m_pDocumentViews->count() - 1 ), m_pCurrentWindow->size() ) ); + } + else + { + pWnd->setGeometry( QRect( m_pMdi->getCascadePoint( m_pDocumentViews->count() - 1 ), defaultChildFrmSize() ) ); + } + } +#ifdef Q_WS_X11 + if ( mdiMode() == KMdi::ToplevelMode ) + { + XSetTransientForHint( qt_xdisplay(), pWnd->winId(), topLevelWidget() ->winId() ); + } +#endif + + return ; + } + +#ifdef Q_WS_X11 + if ( mdiMode() == KMdi::ToplevelMode ) + { + XSetTransientForHint( qt_xdisplay(), pWnd->winId(), topLevelWidget() ->winId() ); + } +#endif + + // this will show it... + if ( bShow ) + { + activateView( pWnd ); + } + + emit childViewIsDetachedNow( pWnd ); +} + +//============== removeWindowFromMdi ==============// +void KMdiMainFrm::removeWindowFromMdi( KMdiChildView *pWnd ) +{ + Q_UNUSED( pWnd ); + //Closes a child window. sends no close event : simply deletes it + //FIXME something wrong with this, but nobody knows whatcart +#if 0 + if ( !( m_pWinList->removeRef( pWnd ) ) ) + return ; + if ( m_pWinList->count() == 0 ) + m_pCurrentWindow = 0L; + + QObject::disconnect( pWnd, SIGNAL( attachWindow( KMdiChildView*, bool ) ), this, SLOT( attachWindow( KMdiChildView*, bool ) ) ); + QObject::disconnect( pWnd, SIGNAL( detachWindow( KMdiChildView*, bool ) ), this, SLOT( detachWindow( KMdiChildView*, bool ) ) ); + QObject::disconnect( pWnd, SIGNAL( focusInEventOccurs( KMdiChildView* ) ), this, SLOT( activateView( KMdiChildView* ) ) ); + QObject::disconnect( pWnd, SIGNAL( childWindowCloseRequest( KMdiChildView* ) ), this, SLOT( childWindowCloseRequest( KMdiChildView* ) ) ); + QObject::disconnect( pWnd, SIGNAL( clickedInWindowMenu( int ) ), this, SLOT( windowMenuItemActivated( int ) ) ); + QObject::disconnect( pWnd, SIGNAL( clickedInDockMenu( int ) ), this, SLOT( dockMenuItemActivated( int ) ) ); + + if ( m_pTaskBar ) + { + KMdiTaskBarButton * but = m_pTaskBar->getButton( pWnd ); + if ( but != 0L ) + { + QObject::disconnect( pWnd, SIGNAL( tabCaptionChanged( const QString& ) ), but, SLOT( setNewText( const QString& ) ) ); + } + m_pTaskBar->removeWinButton( pWnd ); + } + + if ( m_mdiMode == KMdi::TabPageMode ) + { + if ( m_pWinList->count() == 0 ) + { + if ( !m_pDockbaseAreaOfDocumentViews ) + { + m_pDockbaseAreaOfDocumentViews = createDockWidget( "mdiAreaCover", QPixmap(), 0L, "mdi_area_cover" ); + m_pDockbaseAreaOfDocumentViews->setDockWindowTransient( this, true ); + + m_pDockbaseAreaOfDocumentViews->setWidget( m_pMdi ); + setMainDockWidget( m_pDockbaseAreaOfDocumentViews ); + } + m_pDockbaseOfTabPage->setDockSite( KDockWidget::DockFullSite ); + m_pDockbaseAreaOfDocumentViews->setEnableDocking( KDockWidget::DockCenter ); + m_pDockbaseAreaOfDocumentViews->manualDock( m_pDockbaseOfTabPage, KDockWidget::DockCenter ); + m_pDockbaseAreaOfDocumentViews->setEnableDocking( KDockWidget::DockNone ); + m_pDockbaseOfTabPage = m_pDockbaseAreaOfDocumentViews; + m_pClose->hide(); + } + KDockWidget* pDockW = ( KDockWidget* ) pWnd->parentWidget(); + pWnd->reparent( 0L, QPoint( 0, 0 ) ); + pDockW->setWidget( 0L ); + if ( pDockW == m_pDockbaseOfTabPage ) + { + QTabWidget * pTab = ( QTabWidget* ) pDockW->parentWidget() ->parentWidget(); + int cnt = pTab->count(); + m_pDockbaseOfTabPage = ( KDockWidget* ) pTab->page( cnt - 2 ); + if ( pDockW == m_pDockbaseOfTabPage ) + { + m_pDockbaseOfTabPage = ( KDockWidget* ) pTab->page( cnt - 1 ); // different to the one deleted next + } + } + delete pDockW; + if ( m_pWinList->count() == 1 ) + { + m_pWinList->last() ->activate(); // all other views are activated by tab switch + } + } + else if ( pWnd->isAttached() ) + { + pWnd->mdiParent() ->hide(); + m_pMdi->destroyChildButNotItsView( pWnd->mdiParent() ); + } + else + { + // is not attached + if ( m_pMdi->getVisibleChildCount() > 0 ) + { + setActiveWindow(); + m_pCurrentWindow = 0L; + KMdiChildView* pView = m_pMdi->topChild() ->m_pClient; + if ( pView ) + { + pView->activate(); + } + } + else if ( m_pWinList->count() > 0 ) + { + //crash? m_pWinList->last()->activate(); + //crash? m_pWinList->last()->setFocus(); + } + } + + if ( pWnd->isToolView() ) + pWnd->m_bToolView = false; + + if ( !m_pCurrentWindow ) + emit lastChildViewClosed(); +#endif +} + +//============== closeWindow ==============// +void KMdiMainFrm::closeWindow( KMdiChildView *pWnd, bool layoutTaskBar ) +{ + if ( !pWnd ) + return ; + //Closes a child window. sends no close event : simply deletes it + m_pDocumentViews->removeRef( pWnd ); + if ( m_pDocumentViews->count() == 0 ) + m_pCurrentWindow = 0L; + + if ( m_pTaskBar ) + { + m_pTaskBar->removeWinButton( pWnd, layoutTaskBar ); + } + + if ( ( m_mdiMode == KMdi::TabPageMode ) || ( m_mdiMode == KMdi::IDEAlMode ) ) + { + if ( !m_documentTabWidget ) + return ; //oops + if ( m_pDocumentViews->count() == 0 ) + m_pClose->hide(); + pWnd->reparent( 0L, QPoint( 0, 0 ) ); + kdDebug(760) << "-------- 1" << endl; + if ( m_pDocumentViews->count() == 1 ) + { + m_pDocumentViews->last() ->activate(); // all other views are activated by tab switch + } + } + if ( ( m_mdiMode == KMdi::TabPageMode ) || ( m_mdiMode == KMdi::IDEAlMode ) ) + { + if ( m_pDocumentViews->count() == 0 ) + { + if ( !m_pDockbaseAreaOfDocumentViews ) + { + m_pDockbaseAreaOfDocumentViews = createDockWidget( "mdiAreaCover", QPixmap(), 0L, "mdi_area_cover" ); + m_pDockbaseAreaOfDocumentViews->setDockWindowTransient( this, true ); + m_pDockbaseAreaOfDocumentViews->setWidget( m_pMdi ); + setMainDockWidget( m_pDockbaseAreaOfDocumentViews ); + } +#if 0 + m_pDockbaseOfTabPage->setDockSite( KDockWidget::DockFullSite ); + m_pDockbaseAreaOfDocumentViews->setEnableDocking( KDockWidget::DockCenter ); + m_pDockbaseAreaOfDocumentViews->manualDock( m_pDockbaseOfTabPage, KDockWidget::DockCenter ); + m_pDockbaseAreaOfDocumentViews->setEnableDocking( KDockWidget::DockNone ); + m_pDockbaseOfTabPage = m_pDockbaseAreaOfDocumentViews; +#endif + + m_pClose->hide(); + } +#if 0 + KDockWidget* pDockW = ( KDockWidget* ) pWnd->parentWidget(); + pWnd->reparent( 0L, QPoint( 0, 0 ) ); + pDockW->setWidget( 0L ); + if ( pDockW == m_pDockbaseOfTabPage ) + { + QTabWidget * pTab = ( QTabWidget* ) pDockW->parentWidget() ->parentWidget(); + int cnt = pTab->count(); + m_pDockbaseOfTabPage = ( KDockWidget* ) pTab->page( cnt - 2 ); + if ( pDockW == m_pDockbaseOfTabPage ) + { + m_pDockbaseOfTabPage = ( KDockWidget* ) pTab->page( cnt - 1 ); // different to the one deleted next + } + } + delete pDockW; +#endif + + delete pWnd; + if ( m_pDocumentViews->count() == 1 ) + { + m_pDocumentViews->last() ->activate(); // all other views are activated by tab switch + } + } + else if ( pWnd->isAttached() ) + { + m_pMdi->destroyChild( pWnd->mdiParent() ); + } + else + { + delete pWnd; + // is not attached + if ( m_pMdi->getVisibleChildCount() > 0 ) + { + setActiveWindow(); + m_pCurrentWindow = 0L; + KMdiChildView* pView = m_pMdi->topChild() ->m_pClient; + if ( pView ) + { + pView->activate(); + } + } + else if ( m_pDocumentViews->count() > 0 ) + { + if ( m_pDocumentViews->current() ) + { + m_pDocumentViews->current() ->activate(); + m_pDocumentViews->current() ->setFocus(); + } + else + { + m_pDocumentViews->last() ->activate(); + m_pDocumentViews->last() ->setFocus(); + } + } + } + + if ( !m_pCurrentWindow ) + { + d->closeWindowAction->setEnabled(false); + emit lastChildViewClosed(); + } +} + +//================== findWindow =================// +KMdiChildView* KMdiMainFrm::findWindow( const QString& caption ) +{ + QPtrListIterator<KMdiChildView> it( *m_pDocumentViews ); + for ( ; ( *it ); ++it ) + { + if ( ( *it )->caption() == caption ) + return ( *it ); + } + return 0L; +} + +//================== activeWindow ===================// +KMdiChildView* KMdiMainFrm::activeWindow() +{ + return m_pCurrentWindow; +} + +//================== windowExists ? =================// +bool KMdiMainFrm::windowExists( KMdiChildView *pWnd, ExistsAs as ) +{ + if ( ( as == ToolView ) || ( as == AnyView ) ) + { + if ( m_pToolViews->contains( pWnd ) ) + return true; + if ( as == ToolView ) + return false; + } + + if ( m_pDocumentViews->findRef( pWnd ) != -1 ) + return true; + + return false; +} + +QPopupMenu * KMdiMainFrm::windowPopup( KMdiChildView * pWnd, bool bIncludeTaskbarPopup ) +{ + m_pWindowPopup->clear(); + if ( bIncludeTaskbarPopup ) + { + m_pWindowPopup->insertItem( i18n( "Window" ), taskBarPopup( pWnd, false ) ); + m_pWindowPopup->insertSeparator(); + } + return m_pWindowPopup; +} + +//================ taskBarPopup =================// +QPopupMenu* KMdiMainFrm::taskBarPopup( KMdiChildView *pWnd, bool /*bIncludeWindowPopup*/ ) +{ + //returns the g_pTaskBarPopup filled according to the KMdiChildView state + m_pTaskBarPopup->clear(); + if ( pWnd->isAttached() ) + { + m_pTaskBarPopup->insertItem( i18n( "Undock" ), pWnd, SLOT( detach() ) ); + m_pTaskBarPopup->insertSeparator(); + if ( pWnd->isMinimized() || pWnd->isMaximized() ) + m_pTaskBarPopup->insertItem( i18n( "Restore" ), pWnd, SLOT( restore() ) ); + if ( !pWnd->isMaximized() ) + m_pTaskBarPopup->insertItem( i18n( "Maximize" ), pWnd, SLOT( maximize() ) ); + if ( !pWnd->isMinimized() ) + m_pTaskBarPopup->insertItem( i18n( "Minimize" ), pWnd, SLOT( minimize() ) ); + } + else + m_pTaskBarPopup->insertItem( i18n( "Dock" ), pWnd, SLOT( attach() ) ); + m_pTaskBarPopup->insertSeparator(); + m_pTaskBarPopup->insertItem( i18n( "Close" ), pWnd, SLOT( close() ) ); + // the window has a view...get the window popup + m_pTaskBarPopup->insertSeparator(); + m_pTaskBarPopup->insertItem( i18n( "Operations" ), windowPopup( pWnd, false ) ); //alvoid recursion + return m_pTaskBarPopup; +} + +void KMdiMainFrm::slotDocCurrentChanged( QWidget* pWidget ) +{ + KMdiChildView * pWnd = static_cast<KMdiChildView*>( pWidget ); + pWnd->m_bMainframesActivateViewIsPending = true; + + bool bActivateNecessary = true; + if ( m_pCurrentWindow != pWnd ) + m_pCurrentWindow = pWnd; + + if ( m_pTaskBar ) + m_pTaskBar->setActiveButton( pWnd ); + + if ( m_documentTabWidget && ( m_mdiMode == KMdi::TabPageMode || m_mdiMode == KMdi::IDEAlMode ) ) + { + m_documentTabWidget->showPage( pWnd ); + pWnd->activate(); + } + else + { + if ( pWnd->isAttached() ) + { + if ( bActivateNecessary && ( m_pMdi->topChild() == pWnd->mdiParent() ) ) + pWnd->activate(); + + pWnd->mdiParent()->raiseAndActivate(); + } + if ( !pWnd->isAttached() ) + { + if ( bActivateNecessary ) + pWnd->activate(); + + m_pMdi->setTopChild( 0L ); // lose focus in the mainframe window + if ( !pWnd->isActiveWindow() ) + pWnd->setActiveWindow(); + + pWnd->raise(); + } + } + if ( !switching() ) + activeWindow()->updateTimeStamp(); + emit collapseOverlapContainers(); + pWnd->m_bMainframesActivateViewIsPending = false; +} + + +void KMdiMainFrm::activateView( KMdiChildView* pWnd ) +{ + pWnd->m_bMainframesActivateViewIsPending = true; + + bool bActivateNecessary = true; + if ( m_pCurrentWindow != pWnd ) + m_pCurrentWindow = pWnd; + else + { + bActivateNecessary = false; + // if this method is called as answer to view->activate(), + // interrupt it because it's not necessary + pWnd->m_bInterruptActivation = true; + } + + if ( m_pTaskBar ) + m_pTaskBar->setActiveButton( pWnd ); + + if ( m_documentTabWidget && m_mdiMode == KMdi::TabPageMode || m_mdiMode == KMdi::IDEAlMode ) + { + m_documentTabWidget->showPage( pWnd ); + pWnd->activate(); + } + else + { + if ( pWnd->isAttached() ) + { + if ( bActivateNecessary && ( m_pMdi->topChild() == pWnd->mdiParent() ) ) + pWnd->activate(); + + pWnd->mdiParent() ->raiseAndActivate(); + } + if ( !pWnd->isAttached() ) + { + if ( bActivateNecessary ) + pWnd->activate(); + + m_pMdi->setTopChild( 0L ); // lose focus in the mainframe window + if ( !pWnd->isActiveWindow() ) + pWnd->setActiveWindow(); + + pWnd->raise(); + } + } + + emit collapseOverlapContainers(); + + pWnd->m_bMainframesActivateViewIsPending = false; +} + +void KMdiMainFrm::taskbarButtonRightClicked( KMdiChildView *pWnd ) +{ + activateView( pWnd ); // set focus + //QApplication::sendPostedEvents(); + taskBarPopup( pWnd, true ) ->popup( QCursor::pos() ); +} + +void KMdiMainFrm::childWindowCloseRequest( KMdiChildView *pWnd ) +{ + KMdiViewCloseEvent * ce = new KMdiViewCloseEvent( pWnd ); + QApplication::postEvent( this, ce ); +} + +bool KMdiMainFrm::event( QEvent* e ) +{ + if ( e->type() == QEvent::User ) + { + KMdiChildView * pWnd = ( KMdiChildView* ) ( ( KMdiViewCloseEvent* ) e )->data(); + if ( pWnd != 0L ) + closeWindow( pWnd ); + return true; + // A little hack: If MDI child views are moved implicietly by moving + // the main widget they should know this too. Unfortunately there seems to + // be no way to catch the move start / move stop situations for the main + // widget in a clean way. (There is no MouseButtonPress/Release or + // something like that.) Therefore we do the following: When we get the + // "first" move event we start a timer and interprete it as "drag begin". + // If we get the next move event and the timer is running we restart the + // timer and don't do anything else. If the timer elapses (this meens we + // haven't had any move event for a while) we interprete this as "drag + // end". If the moving didn't stop actually, we will later get another + // "drag begin", so we get a drag end too much, but this would be the same + // as if the user would stop moving for a little while. + // Actually we seem to be lucky that the timer does not elapse while we + // are moving -> so we have no obsolete drag end / begin + } + else if ( isVisible() && e->type() == QEvent::Move ) + { + if ( m_pDragEndTimer->isActive() ) + { + // this is not the first move -> stop old timer + m_pDragEndTimer->stop(); + } + else + { + // this is the first move -> send the drag begin to all concerned views + QPtrListIterator<KMdiChildView> it( *m_pDocumentViews ); + for ( ; ( *it ); ++it ) + { + KMdiChildFrmDragBeginEvent dragBeginEvent( 0L ); + QApplication::sendEvent( ( *it ), &dragBeginEvent ); + } + } + m_pDragEndTimer->start( 200, true ); // single shot after 200 ms + } + + return DockMainWindow::event( e ); +} + +bool KMdiMainFrm::eventFilter( QObject * /*obj*/, QEvent *e ) +{ + if ( e->type() == QEvent::Resize && m_mdiMode == KMdi::ToplevelMode ) + { + verifyToplevelHeight(); + return false; //let the rest of the resize magic do its work + } + + if ( e->type() == QEvent::FocusIn ) + { + QFocusEvent * pFE = ( QFocusEvent* ) e; + if ( pFE->reason() == QFocusEvent::ActiveWindow ) + { + if ( m_pCurrentWindow && !m_pCurrentWindow->isHidden() && + !m_pCurrentWindow->isAttached() && m_pMdi->topChild() ) + { + return true; // eat the event + } + } + if ( m_pMdi ) + { + static bool focusTCIsPending = false; + if ( !focusTCIsPending ) + { + focusTCIsPending = true; + m_pMdi->focusTopChild(); + focusTCIsPending = false; + } + } + } + else if ( e->type() == QEvent::KeyRelease ) + { + if ( switching() ) + { + KAction * a = actionCollection() ->action( "view_last_window" ) ; + if ( a ) + { + const KShortcut cut( a->shortcut() ); + const KKeySequence& seq = cut.seq( 0 ); + const KKey& key = seq.key( 0 ); + int modFlags = key.modFlags(); + int state = ( ( QKeyEvent * ) e ) ->state(); + KKey key2( ( QKeyEvent * ) e ); + + /** these are quite some assumptions: + * The key combination uses exactly one modifier key + * The WIN button in KDE is the meta button in Qt + **/ + if ( state != ( ( QKeyEvent * ) e ) ->stateAfter() && + ( ( modFlags & KKey::CTRL ) > 0 ) == ( ( state & Qt::ControlButton ) > 0 ) && + ( ( modFlags & KKey::ALT ) > 0 ) == ( ( state & Qt::AltButton ) > 0 ) && + ( ( modFlags & KKey::WIN ) > 0 ) == ( ( state & Qt::MetaButton ) > 0 ) ) + { + activeWindow() ->updateTimeStamp(); + setSwitching( false ); + } + return true; + } + else + { + kdDebug(760) << "KAction( \"view_last_window\") not found." << endl; + } + } + } + return false; // standard event processing +} + +/** + * close all views + */ +void KMdiMainFrm::closeAllViews() +{ + //save the children first to a list, as removing invalidates our iterator + QValueList<KMdiChildView*> children; + for ( KMdiChildView * w = m_pDocumentViews->first();w;w = m_pDocumentViews->next() ) + { + children.append( w ); + } + QValueListIterator<KMdiChildView *> childIt; + for ( childIt = children.begin(); childIt != children.end(); ++childIt ) + { + ( *childIt )->close(); + } +} + + +/** + * iconify all views + */ +void KMdiMainFrm::iconifyAllViews() +{ + kdDebug(760) << k_funcinfo << "minimizing all the views" << endl; + QPtrListIterator<KMdiChildView> it( *m_pDocumentViews ); + for ( ; ( *it ); ++it ) + ( *it )->minimize(); +} + +/** + * closes the view of the active (topchild) window + */ +void KMdiMainFrm::closeActiveView() +{ + kdDebug(760) << k_funcinfo << "closing the active view" << endl; + if ( m_pCurrentWindow ) + m_pCurrentWindow->close(); +} + +/** find the root dockwidgets and store their geometry */ +void KMdiMainFrm::findRootDockWidgets( QPtrList<KDockWidget>* rootDockWidgetList, QValueList<QRect>* positionList ) +{ + //nothing is valid + if ( !rootDockWidgetList && !positionList ) + return ; + + // since we set some windows to toplevel, we must consider the window manager's window frame + const int frameBorderWidth = 7; // @todo: Can we / do we need to ask the window manager? + const int windowTitleHeight = 10; // @todo: -"- + + QObjectList* pObjList = queryList( "KDockWidget" ); + if ( pObjList->isEmpty() ) + pObjList = queryList( "KDockWidget_Compat::KDockWidget" ); + + QObjectListIt it( *pObjList ); + // for all dockwidgets (which are children of this mainwindow) + while ( ( *it ) ) + { + KDockWidget* dockWindow = 0L; /* pDockW */ + KDockWidget* rootDockWindow = 0L; /* pRootDockWindow */ + KDockWidget* undockCandidate = 0L; /* pUndockCandidate */ + QWidget* pW = static_cast<QWidget*>( ( *it ) ); + + // find the oldest ancestor of the current dockwidget that can be undocked + while ( !pW->isTopLevel() ) + { + if ( ::qt_cast<KDockWidget*>( pW ) || pW->inherits( "KDockWidget_Compat::KDockWidget" ) ) + { + undockCandidate = static_cast<KDockWidget*>( pW ); + if ( undockCandidate->enableDocking() != KDockWidget::DockNone ) + rootDockWindow = undockCandidate; + } + pW = pW->parentWidget(); + } + + if ( rootDockWindow ) + { + // if that oldest ancestor is not already in the list, append it + bool found = false; + if ( !rootDockWidgetList->isEmpty() ) + { + QPtrListIterator<KDockWidget> it2( *rootDockWidgetList ); + for ( ; it2.current() && !found; ++it2 ) + { + dockWindow = it2.current(); + if ( dockWindow == rootDockWindow ) + found = true; + } + } + + if ( !found || rootDockWidgetList->isEmpty() ) + { + rootDockWidgetList->append( dockWindow ); + kdDebug(760) << k_funcinfo << "Appending " << rootDockWindow << " to our list of " << + "root dock windows" << endl; + QPoint p = rootDockWindow->mapToGlobal( rootDockWindow->pos() ) - rootDockWindow->pos(); + QRect r( p.x(), p.y() + m_undockPositioningOffset.y(), + rootDockWindow->width() - windowTitleHeight - frameBorderWidth * 2, + rootDockWindow->height() - windowTitleHeight - frameBorderWidth * 2 ); + positionList->append( r ); + } + } + ++it; + } + delete pObjList; +} + +/** + * undocks all view windows (unix-like) + */ +void KMdiMainFrm::switchToToplevelMode() +{ + if ( m_mdiMode == KMdi::ToplevelMode ) + { + emit mdiModeHasBeenChangedTo( KMdi::ToplevelMode ); + return ; + } + + KMdi::MdiMode oldMdiMode = m_mdiMode; + + const int frameBorderWidth = 7; // @todo: Can we / do we need to ask the window manager? + setUndockPositioningOffset( QPoint( 0, ( m_pTaskBar ? m_pTaskBar->height() : 0 ) + frameBorderWidth ) ); + + // 1.) select the dockwidgets to be undocked and store their geometry + QPtrList<KDockWidget> rootDockWidgetList; + QValueList<QRect> positionList; + + // 2.) undock the MDI views of KMDI + switch( oldMdiMode ) + { + case KMdi::ChildframeMode: + finishChildframeMode(); + break; + case KMdi::TabPageMode: + finishTabPageMode(); + break; + case KMdi::IDEAlMode: + finishIDEAlMode(); + findRootDockWidgets( &rootDockWidgetList, &positionList ); + break; + default: + break; //do nothing + } + + // 3.) undock all these found oldest ancestors (being KDockWidgets) + QPtrListIterator<KDockWidget> kdwit( rootDockWidgetList ); + for ( ; ( *kdwit ); ++kdwit ) + ( *kdwit )->undock(); + + // 4.) recreate the MDI childframe area and hide it + if ( oldMdiMode == KMdi::TabPageMode || oldMdiMode == KMdi::IDEAlMode ) + { + if ( !m_pDockbaseAreaOfDocumentViews ) + { + m_pDockbaseAreaOfDocumentViews = createDockWidget( "mdiAreaCover", QPixmap(), 0L, "mdi_area_cover" ); + m_pDockbaseAreaOfDocumentViews->setDockWindowTransient( this, true ); + m_pDockbaseAreaOfDocumentViews->setEnableDocking( KDockWidget::DockNone ); + m_pDockbaseAreaOfDocumentViews->setDockSite( KDockWidget::DockCorner ); + m_pDockbaseAreaOfDocumentViews->setWidget( m_pMdi ); + } + // set this dock to main view + setView( m_pDockbaseAreaOfDocumentViews ); + setMainDockWidget( m_pDockbaseAreaOfDocumentViews ); + } + // QApplication::sendPostedEvents(); //why do we need to empty the event queue? + if ( !parentWidget() ) + { + //if we don't have a parent widget ( which i expect we wouldn't ) + //make sure we take into account the size of the docks provided by + //QMainWindow + int topDockHeight = topDock() ? topDock()->height() : 0; + int bottomDockHeight = bottomDock() ? bottomDock()->height() : 0; + int menuBarHeight = hasMenuBar() ? menuBar()->height() : 0; + if ( m_pDocumentViews->count() != 0 ) + setFixedHeight( height() - m_pDockbaseAreaOfDocumentViews->height() ); + else + { + kdDebug(760) << k_funcinfo << "height is: " << height() << endl; + kdDebug(760) << k_funcinfo << "top dock height: " << topDockHeight << endl; + kdDebug(760) << k_funcinfo << "bottom dock height: " << bottomDockHeight << endl; + kdDebug(760) << k_funcinfo << "menu bar height: " << menuBarHeight << endl; + kdDebug(760) << k_funcinfo << "dock base area height: " << m_pDockbaseAreaOfDocumentViews->height() << endl; + setFixedHeight( topDockHeight + menuBarHeight ); + } + } + + //FIXME although i don't know what to fix + // 5. show the child views again + QPtrListIterator<KMdiChildView> kmdicvit( *m_pDocumentViews ); + for ( kmdicvit.toFirst(); ( *kmdicvit ); ++kmdicvit ) + { +#ifdef Q_WS_X11 + XSetTransientForHint( qt_xdisplay(), ( *kmdicvit )->winId(), winId() ); +#endif + ( *kmdicvit )->show(); + } + + // 6.) reset all memorized positions of the undocked ones and show them again + QValueList<QRect>::Iterator qvlqrit; + QValueList<QRect>::Iterator qvlEnd = positionList.end(); + for ( kmdicvit.toFirst(), qvlqrit = positionList.begin() ; ( *kmdicvit ) && qvlqrit != qvlEnd; ++kmdicvit, ++qvlqrit ) + { + ( *kmdicvit )->setGeometry( ( *qvlqrit ) ); + ( *kmdicvit )->show(); + } + + m_pDockbaseAreaOfDocumentViews->setDockSite( KDockWidget::DockNone ); + m_mdiMode = KMdi::ToplevelMode; + + kdDebug(760) << k_funcinfo << "Switch to toplevel mode completed" << endl; + emit mdiModeHasBeenChangedTo( KMdi::ToplevelMode ); + +} + +void KMdiMainFrm::finishToplevelMode() +{ + m_pDockbaseAreaOfDocumentViews->setDockSite( KDockWidget::DockCorner ); +} + +/** + * docks all view windows (Windows-like) + */ +void KMdiMainFrm::switchToChildframeMode() +{ + if ( m_mdiMode == KMdi::ChildframeMode ) + { + emit mdiModeHasBeenChangedTo( KMdi::ChildframeMode ); + return ; + } + + QPtrList<KDockWidget> rootDockWidgetList; + QValueList<QRect> positionList; + + if ( m_mdiMode == KMdi::TabPageMode ) + { + kdDebug(760) << k_funcinfo << "finishing tab page mode" << endl; + // select the dockwidgets to be undocked and store their geometry + findRootDockWidgets( &rootDockWidgetList, &positionList ); + kdDebug(760) << k_funcinfo << "Found " << rootDockWidgetList.count() << " widgets to undock" << endl; + + // undock all these found oldest ancestors (being KDockWidgets) + QPtrListIterator<KDockWidget> it( rootDockWidgetList ); + for ( ; ( *it ) ; ++it ) + ( *it )->undock(); + + finishTabPageMode(); + } + else if ( m_mdiMode == KMdi::ToplevelMode ) + { + finishToplevelMode(); + } + else if ( m_mdiMode == KMdi::IDEAlMode ) + { + kdDebug(760) << k_funcinfo << "finishing ideal mode" << endl; + finishIDEAlMode( false ); + + // select the dockwidgets to be undocked and store their geometry + findRootDockWidgets( &rootDockWidgetList, &positionList ); + kdDebug(760) << k_funcinfo << "Found " << rootDockWidgetList.count() << " widgets to undock" << endl; + + // undock all these found oldest ancestors (being KDockWidgets) + QPtrListIterator<KDockWidget> it( rootDockWidgetList ); + for ( ; ( *it ) ; ++it ) + ( *it )->undock(); + + m_mdiMode = KMdi::TabPageMode; + finishTabPageMode(); + m_mdiMode = KMdi::IDEAlMode; + } + + if ( !m_pDockbaseAreaOfDocumentViews ) + { + // cover KMdi's childarea by a dockwidget + m_pDockbaseAreaOfDocumentViews = createDockWidget( "mdiAreaCover", QPixmap(), 0L, "mdi_area_cover" ); + m_pDockbaseAreaOfDocumentViews->setDockWindowTransient( this, true ); + m_pDockbaseAreaOfDocumentViews->setEnableDocking( KDockWidget::DockNone ); + m_pDockbaseAreaOfDocumentViews->setDockSite( KDockWidget::DockCorner ); + m_pDockbaseAreaOfDocumentViews->setWidget( m_pMdi ); + kdDebug(760) << k_funcinfo << "childarea is now covered by a dockwidget" << endl; + } + + if ( m_pDockbaseAreaOfDocumentViews->isTopLevel() ) + { + // set this dock to main view + setView( m_pDockbaseAreaOfDocumentViews ); + setMainDockWidget( m_pDockbaseAreaOfDocumentViews ); + m_pDockbaseAreaOfDocumentViews->setEnableDocking( KDockWidget::DockNone ); + m_pDockbaseAreaOfDocumentViews->setDockSite( KDockWidget::DockCorner ); + kdDebug(760) << k_funcinfo << "Dock base area has been set to the main view" << endl; + } + m_pDockbaseAreaOfDocumentViews->setWidget( m_pMdi ); //JW + m_pDockbaseAreaOfDocumentViews->show(); + + if ( ( m_mdiMode == KMdi::TabPageMode ) || ( m_mdiMode == KMdi::IDEAlMode ) ) + { + kdDebug(760) << k_funcinfo << "trying to dock back the undock toolviews" << endl; + QPtrListIterator<KDockWidget> it( rootDockWidgetList ); + for ( ; ( *it ); ++it ) + ( *it )->dockBack(); + } + + if ( m_mdiMode == KMdi::ToplevelMode && m_pTempDockSession ) + { + // restore the old dock scenario which we memorized at the time we switched to toplevel mode + kdDebug(760) << k_funcinfo << "Restoring old dock scenario memorized from toplevel mode" << endl; + QDomElement oldDockState = m_pTempDockSession->namedItem( "cur_dock_state" ).toElement(); + readDockConfig( oldDockState ); + } + + KMdi::MdiMode oldMdiMode = m_mdiMode; + m_mdiMode = KMdi::ChildframeMode; + + //FIXME although i don't know what to fix. + QPtrListIterator<KMdiChildView> it( *m_pDocumentViews ); + for ( ; ( *it ); ++it ) + { + KMdiChildView* pView = ( *it ); + if ( !pView->isToolView() && pView->isAttached() ) + attachWindow( pView, true ); + } + for ( it.toFirst(); ( *it ); ++it ) + { + KMdiChildView* pView = ( *it ); + if ( !pView->isToolView() ) + pView->show(); + } + if ( ( oldMdiMode == KMdi::ToplevelMode ) && !parentWidget() ) + { + setMinimumHeight( m_oldMainFrmMinHeight ); + setMaximumHeight( m_oldMainFrmMaxHeight ); + resize( width(), m_oldMainFrmHeight ); + m_oldMainFrmHeight = 0; + kdDebug(760) << k_funcinfo << "left top level mode completely" << endl; + emit leftTopLevelMode(); + } + emit mdiModeHasBeenChangedTo( KMdi::ChildframeMode ); +} + +void KMdiMainFrm::finishChildframeMode() +{ + // save the old dock scenario of the dockwidget-like tool views to a DOM tree + kdDebug(760) << k_funcinfo << "saving the current dock scenario" << endl; + delete m_pTempDockSession; + m_pTempDockSession = new QDomDocument( "docksession" ); + QDomElement curDockState = m_pTempDockSession->createElement( "cur_dock_state" ); + m_pTempDockSession->appendChild( curDockState ); + writeDockConfig( curDockState ); + + // detach all non-tool-views to toplevel + kdDebug(760) << k_funcinfo << "detaching all document views and moving them to toplevel" << endl; + QPtrListIterator<KMdiChildView> it( *m_pDocumentViews ); + for ( ; ( *it ); ++it ) + { + KMdiChildView* pView = ( *it ); + if ( pView->isToolView() ) + continue; + if ( pView->isAttached() ) + { + if ( pView->isMaximized() ) + pView->mdiParent()->setGeometry( 0, 0, m_pMdi->width(), m_pMdi->height() ); + detachWindow( pView, false ); + } + } +} + +/** + * Docks all view windows (Windows-like) + */ +void KMdiMainFrm::switchToTabPageMode() +{ + if ( m_mdiMode == KMdi::TabPageMode ) + { + emit mdiModeHasBeenChangedTo( KMdi::TabPageMode ); + return ; // nothing need to be done + } + + switch( m_mdiMode ) + { + case KMdi::ChildframeMode: + finishChildframeMode(); + break; + case KMdi::ToplevelMode: + finishToplevelMode(); + break; + case KMdi::IDEAlMode: + finishIDEAlMode( false ); + emit mdiModeHasBeenChangedTo( KMdi::TabPageMode ); + m_mdiMode = KMdi::TabPageMode; + return; + break; + default: + break; + } + + setupTabbedDocumentViewSpace(); + m_mdiMode = KMdi::TabPageMode; + if ( m_pCurrentWindow ) + m_pCurrentWindow->setFocus(); + + m_pTaskBar->switchOn( false ); + + if ( m_pClose ) + { + QObject::connect( m_pClose, SIGNAL( clicked() ), this, SLOT( closeViewButtonPressed() ) ); + if ( m_pDocumentViews->count() > 0 ) + m_pClose->show(); + } + else + kdDebug(760) << "close button nonexistant. strange things might happen" << endl; + + kdDebug(760) << "Switch to tab page mode complete" << endl; + emit mdiModeHasBeenChangedTo( KMdi::TabPageMode ); +} + +void KMdiMainFrm::finishTabPageMode() +{ + // if tabified, release all views from their docking covers + if ( m_mdiMode == KMdi::TabPageMode ) + { + m_pClose->hide(); + QObject::disconnect( m_pClose, SIGNAL( clicked() ), this, SLOT( closeViewButtonPressed() ) ); + + QPtrListIterator<KMdiChildView> it( *m_pDocumentViews ); + for ( ; it.current(); ++it ) + { + KMdiChildView* pView = it.current(); + if ( pView->isToolView() ) + continue; + kdDebug(760) << "KMdiMainFrm::finishTabPageMode: in loop" << endl; + QSize mins = pView->minimumSize(); + QSize maxs = pView->maximumSize(); + QSize sz = pView->size(); + QWidget* pParent = pView->parentWidget(); + QPoint p( pParent->mapToGlobal( pParent->pos() ) - pParent->pos() + m_undockPositioningOffset ); + m_documentTabWidget->removePage( pView ); + pView->reparent( 0, 0, p ); + // pView->reparent(0,0,p); + pView->resize( sz ); + pView->setMinimumSize( mins.width(), mins.height() ); + pView->setMaximumSize( maxs.width(), maxs.height() ); + // ((KDockWidget*)pParent)->undock(); // this destroys the dockwiget cover, too + // pParent->close(); + // delete pParent; + // if (centralWidget() == pParent) { + // setCentralWidget(0L); // avoid dangling pointer + // } + } + delete m_documentTabWidget; + m_documentTabWidget = 0; + m_pTaskBar->switchOn( true ); + } +} + + + +void KMdiMainFrm::setupTabbedDocumentViewSpace() +{ + // resize to childframe mode size of the mainwindow if we were in toplevel mode + if ( ( m_mdiMode == KMdi::ToplevelMode ) && !parentWidget() ) + { + setMinimumHeight( m_oldMainFrmMinHeight ); + setMaximumHeight( m_oldMainFrmMaxHeight ); + resize( width(), m_oldMainFrmHeight ); + m_oldMainFrmHeight = 0; + //qDebug("TopLevelMode off"); + emit leftTopLevelMode(); + QApplication::sendPostedEvents(); + + // restore the old dock szenario which we memorized at the time we switched to toplevel mode + if ( m_pTempDockSession ) + { + QDomElement oldDockState = m_pTempDockSession->namedItem( "cur_dock_state" ).toElement(); + readDockConfig( oldDockState ); + } + } + +#if 0 + if ( m_pDockbaseOfTabPage != m_pDockbaseAreaOfDocumentViews ) + { + delete m_pDockbaseOfTabPage; + m_pDockbaseOfTabPage = m_pDockbaseAreaOfDocumentViews; + } +#endif + delete m_documentTabWidget; + m_documentTabWidget = new KMdiDocumentViewTabWidget( m_pDockbaseAreaOfDocumentViews ); + connect( m_documentTabWidget, SIGNAL( currentChanged( QWidget* ) ), this, SLOT( slotDocCurrentChanged( QWidget* ) ) ); + m_pDockbaseAreaOfDocumentViews->setWidget( m_documentTabWidget ); + m_documentTabWidget->show(); + QPtrListIterator<KMdiChildView> it4( *m_pDocumentViews ); + for ( ; it4.current(); ++it4 ) + { + KMdiChildView* pView = it4.current(); + m_documentTabWidget->addTab( pView, pView->icon() ? *( pView->icon() ) : QPixmap(), pView->tabCaption() ); + /* + connect(pView,SIGNAL(iconOrCaptionUdpated(QWidget*,QPixmap,const QString&)), + m_documentTabWidget,SLOT(updateView(QWidget*,QPixmap,const QString&))); + */ + connect( pView, SIGNAL( iconUpdated( QWidget*, QPixmap ) ), m_documentTabWidget, SLOT( updateIconInView( QWidget*, QPixmap ) ) ); + connect( pView, SIGNAL( captionUpdated( QWidget*, const QString& ) ), m_documentTabWidget, SLOT( updateCaptionInView( QWidget*, const QString& ) ) ); + + } +} + + +void KMdiMainFrm::setIDEAlModeStyle( int flags ) +{ + d->m_styleIDEAlMode = flags; // see KMultiTabBar for the first 3 bits + if ( m_leftContainer ) + { + KMdiDockContainer * tmpL = ( KMdiDockContainer* ) ( m_leftContainer->getWidget()->qt_cast( "KMdiDockContainer" ) ); + if ( tmpL ) + tmpL->setStyle( flags ); + } + + if ( m_rightContainer ) + { + KMdiDockContainer * tmpR = ( KMdiDockContainer* ) ( m_rightContainer->getWidget()->qt_cast( "KMdiDockContainer" ) ); + if ( tmpR ) + tmpR->setStyle( flags ); + } + + if ( m_topContainer ) + { + KMdiDockContainer * tmpT = ( KMdiDockContainer* ) ( m_topContainer->getWidget()->qt_cast( "KMdiDockContainer" ) ); + if ( tmpT ) + tmpT->setStyle( flags ); + } + + if ( m_bottomContainer ) + { + KMdiDockContainer * tmpB = ( KMdiDockContainer* ) ( m_bottomContainer->getWidget()->qt_cast( "KMdiDockContainer" ) ); + if ( tmpB ) + tmpB->setStyle( flags ); + } +} + +void KMdiMainFrm::setToolviewStyle( int flag ) +{ + if ( m_mdiMode == KMdi::IDEAlMode ) + { + setIDEAlModeStyle( flag ); + } + d->m_toolviewStyle = flag; + bool toolviewExists = false; + QMap<QWidget*, KMdiToolViewAccessor*>::Iterator it; + for ( it = m_pToolViews->begin(); it != m_pToolViews->end(); ++it ) + { + KDockWidget *dockWidget = dynamic_cast<KDockWidget*>( it.data()->wrapperWidget() ); + if ( dockWidget ) + { + switch ( flag ) + { + case KMdi::IconOnly: + dockWidget->setTabPageLabel( QString::null ); + dockWidget->setPixmap( *( it.data()->wrappedWidget()->icon() ) ); + break; + case KMdi::TextOnly: + dockWidget->setPixmap(); //FIXME: Does not hide the icon in the IDEAl mode. + dockWidget->setTabPageLabel( it.data()->wrappedWidget()->caption() ); + break; + case KMdi::TextAndIcon: + dockWidget->setPixmap( *( it.data()->wrappedWidget()->icon() ) ); + dockWidget->setTabPageLabel( it.data()->wrappedWidget()->caption() ); + default: + break; + } + toolviewExists = true; + } + } + + if ( toolviewExists ) + { + //workaround for the above FIXME to make switching to TextOnly mode work in IDEAl as well. Be sure that this version of switch* is called. + if ( m_mdiMode == KMdi::IDEAlMode && flag == KMdi::TextOnly ) + { + KMdiMainFrm::switchToTabPageMode(); + KMdiMainFrm::switchToIDEAlMode(); + } + else + { + writeDockConfig(); + readDockConfig(); + } + } +} + +/** + * Docks all view windows (Windows-like) + */ +void KMdiMainFrm::switchToIDEAlMode() +{ + kdDebug(760) << k_funcinfo << "switching to IDEAl mode" << endl; + + if ( m_mdiMode == KMdi::IDEAlMode ) + { + emit mdiModeHasBeenChangedTo( KMdi::IDEAlMode ); + return ; // nothing need to be done + } + + switch( m_mdiMode ) + { + case KMdi::ChildframeMode: + finishChildframeMode(); + break; + case KMdi::ToplevelMode: + finishToplevelMode(); + break; + case KMdi::TabPageMode: + m_mdiMode = KMdi::IDEAlMode; + setupToolViewsForIDEALMode(); + emit mdiModeHasBeenChangedTo( KMdi::IDEAlMode ); + return; + break; + default: + break; + } + + setupTabbedDocumentViewSpace(); + m_mdiMode = KMdi::IDEAlMode; + setupToolViewsForIDEALMode(); + + if ( m_pCurrentWindow ) + m_pCurrentWindow->setFocus(); + + m_pTaskBar->switchOn( false ); + + if ( m_pClose ) + { + QObject::connect( m_pClose, SIGNAL( clicked() ), this, SLOT( closeViewButtonPressed() ) ); + if ( m_pDocumentViews->count() > 0 ) + m_pClose->show(); + } + else + kdWarning(760) << k_funcinfo << "close button pointer does not exist!" << endl; + + kdDebug(760) << k_funcinfo << "switch to IDEAl mode complete" << endl; + + emit mdiModeHasBeenChangedTo( KMdi::IDEAlMode ); +} + + +void KMdiMainFrm::dockToolViewsIntoContainers( QPtrList<KDockWidget>& widgetsToReparent, KDockWidget *container ) +{ + QPtrListIterator<KDockWidget> it( widgetsToReparent ); + for ( ; ( *it ); ++it ) + { + ( *it )->manualDock( container, KDockWidget::DockCenter, 20 ); + ( *it )->loseFormerBrotherDockWidget(); + } +} + +void KMdiMainFrm::findToolViewsDockedToMain( QPtrList<KDockWidget>* list, KDockWidget::DockPosition dprtmw ) +{ + KDockWidget* mainDock = getMainDockWidget(); + if ( mainDock->parentDockTabGroup() ) + { + mainDock = dynamic_cast<KDockWidget*>( mainDock->parentDockTabGroup()->parent() ); + // FIXME: will likely crash below due to unchecked cast + } + + if ( !mainDock ) + { + kdDebug(760) << k_funcinfo << "mainDock invalid. No main dock widget found." << endl; + return; + } + + KDockWidget* widget = mainDock->findNearestDockWidget( dprtmw ); + if ( widget && widget->parentDockTabGroup() ) + { + widget = static_cast<KDockWidget*>( widget->parentDockTabGroup() ->parent() ); + + if ( widget ) + { + KDockTabGroup* tg = dynamic_cast<KDockTabGroup*>( widget->getWidget() ); + if ( tg ) + { + kdDebug(760) << k_funcinfo << "KDockTabGroup found" << endl; + for ( int i = 0;i < tg->count();i++ ) + list->append( static_cast<KDockWidget*>( tg->page( i ) ) ); + } + else + list->append( widget ); + } + else + kdDebug(760) << k_funcinfo << "no widget found" << endl; + } + else + kdDebug(760) << "No main dock widget found" << endl; +} + + +void KMdiMainFrm::setupToolViewsForIDEALMode() +{ + m_leftContainer = createDockWidget( "KMdiDock::leftDock", SmallIcon( "misc" ), 0L, "Left Dock" ); + m_rightContainer = createDockWidget( "KMdiDock::rightDock", SmallIcon( "misc" ), 0L, "Right Dock" ); + m_topContainer = createDockWidget( "KMdiDock::topDock", SmallIcon( "misc" ), 0L, "Top Dock" ); + m_bottomContainer = createDockWidget( "KMdiDock::bottomDock", SmallIcon( "misc" ), 0L, "Bottom Dock" ); + + KDockWidget *mainDock = getMainDockWidget(); + KDockWidget *w = mainDock; + if ( mainDock->parentDockTabGroup() ) + w = static_cast<KDockWidget*>( mainDock->parentDockTabGroup()->parent() ); + + QPtrList<KDockWidget> leftReparentWidgets; + QPtrList<KDockWidget> rightReparentWidgets; + QPtrList<KDockWidget> bottomReparentWidgets; + QPtrList<KDockWidget> topReparentWidgets; + + if ( mainDock->parentDockTabGroup() ) + mainDock = static_cast<KDockWidget*>( mainDock->parentDockTabGroup() ->parent() ); + + findToolViewsDockedToMain( &leftReparentWidgets, KDockWidget::DockLeft ); + findToolViewsDockedToMain( &rightReparentWidgets, KDockWidget::DockRight ); + findToolViewsDockedToMain( &bottomReparentWidgets, KDockWidget::DockBottom ); + findToolViewsDockedToMain( &topReparentWidgets, KDockWidget::DockTop ); + + mainDock->setEnableDocking( KDockWidget::DockNone ); //::DockCorner); + mainDock->setDockSite( KDockWidget::DockCorner ); + + + KMdiDockContainer *tmpDC; + m_leftContainer->setWidget( tmpDC = new KMdiDockContainer( m_leftContainer, this, KDockWidget::DockLeft, d->m_styleIDEAlMode ) ); + m_leftContainer->setEnableDocking( KDockWidget::DockLeft ); + m_leftContainer->manualDock( mainDock, KDockWidget::DockLeft, 20 ); + tmpDC->init(); + if ( m_mdiGUIClient ) + connect ( this, SIGNAL( toggleLeft() ), tmpDC, SLOT( toggle() ) ); + connect( this, SIGNAL( collapseOverlapContainers() ), tmpDC, SLOT( collapseOverlapped() ) ); + connect( tmpDC, SIGNAL( activated( KMdiDockContainer* ) ), this, SLOT( setActiveToolDock( KMdiDockContainer* ) ) ); + connect( tmpDC, SIGNAL( deactivated( KMdiDockContainer* ) ), this, SLOT( removeFromActiveDockList( KMdiDockContainer* ) ) ); + + m_rightContainer->setWidget( tmpDC = new KMdiDockContainer( m_rightContainer, this, KDockWidget::DockRight, d->m_styleIDEAlMode ) ); + m_rightContainer->setEnableDocking( KDockWidget::DockRight ); + m_rightContainer->manualDock( mainDock, KDockWidget::DockRight, 80 ); + tmpDC->init(); + if ( m_mdiGUIClient ) + connect ( this, SIGNAL( toggleRight() ), tmpDC, SLOT( toggle() ) ); + connect( this, SIGNAL( collapseOverlapContainers() ), tmpDC, SLOT( collapseOverlapped() ) ); + connect( tmpDC, SIGNAL( activated( KMdiDockContainer* ) ), this, SLOT( setActiveToolDock( KMdiDockContainer* ) ) ); + connect( tmpDC, SIGNAL( deactivated( KMdiDockContainer* ) ), this, SLOT( removeFromActiveDockList( KMdiDockContainer* ) ) ); + + m_topContainer->setWidget( tmpDC = new KMdiDockContainer( m_topContainer, this, KDockWidget::DockTop, d->m_styleIDEAlMode ) ); + m_topContainer->setEnableDocking( KDockWidget::DockTop ); + m_topContainer->manualDock( mainDock, KDockWidget::DockTop, 20 ); + tmpDC->init(); + if ( m_mdiGUIClient ) + connect ( this, SIGNAL( toggleTop() ), tmpDC, SLOT( toggle() ) ); + connect( this, SIGNAL( collapseOverlapContainers() ), tmpDC, SLOT( collapseOverlapped() ) ); + connect( tmpDC, SIGNAL( activated( KMdiDockContainer* ) ), this, SLOT( setActiveToolDock( KMdiDockContainer* ) ) ); + connect( tmpDC, SIGNAL( deactivated( KMdiDockContainer* ) ), this, SLOT( removeFromActiveDockList( KMdiDockContainer* ) ) ); + + m_bottomContainer->setWidget( tmpDC = new KMdiDockContainer( m_bottomContainer, this, KDockWidget::DockBottom, d->m_styleIDEAlMode ) ); + m_bottomContainer->setEnableDocking( KDockWidget::DockBottom ); + m_bottomContainer->manualDock( mainDock, KDockWidget::DockBottom, 80 ); + tmpDC->init(); + if ( m_mdiGUIClient ) + connect ( this, SIGNAL( toggleBottom() ), tmpDC, SLOT( toggle() ) ); + connect( this, SIGNAL( collapseOverlapContainers() ), tmpDC, SLOT( collapseOverlapped() ) ); + connect( tmpDC, SIGNAL( activated( KMdiDockContainer* ) ), this, SLOT( setActiveToolDock( KMdiDockContainer* ) ) ); + connect( tmpDC, SIGNAL( deactivated( KMdiDockContainer* ) ), this, SLOT( removeFromActiveDockList( KMdiDockContainer* ) ) ); + + m_leftContainer->setDockSite( KDockWidget::DockCenter ); + m_rightContainer->setDockSite( KDockWidget::DockCenter ); + m_topContainer->setDockSite( KDockWidget::DockCenter ); + m_bottomContainer->setDockSite( KDockWidget::DockCenter ); + + dockToolViewsIntoContainers( leftReparentWidgets, m_leftContainer ); + dockToolViewsIntoContainers( rightReparentWidgets, m_rightContainer ); + dockToolViewsIntoContainers( bottomReparentWidgets, m_bottomContainer ); + dockToolViewsIntoContainers( topReparentWidgets, m_topContainer ); + + + dockManager->setSpecialLeftDockContainer( m_leftContainer ); + dockManager->setSpecialRightDockContainer( m_rightContainer ); + dockManager->setSpecialTopDockContainer( m_topContainer ); + dockManager->setSpecialBottomDockContainer( m_bottomContainer ); + + + ( ( KMdiDockContainer* ) ( m_leftContainer->getWidget() ) ) ->hideIfNeeded(); + ( ( KMdiDockContainer* ) ( m_rightContainer->getWidget() ) ) ->hideIfNeeded(); + ( ( KMdiDockContainer* ) ( m_topContainer->getWidget() ) ) ->hideIfNeeded(); + ( ( KMdiDockContainer* ) ( m_bottomContainer->getWidget() ) ) ->hideIfNeeded(); + +} + + + +void KMdiMainFrm::finishIDEAlMode( bool full ) +{ + // if tabified, release all views from their docking covers + if ( m_mdiMode == KMdi::IDEAlMode ) + { + assert( m_pClose ); + m_pClose->hide(); + QObject::disconnect( m_pClose, SIGNAL( clicked() ), this, SLOT( closeViewButtonPressed() ) ); + + + QStringList leftNames; + leftNames = prepareIdealToTabs( m_leftContainer ); + int leftWidth = m_leftContainer->width(); + + QStringList rightNames; + rightNames = prepareIdealToTabs( m_rightContainer ); + int rightWidth = m_rightContainer->width(); + + QStringList topNames; + topNames = prepareIdealToTabs( m_topContainer ); + int topHeight = m_topContainer->height(); + + QStringList bottomNames; + bottomNames = prepareIdealToTabs( m_bottomContainer ); + int bottomHeight = m_bottomContainer->height(); + + + kdDebug(760) << "leftNames" << leftNames << endl; + kdDebug(760) << "rightNames" << rightNames << endl; + kdDebug(760) << "topNames" << topNames << endl; + kdDebug(760) << "bottomNames" << bottomNames << endl; + + delete m_leftContainer; + m_leftContainer = 0; + delete m_rightContainer; + m_rightContainer = 0; + delete m_bottomContainer; + m_bottomContainer = 0; + delete m_topContainer; + m_topContainer = 0; + + + idealToolViewsToStandardTabs( bottomNames, KDockWidget::DockBottom, bottomHeight ); + idealToolViewsToStandardTabs( leftNames, KDockWidget::DockLeft, leftWidth ); + idealToolViewsToStandardTabs( rightNames, KDockWidget::DockRight, rightWidth ); + idealToolViewsToStandardTabs( topNames, KDockWidget::DockTop, topHeight ); + + QApplication::sendPostedEvents(); + + if ( !full ) + return ; + + QPtrListIterator<KMdiChildView> it( *m_pDocumentViews ); + for ( ; it.current(); ++it ) + { + KMdiChildView* pView = it.current(); + if ( pView->isToolView() ) + continue; + QSize mins = pView->minimumSize(); + QSize maxs = pView->maximumSize(); + QSize sz = pView->size(); + QWidget* pParent = pView->parentWidget(); + QPoint p( pParent->mapToGlobal( pParent->pos() ) - pParent->pos() + m_undockPositioningOffset ); + pView->reparent( 0, 0, p ); + pView->reparent( 0, 0, p ); + pView->resize( sz ); + pView->setMinimumSize( mins.width(), mins.height() ); + pView->setMaximumSize( maxs.width(), maxs.height() ); + KDockWidget* pDockW = 0L; + // find the oldest ancestor of the current dockwidget that can be undocked + do + { + if ( pParent->inherits( "KDockWidget" ) || pParent->inherits( "KDockWidget_Compat::KDockWidget" ) ) + { + pDockW = ( KDockWidget* ) pParent; + pDockW->undock(); // this destroys the dockwiget cover, too + if ( pParent != m_pDockbaseAreaOfDocumentViews ) + { + pParent->close(); + delete pParent; + } + } + else + { + pParent = pParent->parentWidget(); + } + } + while ( pParent && !pDockW ); + if ( centralWidget() == pParent ) + { + setCentralWidget( 0L ); // avoid dangling pointer + } + } + m_pTaskBar->switchOn( true ); + + } + +} + +QStringList KMdiMainFrm::prepareIdealToTabs( KDockWidget* container ) +{ + KDockContainer * pDW = dynamic_cast<KDockContainer*>( container->getWidget() ); + QStringList widgetNames = ( ( KMdiDockContainer* ) pDW ) ->containedWidgets(); + for ( QStringList::iterator it = widgetNames.begin();it != widgetNames.end();++it ) + { + KDockWidget* dw = ( KDockWidget* ) manager() ->getDockWidgetFromName( *it ); + dw->undock(); + dw->setLatestKDockContainer( 0 ); + dw->loseFormerBrotherDockWidget(); + } + return widgetNames; +} + +void KMdiMainFrm::idealToolViewsToStandardTabs( QStringList widgetNames, KDockWidget::DockPosition pos, int size ) +{ + Q_UNUSED( size ) + + KDockWidget * mainDock = getMainDockWidget(); + if ( mainDock->parentDockTabGroup() ) + { + mainDock = static_cast<KDockWidget*>( mainDock->parentDockTabGroup() ->parent() ); + } + + if ( widgetNames.count() > 0 ) + { + QStringList::iterator it = widgetNames.begin(); + KDockWidget *dwpd = manager() ->getDockWidgetFromName( *it ); + if ( !dwpd ) + { + kdDebug(760) << "Fatal error in finishIDEAlMode" << endl; + return ; + } + dwpd->manualDock( mainDock, pos, 20 ); + ++it; + for ( ;it != widgetNames.end();++it ) + { + KDockWidget *tmpdw = manager() ->getDockWidgetFromName( *it ); + if ( !tmpdw ) + { + kdDebug(760) << "Fatal error in finishIDEAlMode" << endl; + return ; + } + tmpdw->manualDock( dwpd, KDockWidget::DockCenter, 20 ); + } + +#if 0 + QWidget *wid = dwpd->parentDockTabGroup(); + if ( !wid ) + wid = dwpd; + wid->setGeometry( 0, 0, 20, 20 ); + /* wid->resize( + ((pos==KDockWidget::DockLeft) || (pos==KDockWidget::DockRight))?size:wid->width(), + ((pos==KDockWidget::DockLeft) || (pos==KDockWidget::DockRight))?wid->height():size); + */ +#endif + + } + +} + + +/** + * redirect the signal for insertion of buttons to an own slot + * that means: If the menubar (where the buttons should be inserted) is given, + * QextMDI can insert them automatically. + * Otherwise only signals can be emitted to tell the outside that + * someone must do this job itself. + */ +void KMdiMainFrm::setMenuForSDIModeSysButtons( KMenuBar* pMenuBar ) +{ + if ( m_bSDIApplication ) // there are no buttons in the menubar in this mode (although the view is always maximized) + return ; + + m_pMainMenuBar = pMenuBar; + if ( m_pMainMenuBar == 0L ) + return ; // use setMenuForSDIModeSysButtons( 0L) for unsetting the external main menu! + + if ( !m_pUndock ) + m_pUndock = new QToolButton( pMenuBar ); + if ( !m_pRestore ) + m_pRestore = new QToolButton( pMenuBar ); + if ( !m_pMinimize ) + m_pMinimize = new QToolButton( pMenuBar ); + if ( !m_pClose ) + m_pClose = new QToolButton( pMenuBar ); + m_pUndock->setAutoRaise( false ); + m_pMinimize->setAutoRaise( false ); + m_pRestore->setAutoRaise( false ); + m_pClose->setAutoRaise( false ); + + setSysButtonsAtMenuPosition(); + + delete m_pUndockButtonPixmap; + delete m_pMinButtonPixmap; + delete m_pRestoreButtonPixmap; + delete m_pCloseButtonPixmap; + // create the decoration pixmaps + if ( frameDecorOfAttachedViews() == KMdi::Win95Look ) + { + m_pUndockButtonPixmap = new QPixmap( win_undockbutton ); + m_pMinButtonPixmap = new QPixmap( win_minbutton ); + m_pRestoreButtonPixmap = new QPixmap( win_restorebutton ); + m_pCloseButtonPixmap = new QPixmap( win_closebutton ); + } + else if ( frameDecorOfAttachedViews() == KMdi::KDE1Look ) + { + m_pUndockButtonPixmap = new QPixmap( kde_undockbutton ); + m_pMinButtonPixmap = new QPixmap( kde_minbutton ); + m_pRestoreButtonPixmap = new QPixmap( kde_restorebutton ); + m_pCloseButtonPixmap = new QPixmap( kde_closebutton ); + m_pUndock->setAutoRaise( true ); + m_pMinimize->setAutoRaise( true ); + m_pRestore->setAutoRaise( true ); + m_pClose->setAutoRaise( true ); + } + else if ( frameDecorOfAttachedViews() == KMdi::KDELook ) + { + m_pUndockButtonPixmap = new QPixmap( kde2_undockbutton ); + m_pMinButtonPixmap = new QPixmap( kde2_minbutton ); + m_pRestoreButtonPixmap = new QPixmap( kde2_restorebutton ); + m_pCloseButtonPixmap = new QPixmap( kde2_closebutton ); + } + else + { // kde2laptop look + m_pUndockButtonPixmap = new QPixmap( kde2laptop_undockbutton ); + m_pMinButtonPixmap = new QPixmap( kde2laptop_minbutton ); + m_pRestoreButtonPixmap = new QPixmap( kde2laptop_restorebutton ); + m_pCloseButtonPixmap = new QPixmap( kde2laptop_closebutton ); + } + + m_pUndock->hide(); + m_pMinimize->hide(); + m_pRestore->hide(); + m_pClose->hide(); + + m_pUndock->setPixmap( *m_pUndockButtonPixmap ); + m_pMinimize->setPixmap( *m_pMinButtonPixmap ); + m_pRestore->setPixmap( *m_pRestoreButtonPixmap ); + m_pClose->setPixmap( *m_pCloseButtonPixmap ); +} + +void KMdiMainFrm::setSysButtonsAtMenuPosition() +{ + if ( m_pMainMenuBar == 0L ) + return ; + if ( m_pMainMenuBar->parentWidget() == 0L ) + return ; + + int menuW = m_pMainMenuBar->parentWidget() ->width(); + int h; + int y; + if ( frameDecorOfAttachedViews() == KMdi::Win95Look ) + h = 16; + else if ( frameDecorOfAttachedViews() == KMdi::KDE1Look ) + h = 20; + else if ( frameDecorOfAttachedViews() == KMdi::KDELook ) + h = 16; + else + h = 14; + y = m_pMainMenuBar->height() / 2 - h / 2; + + if ( frameDecorOfAttachedViews() == KMdi::KDELaptopLook ) + { + int w = 27; + m_pUndock->setGeometry( ( menuW - ( w * 3 ) - 5 ), y, w, h ); + m_pMinimize->setGeometry( ( menuW - ( w * 2 ) - 5 ), y, w, h ); + m_pRestore->setGeometry( ( menuW - w - 5 ), y, w, h ); + } + else + { + m_pUndock->setGeometry( ( menuW - ( h * 4 ) - 5 ), y, h, h ); + m_pMinimize->setGeometry( ( menuW - ( h * 3 ) - 5 ), y, h, h ); + m_pRestore->setGeometry( ( menuW - ( h * 2 ) - 5 ), y, h, h ); + m_pClose->setGeometry( ( menuW - h - 5 ), y, h, h ); + } +} + +/** Activates the next open view */ +void KMdiMainFrm::activateNextWin() +{ + KMdiIterator<KMdiChildView*>* it = createIterator(); + KMdiChildView* aWin = activeWindow(); + for ( it->first(); !it->isDone(); it->next() ) + { + if ( it->currentItem() == aWin ) + { + it->next(); + if ( !it->currentItem() ) + { + it->first(); + } + if ( it->currentItem() ) + { + activateView( it->currentItem() ); + } + break; + } + } + delete it; +} + +/** Activates the previous open view */ +void KMdiMainFrm::activatePrevWin() +{ + KMdiIterator<KMdiChildView*>* it = createIterator(); + KMdiChildView* aWin = activeWindow(); + for ( it->first(); !it->isDone(); it->next() ) + { + if ( it->currentItem() == aWin ) + { + it->prev(); + if ( !it->currentItem() ) + { + it->last(); + } + if ( it->currentItem() ) + { + activateView( it->currentItem() ); + } + break; + } + } + delete it; +} + +/** Activates the view we accessed the most time ago */ +void KMdiMainFrm::activateFirstWin() +{ + m_bSwitching= true; // flag that we are currently switching between windows + KMdiIterator<KMdiChildView*>* it = createIterator(); + QMap<QDateTime, KMdiChildView*> m; + for ( it->first(); !it->isDone(); it->next() ) + { + m.insert( it->currentItem() ->getTimeStamp(), it->currentItem() ); + } + + if ( !activeWindow() ) + return ; + + QDateTime current = activeWindow() ->getTimeStamp(); + QMap<QDateTime, KMdiChildView*>::iterator pos( m.find( current ) ); + QMap<QDateTime, KMdiChildView*>::iterator newPos = pos; + if ( pos != m.end() ) + { + ++newPos; + } + if ( newPos != m.end() ) + { // look ahead + ++pos; + } + else + { + pos = m.begin(); + } + activateView( pos.data() ); + delete it; +} + +/** Activates the previously accessed view before this one was activated */ +void KMdiMainFrm::activateLastWin() +{ + m_bSwitching= true; // flag that we are currently switching between windows + KMdiIterator<KMdiChildView*>* it = createIterator(); + QMap<QDateTime, KMdiChildView*> m; + for ( it->first(); !it->isDone(); it->next() ) + { + m.insert( it->currentItem() ->getTimeStamp(), it->currentItem() ); + } + + if ( !activeWindow() ) + return ; + + QDateTime current = activeWindow() ->getTimeStamp(); + QMap<QDateTime, KMdiChildView*>::iterator pos( m.find( current ) ); + if ( pos != m.begin() ) + { + --pos; + } + else + { + pos = m.end(); + --pos; + } + activateView( pos.data() ); + delete it; +} + +/** Activates the view with a certain index (TabPage mode only) */ +void KMdiMainFrm::activateView( int index ) +{ + KMdiChildView * pView = m_pDocumentViews->first(); + for ( int i = 0; pView && ( i < index ); i++ ) + { + pView = m_pDocumentViews->next(); + } + if ( pView ) + { + pView->activate(); + } +} + +/** turns the system buttons for maximize mode (SDI mode) on, and connects them with the current child frame */ +void KMdiMainFrm::setEnableMaximizedChildFrmMode( bool enableMaxChildFrameMode ) +{ + if ( enableMaxChildFrameMode ) + { + kdDebug(760) << k_funcinfo << "Turning on maximized child frame mode" << endl; + m_bMaximizedChildFrmMode = true; + + KMdiChildFrm* pCurrentChild = m_pMdi->topChild(); + + //If we have no child or there is no menubar, we do nothing + if ( !pCurrentChild || !m_pMainMenuBar ) + return ; + + QObject::connect( m_pUndock, SIGNAL( clicked() ), pCurrentChild, SLOT( undockPressed() ) ); + QObject::connect( m_pMinimize, SIGNAL( clicked() ), pCurrentChild, SLOT( minimizePressed() ) ); + QObject::connect( m_pRestore, SIGNAL( clicked() ), pCurrentChild, SLOT( maximizePressed() ) ); + m_pMinimize->show(); + m_pUndock->show(); + m_pRestore->show(); + + if ( frameDecorOfAttachedViews() == KMdi::KDELaptopLook ) + { + m_pMainMenuBar->insertItem( QPixmap( kde2laptop_closebutton_menu ), m_pMdi->topChild(), SLOT( closePressed() ), 0, -1, 0 ); + } + else + { + m_pMainMenuBar->insertItem( *pCurrentChild->icon(), pCurrentChild->systemMenu(), -1, 0 ); + if ( m_pClose ) + { + QObject::connect( m_pClose, SIGNAL( clicked() ), pCurrentChild, SLOT( closePressed() ) ); + m_pClose->show(); + } + else + kdDebug(760) << k_funcinfo << "no close button. things won't behave correctly" << endl; + } + } + else + { + if ( !m_bMaximizedChildFrmMode ) + return ; // already set, nothing to do + + kdDebug(760) << k_funcinfo << "Turning off maximized child frame mode" << endl; + m_bMaximizedChildFrmMode = false; + + KMdiChildFrm* pFrmChild = m_pMdi->topChild(); + if ( pFrmChild && pFrmChild->m_pClient && pFrmChild->state() == KMdiChildFrm::Maximized ) + { + pFrmChild->m_pClient->restore(); + switchOffMaximizeModeForMenu( pFrmChild ); + } + } +} + +/** turns the system buttons for maximize mode (SDI mode) off, and disconnects them */ +void KMdiMainFrm::switchOffMaximizeModeForMenu( KMdiChildFrm* oldChild ) +{ + // if there is no menubar given, those system buttons aren't possible + if ( !m_pMainMenuBar ) + return ; + + m_pMainMenuBar->removeItem( m_pMainMenuBar->idAt( 0 ) ); + + if ( oldChild ) + { + Q_ASSERT( m_pClose ); + QObject::disconnect( m_pUndock, SIGNAL( clicked() ), oldChild, SLOT( undockPressed() ) ); + QObject::disconnect( m_pMinimize, SIGNAL( clicked() ), oldChild, SLOT( minimizePressed() ) ); + QObject::disconnect( m_pRestore, SIGNAL( clicked() ), oldChild, SLOT( maximizePressed() ) ); + QObject::disconnect( m_pClose, SIGNAL( clicked() ), oldChild, SLOT( closePressed() ) ); + } + m_pUndock->hide(); + m_pMinimize->hide(); + m_pRestore->hide(); + m_pClose->hide(); +} + +/** reconnects the system buttons form maximize mode (SDI mode) with the new child frame */ +void KMdiMainFrm::updateSysButtonConnections( KMdiChildFrm* oldChild, KMdiChildFrm* newChild ) +{ + //qDebug("updateSysButtonConnections"); + // if there is no menubar given, those system buttons aren't possible + if ( !m_pMainMenuBar ) + return ; + + if ( newChild ) + { + if ( frameDecorOfAttachedViews() == KMdi::KDELaptopLook ) + m_pMainMenuBar->insertItem( QPixmap( kde2laptop_closebutton_menu ), newChild, SLOT( closePressed() ), 0, -1, 0 ); + else + m_pMainMenuBar->insertItem( *newChild->icon(), newChild->systemMenu(), -1, 0 ); + } + + if ( oldChild ) + { + m_pMainMenuBar->removeItem( m_pMainMenuBar->idAt( 1 ) ); + Q_ASSERT( m_pClose ); + QObject::disconnect( m_pUndock, SIGNAL( clicked() ), oldChild, SLOT( undockPressed() ) ); + QObject::disconnect( m_pMinimize, SIGNAL( clicked() ), oldChild, SLOT( minimizePressed() ) ); + QObject::disconnect( m_pRestore, SIGNAL( clicked() ), oldChild, SLOT( maximizePressed() ) ); + QObject::disconnect( m_pClose, SIGNAL( clicked() ), oldChild, SLOT( closePressed() ) ); + } + if ( newChild ) + { + Q_ASSERT( m_pClose ); + QObject::connect( m_pUndock, SIGNAL( clicked() ), newChild, SLOT( undockPressed() ) ); + QObject::connect( m_pMinimize, SIGNAL( clicked() ), newChild, SLOT( minimizePressed() ) ); + QObject::connect( m_pRestore, SIGNAL( clicked() ), newChild, SLOT( maximizePressed() ) ); + QObject::connect( m_pClose, SIGNAL( clicked() ), newChild, SLOT( closePressed() ) ); + } +} + +/** Shows the view taskbar. This should be connected with your "View" menu. */ +bool KMdiMainFrm::isViewTaskBarOn() +{ + if ( m_pTaskBar ) + return m_pTaskBar->isSwitchedOn(); + else + return false; +} + +/** Shows the view taskbar. This should be connected with your "View" menu. */ +void KMdiMainFrm::showViewTaskBar() +{ + if ( m_pTaskBar ) + m_pTaskBar->switchOn( true ); +} + +/** Hides the view taskbar. This should be connected with your "View" menu. */ +void KMdiMainFrm::hideViewTaskBar() +{ + if ( m_pTaskBar ) + m_pTaskBar->switchOn( false ); +} + +//=============== fillWindowMenu ===============// +void KMdiMainFrm::fillWindowMenu() +{ + bool tabPageMode = false; + if ( m_mdiMode == KMdi::TabPageMode ) + tabPageMode = true; + + bool IDEAlMode = false; + if ( m_mdiMode == KMdi::IDEAlMode ) + IDEAlMode = true; + + bool noViewOpened = false; + if ( m_pDocumentViews->isEmpty() ) + noViewOpened = true; + + // construct the menu and its submenus + if ( !m_bClearingOfWindowMenuBlocked ) + m_pWindowMenu->clear(); + + d->closeWindowAction->plug(m_pWindowMenu); + + int closeAllId = m_pWindowMenu->insertItem( i18n( "Close &All" ), this, SLOT( closeAllViews() ) ); + if ( noViewOpened ) + { + d->closeWindowAction->setEnabled(false); + m_pWindowMenu->setItemEnabled( closeAllId, false ); + } + + if ( !tabPageMode && !IDEAlMode ) + { + int iconifyId = m_pWindowMenu->insertItem( i18n( "&Minimize All" ), this, SLOT( iconifyAllViews() ) ); + if ( noViewOpened ) + m_pWindowMenu->setItemEnabled( iconifyId, false ); + } + + m_pWindowMenu->insertSeparator(); + m_pWindowMenu->insertItem( i18n( "&MDI Mode" ), m_pMdiModeMenu ); + m_pMdiModeMenu->clear(); + m_pMdiModeMenu->insertItem( i18n( "&Toplevel Mode" ), this, SLOT( switchToToplevelMode() ) ); + m_pMdiModeMenu->insertItem( i18n( "C&hildframe Mode" ), this, SLOT( switchToChildframeMode() ) ); + m_pMdiModeMenu->insertItem( i18n( "Ta&b Page Mode" ), this, SLOT( switchToTabPageMode() ) ); + m_pMdiModeMenu->insertItem( i18n( "I&DEAl Mode" ), this, SLOT( switchToIDEAlMode() ) ); + switch ( m_mdiMode ) + { + case KMdi::ToplevelMode: + m_pMdiModeMenu->setItemChecked( m_pMdiModeMenu->idAt( 0 ), true ); + break; + case KMdi::ChildframeMode: + m_pMdiModeMenu->setItemChecked( m_pMdiModeMenu->idAt( 1 ), true ); + break; + case KMdi::TabPageMode: + m_pMdiModeMenu->setItemChecked( m_pMdiModeMenu->idAt( 2 ), true ); + break; + case KMdi::IDEAlMode: + m_pMdiModeMenu->setItemChecked( m_pMdiModeMenu->idAt( 3 ), true ); + break; + default: + break; + } + + m_pWindowMenu->insertSeparator(); + if ( !tabPageMode && !IDEAlMode ) + { + int placMenuId = m_pWindowMenu->insertItem( i18n( "&Tile" ), m_pPlacingMenu ); + m_pPlacingMenu->clear(); + m_pPlacingMenu->insertItem( i18n( "Ca&scade Windows" ), m_pMdi, SLOT( cascadeWindows() ) ); + m_pPlacingMenu->insertItem( i18n( "Cascade &Maximized" ), m_pMdi, SLOT( cascadeMaximized() ) ); + m_pPlacingMenu->insertItem( i18n( "Expand &Vertically" ), m_pMdi, SLOT( expandVertical() ) ); + m_pPlacingMenu->insertItem( i18n( "Expand &Horizontally" ), m_pMdi, SLOT( expandHorizontal() ) ); + m_pPlacingMenu->insertItem( i18n( "Tile &Non-Overlapped" ), m_pMdi, SLOT( tileAnodine() ) ); + m_pPlacingMenu->insertItem( i18n( "Tile Overla&pped" ), m_pMdi, SLOT( tilePragma() ) ); + m_pPlacingMenu->insertItem( i18n( "Tile V&ertically" ), m_pMdi, SLOT( tileVertically() ) ); + if ( m_mdiMode == KMdi::ToplevelMode ) + { + m_pWindowMenu->setItemEnabled( placMenuId, false ); + } + m_pWindowMenu->insertSeparator(); + int dockUndockId = m_pWindowMenu->insertItem( i18n( "&Dock/Undock" ), m_pDockMenu ); + m_pDockMenu->clear(); + m_pWindowMenu->insertSeparator(); + if ( noViewOpened ) + { + m_pWindowMenu->setItemEnabled( placMenuId, false ); + m_pWindowMenu->setItemEnabled( dockUndockId, false ); + } + } + int entryCount = m_pWindowMenu->count(); + + // for all child frame windows: give an ID to every window and connect them in the end with windowMenuItemActivated() + int i = 100; + KMdiChildView* pView = 0L; + QPtrListIterator<KMdiChildView> it( *m_pDocumentViews ); + QValueList<QDateTime> timeStamps; + for ( ; it.current(); ++it ) + { + pView = it.current(); + QDateTime timeStamp( pView->getTimeStamp() ); + + if ( pView->isToolView() ) + { + continue; + } + + QString item; + // set titles of minimized windows in brackets + if ( pView->isMinimized() ) + { + item += "("; + item += pView->caption(); + item += ")"; + } + else + { + item += " "; + item += pView->caption(); + } + + // insert the window entry sorted by access time + unsigned int indx; + unsigned int windowItemCount = m_pWindowMenu->count() - entryCount; + bool inserted = false; + QString tmpString; + QValueList<QDateTime>::iterator timeStampIterator = timeStamps.begin(); + for ( indx = 0; indx <= windowItemCount; indx++, ++timeStampIterator ) + { + bool putHere = false; + if ( ( *timeStampIterator ) < timeStamp ) + { + putHere = true; + timeStamps.insert( timeStampIterator, timeStamp ); + } + if ( putHere ) + { + m_pWindowMenu->insertItem( item, pView, SLOT( slot_clickedInWindowMenu() ), 0, -1, indx + entryCount ); + if ( pView == m_pCurrentWindow ) + { + m_pWindowMenu->setItemChecked( m_pWindowMenu->idAt( indx + entryCount ), true ); + } + pView->setWindowMenuID( i ); + if ( !tabPageMode ) + { + m_pDockMenu->insertItem( item, pView, SLOT( slot_clickedInDockMenu() ), 0, -1, indx ); + if ( pView->isAttached() ) + { + m_pDockMenu->setItemChecked( m_pDockMenu->idAt( indx ), true ); + } + } + inserted = true; + break; + indx = windowItemCount + 1; // break the loop + } + } + if ( !inserted ) + { // append it + m_pWindowMenu->insertItem( item, pView, SLOT( slot_clickedInWindowMenu() ), 0, -1, windowItemCount + entryCount ); + if ( pView == m_pCurrentWindow ) + { + m_pWindowMenu->setItemChecked( m_pWindowMenu->idAt( windowItemCount + entryCount ), true ); + } + pView->setWindowMenuID( i ); + if ( !tabPageMode ) + { + m_pDockMenu->insertItem( item, pView, SLOT( slot_clickedInDockMenu() ), 0, -1, windowItemCount ); + if ( pView->isAttached() ) + { + m_pDockMenu->setItemChecked( m_pDockMenu->idAt( windowItemCount ), true ); + } + } + } + i++; + } +} + +//================ windowMenuItemActivated ===============// + +void KMdiMainFrm::windowMenuItemActivated( int id ) +{ + if ( id < 100 ) + return ; + id -= 100; + KMdiChildView *pView = m_pDocumentViews->at( id ); + if ( !pView ) + return ; + if ( pView->isMinimized() ) + pView->minimize(); + if ( m_mdiMode != KMdi::TabPageMode ) + { + KMdiChildFrm * pTopChild = m_pMdi->topChild(); + if ( pTopChild ) + { + if ( ( pView == pTopChild->m_pClient ) && pView->isAttached() ) + { + return ; + } + } + } + activateView( pView ); +} + +//================ dockMenuItemActivated ===============// + +void KMdiMainFrm::dockMenuItemActivated( int id ) +{ + if ( id < 100 ) + return ; + id -= 100; + KMdiChildView *pView = m_pDocumentViews->at( id ); + if ( !pView ) + return ; + if ( pView->isMinimized() ) + pView->minimize(); + if ( pView->isAttached() ) + { + detachWindow( pView, true ); + } + else + { // is detached + attachWindow( pView, true ); + } +} + +//================ popupWindowMenu ===============// + +void KMdiMainFrm::popupWindowMenu( QPoint p ) +{ + if ( !isFakingSDIApplication() ) + { + m_pWindowMenu->popup( p ); + } +} + +//================ dragEndTimeOut ===============// +void KMdiMainFrm::dragEndTimeOut() +{ + // send drag end to all concerned views. + KMdiChildView * pView; + for ( m_pDocumentViews->first(); ( pView = m_pDocumentViews->current() ) != 0L; m_pDocumentViews->next() ) + { + KMdiChildFrmDragEndEvent dragEndEvent( 0L ); + QApplication::sendEvent( pView, &dragEndEvent ); + } +} + +//================ setFrameDecorOfAttachedViews ===============// + +void KMdiMainFrm::setFrameDecorOfAttachedViews( int frameDecor ) +{ + switch ( frameDecor ) + { + case 0: + m_frameDecoration = KMdi::Win95Look; + break; + case 1: + m_frameDecoration = KMdi::KDE1Look; + break; + case 2: + m_frameDecoration = KMdi::KDELook; + break; + case 3: + m_frameDecoration = KMdi::KDELaptopLook; + break; + default: + qDebug( "unknown MDI decoration" ); + break; + } + setMenuForSDIModeSysButtons( m_pMainMenuBar ); + QPtrListIterator<KMdiChildView> it( *m_pDocumentViews ); + for ( ; it.current(); ++it ) + { + KMdiChildView* pView = it.current(); + if ( pView->isToolView() ) + continue; + if ( pView->isAttached() ) + pView->mdiParent() ->redecorateButtons(); + } +} + +void KMdiMainFrm::fakeSDIApplication() +{ + m_bSDIApplication = true; + if ( m_pTaskBar ) + m_pTaskBar->close(); + m_pTaskBar = 0L; +} + +void KMdiMainFrm::closeViewButtonPressed() +{ + KMdiChildView * pView = activeWindow(); + if ( pView ) + { + pView->close(); + } +} + +void KMdiMainFrm::setManagedDockPositionModeEnabled( bool enabled ) +{ + m_managedDockPositionMode = enabled; +} + +void KMdiMainFrm::setActiveToolDock( KMdiDockContainer* td ) +{ + if ( td == d->activeDockPriority[ 0 ] ) + return ; + if ( d->activeDockPriority[ 0 ] == 0 ) + { + d->activeDockPriority[ 0 ] = td; + // d->focusList=new KMdiFocusList(this); + // if (m_pMdi) d->focusList->addWidgetTree(m_pMdi); + // if (m_documentTabWidget) d->focusList->addWidgetTree(m_documentTabWidget); + return ; + } + for ( int dst = 3, src = 2;src >= 0;dst--, src-- ) + { + if ( d->activeDockPriority[ src ] == td ) + src--; + if ( src < 0 ) + break; + d->activeDockPriority[ dst ] = d->activeDockPriority[ src ]; + } + d->activeDockPriority[ 0 ] = td; +} + +void KMdiMainFrm::removeFromActiveDockList( KMdiDockContainer* td ) +{ + for ( int i = 0;i < 4;i++ ) + { + if ( d->activeDockPriority[ i ] == td ) + { + for ( ;i < 3;i++ ) + d->activeDockPriority[ i ] = d->activeDockPriority[ i + 1 ]; + d->activeDockPriority[ 3 ] = 0; + break; + } + } + /* + if (d->activeDockPriority[0]==0) { + if (d->focusList) d->focusList->restore(); + delete d->focusList; + d->focusList=0; + } + */ +} + +void KMdiMainFrm::prevToolViewInDock() +{ + KMdiDockContainer * td = d->activeDockPriority[ 0 ]; + if ( !td ) + return ; + td->prevToolView(); +} + +void KMdiMainFrm::nextToolViewInDock() +{ + KMdiDockContainer * td = d->activeDockPriority[ 0 ]; + if ( !td ) + return ; + td->nextToolView(); +} + +KMdi::TabWidgetVisibility KMdiMainFrm::tabWidgetVisibility() +{ + if ( m_documentTabWidget ) + return m_documentTabWidget->tabWidgetVisibility(); + + return KMdi::NeverShowTabs; +} + +void KMdiMainFrm::setTabWidgetVisibility( KMdi::TabWidgetVisibility visibility ) +{ + if ( m_documentTabWidget ) + m_documentTabWidget->setTabWidgetVisibility( visibility ); +} + +KTabWidget * KMdiMainFrm::tabWidget() const +{ + return m_documentTabWidget; +} + +#include "kmdimainfrm.moc" + +// vim: ts=2 sw=2 et +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; diff --git a/lib/compatibility/kmdi/qextmdi/kmdimainfrm.h b/lib/compatibility/kmdi/qextmdi/kmdimainfrm.h new file mode 100644 index 00000000..24a956cf --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmdimainfrm.h @@ -0,0 +1,872 @@ +//---------------------------------------------------------------------------- +// filename : kmdimainfrm.h +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 07/1999 by Szymon Stefanek as part of kvirc +// (an IRC application) +// changes : 09/1999 by Falk Brettschneider to create an +// - 06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// : 02/2000 by Massimo Morin (mmorin@schedsys.com) +// 2000-2003 maintained by the KDevelop project +// patches : */2000 by Lars Beikirch (Lars.Beikirch@gmx.net) +// : 01/2003 by Jens Zurheide (jens.zurheide@gmx.de) +// +// copyright : (C) 1999-2003 by Falk Brettschneider +// and +// Szymon Stefanek (stefanek@tin.it) +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program 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. +// +//---------------------------------------------------------------------------- + +#ifndef _KMDIMAINFRM_H_ +#define _KMDIMAINFRM_H_ + +#include <kparts/dockmainwindow.h> +#include <kmenubar.h> +#include <kpopupmenu.h> + +#include <qptrlist.h> +#include <qrect.h> +#include <qapplication.h> +#include <qdom.h> +#include <qguardedptr.h> + +#include "kmditaskbar.h" +#include "kmdichildarea.h" +#include "kmdichildview.h" +#include "kmdiiterator.h" +#include "kmdilistiterator.h" +#include "kmdinulliterator.h" +#include "kmditoolviewaccessor.h" + +class QTimer; +class QPopupMenu; +class QMenuBar; + + +class QToolButton; + +namespace KMDIPrivate +{ +class KMDIGUIClient; +} + +class KMdiDockContainer; +class KMdiMainFrmPrivate; + +/** + * @short Internal class + * + * This special event is needed because the view has to inform the main frame that it`s being closed. + */ +class KMDI_EXPORT KMdiViewCloseEvent : public QCustomEvent +{ +public: + KMdiViewCloseEvent( KMdiChildView* pWnd ) : QCustomEvent( QEvent::User, pWnd ) {} +}; + +/** + * \short Base class for all your special main frames. + * + * It contains the child frame area (QMainWindow's central widget) and a child view taskbar + * for switching the MDI views. Most methods are virtual functions for later overriding. + * + * Basically, this class provides functionality for docking/undocking view windows and + * manages the taskbar. Usually a developer will only need to know about this class and + * \ref KMdiChildView. + * + * \par General usage + * + * Your program mainwidget should inherit KMdiMainFrm. Then usually you'll just need + * addWindow() and removeWindowFromMdi() to control the views. + * \code + * class MyMainWindow : public KMdiMainFrm + * { .... }; + * \endcode + * + * to define your main window class and + * + * \code + * MyMainWindow mainframe; + * qApp->setMainWidget(&mainframe); + * mainframe->addWindow(view1); // put it under MDI control + * mainframe->addWindow(view2); + * \endcode + * + * when you wish to use your main window class. The above example also adds a few windows + * to the frame. + * + * KMdiMainFrm will provide the "Window" menu needed in common MDI applications. Just + * insert it in your main menu: + * + * \code + * if ( !isFakingSDIApplication() ) + * { + * menuBar()->insertItem( i18n( "&Window" ), windowMenu() ); + * } + * \endcode + * + * To synchronize the positions of the MDI control buttons inserted in your mainmenu: + * \code + * void B_MainModuleWidget::initMenuBar() + * { + * setMenuForSDIModeSysButtons( menuBar() ); + * } + * ... + * void B_MainModuleWidget::resizeEvent ( QResizeEvent *e ) + * { + * KMdiMainFrm::resizeEvent( e ); + * setSysButtonsAtMenuPosition(); + * } + * \endcode + * + * \par Dynamic mode switching + * + * Dynamic switching of the MDI mode can be done via the following functions: + * - switchToChildframeMode() + * - switchToToplevelMode() + * - switchToTabPageMode() + * - switchToIDEAlMode() + * + * The MDI mode can be gotten using mdiMode(). If you need to fake the look of an SDI application + * use fakeSDIApplication() to fake it and isFakingSDIApplication() to query whether or not an SDI + * interface is being faked. + * + * You can dynamically change the shape of the attached MDI views using setFrameDecorOfAttachedViews(). + * + * Additionally, here's a hint how to restore the mainframe's settings from config file: + * \code + * + * // restore MDI mode (toplevel, childframe, tabpage) + * int mdiMode = config->readIntEntry( "mainmodule session", "MDI mode", KMdi::ChildframeMode); + * switch (mdiMode) { + * case KMdi::ToplevelMode: + * { + * int childFrmModeHt = config->readIntEntry( "mainmodule session", "Childframe mode height", desktop()->height() - 50); + * mainframe->resize( m_pMdiMainFrm->width(), childFrmModeHt); + * mainframe->switchToToplevelMode(); + * } + * break; + * case KMdi::ChildframeMode: + * break; + * case KMdi::TabPageMode: + * { + * int childFrmModeHt = m_pCfgFileManager->readIntEntry( "mainmodule session", "Childframe mode height", desktop()->height() - 50); + * mainframe->resize( m_pMdiMainFrm->width(), childFrmModeHt); + * mainframe->switchToTabPageMode(); + * } + * break; + * default: + * break; + * } + * + * // restore a possible maximized Childframe mode + * bool maxChildFrmMode = config->readBoolEntry( "mainmodule session", "maximized childframes", true); + * mainframe->setEnableMaximizedChildFrmMode(maxChildFrmMode); + * \endcode + * The maximized-Childframe mode means that currently all views are maximized in Childframe mode's application desktop. + * + * \par Managing views + * + * This class provides placing algorithms in Childframe mode. The following is a list of the window placement functions + * - tilePragma() - Tile the windows and allow them to overlap + * - tileAnodine() - Tile the windows but don't allow them to overlap + * - tileVertically() - Tile the windows vertically + * - cascadeWindows() - cascade windows + * - cascadeMaximized() - cascade windows and maximize their viewing area + * - expandVertical() - expand all the windows to use the most amount of vertical space + * - expandHorizontal() - expand all the windows to use the most amount of horizontal space + * + * activateView(KMdiChildView*) and activateView(int index) set the appropriate MDI child view as the active + * one. It will be raised, will get an active MDI frame and will get the focus. Call activeView() to find out what the + * current MDI view is. + * + * Use detachWindow() and attachWindow() for docking the MDI views to desktop and back. + * + * Connect accels of your program with activatePrevWin(), activateNextWin() and activateView(int index). + * + * Note: KMdiChildViews can be added in 2 meanings: Either as a normal child view (usually containing + * user document views) or as a tool-view (usually containing status, info or control widgets). + * The tool-views can be added as floating dockwidgets or as stay-on-top desktop windows in tool style. + * + * Also, pay attention to the fact that when you click on the close button of MDI views that their + * close event should be redirected to closeWindow(). Otherwise the mainframe class will + * not get noticed about the deleted view and a dangling pointer will remain in the MDI control. The + * closeWindow() or the removeWindowFromMdi() method is for that issue. The difference is closeWindow() + * deletes the view object. So if your application wants to control that by itself, call removeWindowFromMdi() + * and call delete by yourself. See also KMdiChildView::closeEvent() for that issue. + * + * Here's an example how you can suggest things for the adding of views to the MDI control via flags: + * \code + * m_mapOfMdiWidgets.insert( pWnd, mh ); + * unsigned int mdiFlags = KMdi::StandardAdd; + * + * if ( !show ) + * mdiFlags |= KMdi::Hide; + * + * if ( !attach ) + * mdiFlags |= KMdi::Detach; + * + * if ( minimize ) + * mdiFlags |= KMdi::Minimize; + * + * if ( bToolWindow) + * mdiFlags |= KMdi::ToolWindow; + * + * if ( m_pMdiMainFrm->isFakingSDIApplication() ) + * { + * if ( attach ) //fake an SDI app + * mdiFlags |= KMdi::Maximize; + * } + * else + * { + * m_pMdiMainFrm->addWindow( pWnd, QPoint(20, 20), KMdi::AddWindowFlags(mdiFlags)); + * return; + * } + * m_pMdiMainFrm->addWindow( pWnd, KMdi::AddWindowFlags(mdiFlags)); + * \endcode + */ +class KMDI_EXPORT KMdiMainFrm : public KParts::DockMainWindow +{ + friend class KMdiChildView; + friend class KMdiTaskBar; + Q_OBJECT + + friend class KMdiToolViewAccessor; + // attributes +protected: + KMdi::MdiMode m_mdiMode; + KMdiChildArea *m_pMdi; + KMdiTaskBar *m_pTaskBar; + QPtrList<KMdiChildView> *m_pDocumentViews; + QMap<QWidget*, KMdiToolViewAccessor*> *m_pToolViews; + KMdiChildView *m_pCurrentWindow; + QPopupMenu *m_pWindowPopup; + QPopupMenu *m_pTaskBarPopup; + QPopupMenu *m_pWindowMenu; + QPopupMenu *m_pDockMenu; + QPopupMenu *m_pMdiModeMenu; + QPopupMenu *m_pPlacingMenu; + KMenuBar *m_pMainMenuBar; + + QPixmap *m_pUndockButtonPixmap; + QPixmap *m_pMinButtonPixmap; + QPixmap *m_pRestoreButtonPixmap; + QPixmap *m_pCloseButtonPixmap; + + QToolButton *m_pUndock; + QToolButton *m_pMinimize; + QToolButton *m_pRestore; + QToolButton *m_pClose; + QPoint m_undockPositioningOffset; + bool m_bMaximizedChildFrmMode; + int m_oldMainFrmHeight; + int m_oldMainFrmMinHeight; + int m_oldMainFrmMaxHeight; + static KMdi::FrameDecor m_frameDecoration; + bool m_bSDIApplication; + KDockWidget* m_pDockbaseAreaOfDocumentViews; + QDomDocument* m_pTempDockSession; + bool m_bClearingOfWindowMenuBlocked; + + QTimer* m_pDragEndTimer; + + bool m_bSwitching; + + KDockWidget* m_leftContainer; + KDockWidget* m_rightContainer; + KDockWidget* m_topContainer; + KDockWidget* m_bottomContainer; + + +private: + KMdiMainFrmPrivate* d; + KMDIPrivate::KMDIGUIClient* m_mdiGUIClient; + bool m_managedDockPositionMode; + + // methods +public: + KMdiMainFrm( QWidget* parentWidget, const char* name = "", KMdi::MdiMode mdiMode = KMdi::ChildframeMode, WFlags flags = WType_TopLevel | WDestructiveClose ); + virtual ~KMdiMainFrm(); + + /** + * Control whether or not the standard MDI menu is displayed + * when a context menu is displayed + */ + void setStandardMDIMenuEnabled( bool showModeMenu = true ); + + void setManagedDockPositionModeEnabled( bool enabled ); + + /** + * Returns whether the application's MDI views are in maximized state or not. + */ + bool isInMaximizedChildFrmMode() { return m_bMaximizedChildFrmMode; } + + /** + * Returns the MDI mode. This can be one of the enumerations KMdi::MdiMode. + */ + KMdi::MdiMode mdiMode() { return m_mdiMode; } + + /** + * Returns the focused attached MDI view. + */ + KMdiChildView* activeWindow(); + + /** + * Returns a popup menu filled according to the MDI view state. You can override this + * method to insert additional entries there. The popup menu is usually popuped when the user + * clicks with the right mouse button on a taskbar entry. The default entries are: + * Undock/Dock, Restore/Maximize/Minimize, Close and an empty sub-popup ( windowPopup() ) + * menu called Operations. + */ + virtual QPopupMenu * taskBarPopup( KMdiChildView *pWnd, bool bIncludeWindowPopup = false ); + + /** + * Returns a popup menu with only a title "Window". You can fill it with own operations entries + * on the MDI view. This popup menu is inserted as last menu item in taskBarPopup() . + */ + virtual QPopupMenu * windowPopup( KMdiChildView *pWnd, bool bIncludeTaskbarPopup = true ); + + /** + * Called in the constructor (forces a resize of all MDI views) + */ + virtual void applyOptions(); + + /** + * Returns the KMdiChildView belonging to the given caption string. + */ + KMdiChildView * findWindow( const QString& caption ); + + enum ExistsAs {DocumentView, ToolView, AnyView}; + /** + * Returns whether this MDI child view is under MDI control (using addWindow() ) or not. + */ + bool windowExists( KMdiChildView *pWnd, ExistsAs as ); + + /** + * Catches certain Qt events and processes it here. + * Currently, here this catches only the KMdiViewCloseEvent (a KMdi user event) which is sent + * from itself in childWindowCloseRequest() right after a KMdiChildView::closeEvent() . + * The reason for this event to itself is simple: It just wants to break the function call stack. + * It continues the processing with calling closeWindow() . + * You see, a close() is translated to a closeWindow() . + * It is necessary that the main frame has to start an MDI view close action because it must + * remove the MDI view from MDI control, additionally. + * + * This method calls QMainWindow::event , additionally. + */ + virtual bool event( QEvent* e ); + + /** + * If there's a main menubar given, it will create the 4 maximize mode buttons there (undock, minimize, restore, close). + */ + virtual void setSysButtonsAtMenuPosition(); + + /** + * Returns the height of the taskbar. + */ + virtual int taskBarHeight() { return m_pTaskBar ? m_pTaskBar->height() : 0; } + + /** + * Sets an offset value that is used on detachWindow() . The undocked window + * is visually moved on the desktop by this offset. + */ + virtual void setUndockPositioningOffset( QPoint offset ) { m_undockPositioningOffset = offset; } + + /** + * If you don't want to know about the inner structure of the KMdi system, you can use + * this iterator to handle with the MDI view list in a more abstract way. + * The iterator hides what special data structure is used in KMdi. + */ + // FIXME And what exactly are we supposed to fix? -mattr + KMdiIterator<KMdiChildView*>* createIterator() + { + if ( m_pDocumentViews == 0L ) + { + return new KMdiNullIterator<KMdiChildView*>(); + } + else + { + return new KMdiListIterator<KMdiChildView>( *m_pDocumentViews ); + } + } + + /** + * Deletes an KMdiIterator created in the KMdi library (needed for the windows dll problem). + */ + void deleteIterator( KMdiIterator<KMdiChildView*>* pIt ) + { + delete pIt; + } + + /** + * Returns a popup menu that contains the MDI controlled view list. + * Additionally, this menu provides some placing actions for these views. + * Usually, you insert this popup menu in your main menubar as "Window" menu. + */ + QPopupMenu* windowMenu() const { return m_pWindowMenu; }; + + /** + * Sets a background color for the MDI view area widget. + */ + virtual void setBackgroundColor( const QColor &c ) { m_pMdi->setBackgroundColor( c ); } + + /** + * Sets a background pixmap for the MDI view area widget. + */ + virtual void setBackgroundPixmap( const QPixmap &pm ) { m_pMdi->setBackgroundPixmap( pm ); } + + /** + * Sets a size that is used as the default size for a newly to the MDI system added KMdiChildView . + * By default this size is 600x400. So all non-resized added MDI views appear in that size. + */ + void setDefaultChildFrmSize( const QSize& sz ) { m_pMdi->m_defaultChildFrmSize = sz; } + + /** + * Returns the default size for a newly added KMdiChildView. See setDefaultChildFrmSize() . + */ + QSize defaultChildFrmSize() { return m_pMdi->m_defaultChildFrmSize; } + + /** + * Do nothing when in Toplevel mode + */ + virtual void setMinimumSize( int minw, int minh ); + + /** + * Returns the Childframe mode height of this. Makes only sense when in Toplevel mode. + */ + int childFrameModeHeight() { return m_oldMainFrmHeight; }; + /** + * Tells the MDI system a QMenu where it can insert buttons for + * the system menu, undock, minimize, restore actions. + * If no such menu is given, KMdi simply overlays the buttons + * at the upper right-hand side of the main widget. + */ + virtual void setMenuForSDIModeSysButtons( KMenuBar* menuBar = 0 ); + + /** + * @return the decoration of the window frame of docked (attached) MDI views + */ + static int frameDecorOfAttachedViews() { return m_frameDecoration; } + + /** + * An SDI application user interface is faked: + * @li an opened view is always maximized + * @li buttons for maximized childframe mode aren't inserted in the main menubar + * @li taskbar and windowmenu are not created/updated + */ + void fakeSDIApplication(); + + /** + * @returns if we are faking an SDI application (fakeSDIApplication()) + */ + bool isFakingSDIApplication() const { return m_bSDIApplication; } + + virtual bool eventFilter( QObject *obj, QEvent *e ); + void findRootDockWidgets( QPtrList<KDockWidget>* pRootDockWidgetList, QValueList<QRect>* pPositionList ); + + /** We're switching something.*/ + void setSwitching( const bool switching ) { m_bSwitching = switching; } + bool switching( void ) const { return m_bSwitching; } + +public slots: + /** + * addWindow demands a KMdiChildView. This method wraps every QWidget in such an object and + * this way you can put every widget under MDI control. + */ + KMdiChildView* createWrapper( QWidget *view, const QString& name, const QString& shortName ); + + /** + * Adds a KMdiChildView to the MDI system. The main frame takes control of it. + * \param flags the flags for the view such as: + * \li whether the view should be attached or detached. + * \li whether the view should be shown or hidden + * \li whether the view should be maximized, minimized or restored (normalized) + * \li whether the view should be added as tool view (stay-on-top and toplevel) or added as document-type view. + */ + virtual void addWindow( KMdiChildView* pView, int flags = KMdi::StandardAdd ); + + //KDE4: merge the two methods + /** + * Adds a KMdiChildView to the MDI system. The main frame takes control of it. + * \param index the index of the tab we should insert the new tab after. If index == -1 then + * the tab will just be appended to the end. Using this parameter in childview mode has no effect. + * \param flags + * You can specify here whether: + * \li the view should be attached or detached. + * \li shown or hidden + * \li maximized, minimized or restored (normalized) + * \li added as tool view (stay-on-top and toplevel) or added as document-type view. + * \since 3.3 + */ + void addWindow( KMdiChildView* pView, int flags, int index ); + + /** + * Adds a KMdiChildView to the MDI system. The main frame takes control of it. + * \param pos move the child view to the specified position + * \param flags the flags for the view such as: + * \li whether the view should be attached or detached. + * \li whether the view should be shown or hidden + * \li whether the view should be maximized, minimized or restored (normalized) + * \li whether the view should be added as tool view (stay-on-top and toplevel) or + * added as document-type view. + */ + virtual void addWindow( KMdiChildView* pView, QPoint pos, int flags = KMdi::StandardAdd ); + + /** + * Adds a KMdiChildView to the MDI system. The main frame takes control of it. + * \param rectNormal Sets the geometry for this child view + * \param flags the flags for the view such as: + * \li whether the view should be attached or detached. + * \li whether the view should be shown or hidden + * \li whether the view should be maximized, minimized or restored (normalized) + * \li whether the view should be added as tool view (stay-on-top and toplevel) or + * added as document-type view. + */ + virtual void addWindow( KMdiChildView* pView, QRect rectNormal, int flags = KMdi::StandardAdd ); + + /** + * Usually called from addWindow() when adding a tool view window. It reparents the given widget + * as toplevel and stay-on-top on the application's main widget. + */ + virtual KMdiToolViewAccessor *addToolWindow( QWidget* pWnd, KDockWidget::DockPosition pos = KDockWidget::DockNone, + QWidget* pTargetWnd = 0L, int percent = 50, const QString& tabToolTip = 0, + const QString& tabCaption = 0 ); + + virtual void deleteToolWindow( QWidget* pWnd ); + virtual void deleteToolWindow( KMdiToolViewAccessor *accessor ); + + /** + * Using this method you have to use the setWidget method of the access object, and it is very recommendet, that you use + * the widgetContainer() method for the parent of your newly created widget + */ + KMdiToolViewAccessor *createToolWindow(); + + /** + * Removes a KMdiChildView from the MDI system and from the main frame`s control. + * The caller is responsible for deleting the view. If the view is not deleted it will + * be reparented to 0 + */ + virtual void removeWindowFromMdi( KMdiChildView *pWnd ); + + /** + * Removes a KMdiChildView from the MDI system and from the main frame`s control. + * Note: The view will be deleted! + */ + virtual void closeWindow( KMdiChildView *pWnd, bool layoutTaskBar = true ); + + /** + * Switches the KMdiTaskBar on and off. + */ + virtual void slot_toggleTaskBar(); + + /** + * Makes a main frame controlled undocked KMdiChildView docked. + * Doesn't work on KMdiChildView which aren't added to the MDI system. + * Use addWindow() for that. + */ + virtual void attachWindow( KMdiChildView *pWnd, bool bShow = true, bool bAutomaticResize = false ); + + /** + * Makes a docked KMdiChildView undocked. + * The view window still remains under the main frame's MDI control. + */ + virtual void detachWindow( KMdiChildView *pWnd, bool bShow = true ); + + /** + * Someone wants that the MDI view to be closed. This method sends a KMdiViewCloseEvent to itself + * to break the function call stack. See also event() . + */ + virtual void childWindowCloseRequest( KMdiChildView *pWnd ); + + /** + * Close all views + */ + virtual void closeAllViews(); + + /** + * Iconfiy all views + */ + virtual void iconifyAllViews(); + + /** + * Closes the view of the active (topchild) window + */ + virtual void closeActiveView(); + + /** + * Undocks all view windows (unix-like) + */ + virtual void switchToToplevelMode(); + virtual void finishToplevelMode(); + + /** + * Docks all view windows (Windows-like) + */ + virtual void switchToChildframeMode(); + virtual void finishChildframeMode(); + + /** + * Docks all view windows (Windows-like) + */ + virtual void switchToTabPageMode(); + virtual void finishTabPageMode(); + + /** + * Docks all view windows. Toolviews use dockcontainers + */ + virtual void switchToIDEAlMode(); + virtual void finishIDEAlMode( bool full = true ); + + /** + * Sets the appearance of the IDEAl mode. See KMultiTabBar styles for the first 3 bits. + * @deprecated use setToolviewStyle(int flags) instead + */ + void setIDEAlModeStyle( int flags ) KDE_DEPRECATED; + //KDE4: Get rid of the above. + /** + * Sets the appearance of the toolview tabs. + * @param flags See KMdi::ToolviewStyle. + * @since 3.3 + */ + void setToolviewStyle( int flags ); + /** + * @return if the view taskbar should be shown if there are MDI views + */ + bool isViewTaskBarOn(); + + /** + * Shows the view taskbar. This should be connected with your "View" menu. + */ + virtual void showViewTaskBar(); + + /** + * Hides the view taskbar. This should be connected with your "View" menu. + */ + virtual void hideViewTaskBar(); + + /** + * Update of the window menu contents. + */ + virtual void fillWindowMenu(); + + /** + * Cascades the windows without resizing them. + */ + virtual void cascadeWindows() { m_pMdi->cascadeWindows(); } + + /** + * Cascades the windows resizing them to the maximum available size. + */ + virtual void cascadeMaximized() { m_pMdi->cascadeMaximized(); } + + /** + * Maximizes only in vertical direction. + */ + virtual void expandVertical() { m_pMdi->expandVertical(); } + + /** + * Maximizes only in horizontal direction. + */ + virtual void expandHorizontal() { m_pMdi->expandHorizontal(); } + + /** + * Tile Pragma + */ + virtual void tilePragma() { m_pMdi->tilePragma(); } + + /** + * Tile Anodine + */ + virtual void tileAnodine() { m_pMdi->tileAnodine(); } + + /** + * Tile Vertically + */ + virtual void tileVertically() { m_pMdi->tileVertically(); } + + /** + * Sets the decoration of the window frame of docked (attached) MDI views + * @deprecated Will be removed in KDE 4 + */ + virtual void setFrameDecorOfAttachedViews( int frameDecor ); + + /** + * If in Childframe mode, we can switch between maximized or restored shown MDI views + */ + virtual void setEnableMaximizedChildFrmMode( bool bEnable ); + + /** + * Activates the next open view + */ + virtual void activateNextWin(); + + /** + * Activates the previous open view + */ + virtual void activatePrevWin(); + + /** + * Activates the view first viewed concerning to the access time. + */ + virtual void activateFirstWin(); + + /** + * Activates the view last viewed concerning to the access time. + */ + virtual void activateLastWin(); + + /** + * Activates the view with the tab page index (TabPage mode only) + */ + virtual void activateView( int index ); + +private: + void setupToolViewsForIDEALMode(); + void setupTabbedDocumentViewSpace(); + class KMdiDocumentViewTabWidget * m_documentTabWidget; + +protected: + + virtual void resizeEvent( QResizeEvent * ); + + /** + * Creates a new MDI taskbar (showing the MDI views as taskbar entries) and shows it. + */ + virtual void createTaskBar(); + + /** + * Creates the MDI view area and connects some signals and slots with the KMdiMainFrm widget. + */ + virtual void createMdiManager(); + + /** + * prevents fillWindowMenu() from m_pWindowMenu->clear(). You have to care for it by yourself. + * This is useful if you want to add some actions in your overridden fillWindowMenu() method. + */ + void blockClearingOfWindowMenu( bool bBlocked ) { m_bClearingOfWindowMenuBlocked = bBlocked; } + + void findToolViewsDockedToMain( QPtrList<KDockWidget>* list, KDockWidget::DockPosition dprtmw ); + void dockToolViewsIntoContainers( QPtrList<KDockWidget>& widgetsToReparent, KDockWidget *container ); + QStringList prepareIdealToTabs( KDockWidget* container ); + void idealToolViewsToStandardTabs( QStringList widgetNames, KDockWidget::DockPosition pos, int sizee ); + + /** Get tabwidget visibility */ + KMdi::TabWidgetVisibility tabWidgetVisibility(); + + /** Set tabwidget visibility */ + void setTabWidgetVisibility( KMdi::TabWidgetVisibility ); + + /** Returns the tabwidget used in IDEAl and Tabbed modes. Returns 0 in other modes. */ + class KTabWidget * tabWidget() const; + + +protected slots: // Protected slots + /** + * Sets the focus to this MDI view, raises it, activates its taskbar button and updates + * the system buttons in the main menubar when in maximized (Maximize mode). + */ + virtual void activateView( KMdiChildView *pWnd ); + + /** + * Activates the MDI view (see activateView() ) and popups the taskBar popup menu (see taskBarPopup() ). + */ + virtual void taskbarButtonRightClicked( KMdiChildView *pWnd ); + + /** + * Turns the system buttons for maximize mode (SDI mode) off, and disconnects them + */ + void switchOffMaximizeModeForMenu( KMdiChildFrm* oldChild ); + + /** + * Reconnects the system buttons form maximize mode (SDI mode) with the new child frame + */ + void updateSysButtonConnections( KMdiChildFrm* oldChild, KMdiChildFrm* newChild ); + + /** + * Usually called when the user clicks an MDI view item in the "Window" menu. + */ + void windowMenuItemActivated( int id ); + + /** + * Usually called when the user clicks an MDI view item in the sub-popup menu "Docking" of the "Window" menu. + */ + void dockMenuItemActivated( int id ); + + /** + * Popups the "Window" menu. See also windowPopup() . + */ + void popupWindowMenu( QPoint p ); + + /** + * The timer for main widget moving has elapsed -> send drag end to all concerned views. + */ + void dragEndTimeOut(); + + /** + * internally used to handle click on view close button (TabPage mode, only) + */ + void closeViewButtonPressed(); + +signals: + /** + * Signals the last attached KMdiChildView has been closed + */ + void lastChildFrmClosed(); + + /** + * Signals the last KMdiChildView (that is under MDI control) has been closed + */ + void lastChildViewClosed(); + + /** + * Signals that the Toplevel mode has been left + */ + void leftTopLevelMode(); + + /** + * Signals that a child view has been detached (undocked to desktop) + */ + void childViewIsDetachedNow( QWidget* ); + + /** Signals we need to collapse the overlapped containers */ + void collapseOverlapContainers(); + + /** Signals the MDI mode has been changed */ + void mdiModeHasBeenChangedTo( KMdi::MdiMode ); + + void viewActivated( KMdiChildView* ); + void viewDeactivated( KMdiChildView* ); + +public slots: + void prevToolViewInDock(); + void nextToolViewInDock(); + +private slots: + void setActiveToolDock( KMdiDockContainer* ); + void removeFromActiveDockList( KMdiDockContainer* ); + void slotDocCurrentChanged( QWidget* ); + void verifyToplevelHeight(); +#define protected public +signals: +#undef protected + + void toggleTop(); + void toggleLeft(); + void toggleRight(); + void toggleBottom(); +}; + +#endif //_KMDIMAINFRM_H_ + +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; diff --git a/lib/compatibility/kmdi/qextmdi/kmdinulliterator.h b/lib/compatibility/kmdi/qextmdi/kmdinulliterator.h new file mode 100644 index 00000000..3c976caa --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmdinulliterator.h @@ -0,0 +1,49 @@ +//---------------------------------------------------------------------------- +// filename : kmdinulliterator.h +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 02/2000 by Massimo Morin +// changes : 02/2000 by Falk Brettschneider to create an +// - 06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// 2000-2003 maintained by the KDevelop project +// +// copyright : (C) 1999-2003 by Massimo Morin (mmorin@schedsys.com) +// and +// Falk Brettschneider +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program 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. +// +//---------------------------------------------------------------------------- + +#ifndef _KMDINULLITERATOR_H_ +#define _KMDINULLITERATOR_H_ + +#include "kmdiiterator.h" + +template <class Item> +class KMdiNullIterator : public KMdiIterator<Item> { +public: + KMdiNullIterator() {}; + virtual void first() {} + virtual void last() {} + virtual void next() {} + virtual void prev() {} + virtual bool isDone() const { return true; } + virtual Item currentItem() const { + /* should really never go inside here */ + return 0; + } +}; + +#endif // _KMDINULLITERATOR_H_ +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; + diff --git a/lib/compatibility/kmdi/qextmdi/kmditaskbar.cpp b/lib/compatibility/kmdi/qextmdi/kmditaskbar.cpp new file mode 100644 index 00000000..2b86c0c8 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmditaskbar.cpp @@ -0,0 +1,390 @@ +//---------------------------------------------------------------------------- +// filename : kmditaskbar.cpp +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 07/1999 by Szymon Stefanek as part of kvirc +// (an IRC application) +// changes : 09/1999 by Falk Brettschneider to create an +// - 06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// 2000-2003 maintained by the KDevelop project +// patches : 02/2000 by Massimo Morin (mmorin@schedsys.com) +// +// copyright : (C) 1999-2003 by Szymon Stefanek (stefanek@tin.it) +// and +// Falk Brettschneider +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program 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. +// +//---------------------------------------------------------------------------- + +#include "kmditaskbar.h" +#include "kmditaskbar.moc" + +#include "kmdimainfrm.h" +#include "kmdichildview.h" +#include "kmdidefines.h" + +#include <qtooltip.h> +#include <qlabel.h> +#include <qwidget.h> +#include <qstyle.h> + +#include <qnamespace.h> + +/* + @quickhelp: KMdiTaskBar + @widget: Taskbar + This window lists the currently open windows.<br> + Each button corresponds to a single MDI (child) window.<br> + The button is enabled (clickable) when the window is docked , and can be + pressed to bring it to the top of the other docked windows.<br> + The button text becomes red when new output is shown in the window and it is not the active one.<br> +*/ + +//#################################################################### +// +// KMdiTaskBarButton +// +//#################################################################### +KMdiTaskBarButton::KMdiTaskBarButton( KMdiTaskBar *pTaskBar, KMdiChildView *win_ptr ) + : QPushButton( pTaskBar ), + m_actualText( "" ) +{ + setToggleButton( true ); + m_pWindow = win_ptr; + QToolTip::add + ( this, win_ptr->caption() ); + setFocusPolicy( NoFocus ); +} + +KMdiTaskBarButton::~KMdiTaskBarButton() +{} + +void KMdiTaskBarButton::mousePressEvent( QMouseEvent* e ) +{ + switch ( e->button() ) + { + case QMouseEvent::LeftButton: + emit leftMouseButtonClicked( m_pWindow ); + break; + case QMouseEvent::RightButton: + emit rightMouseButtonClicked( m_pWindow ); + break; + default: + break; + } + emit clicked( m_pWindow ); +} + +/** slot version of setText */ +void KMdiTaskBarButton::setNewText( const QString& s ) +{ + setText( s ); + emit buttonTextChanged( 0 ); +} + +void KMdiTaskBarButton::setText( const QString& s ) +{ + m_actualText = s; + QButton::setText( s ); +} + +void KMdiTaskBarButton::fitText( const QString& origStr, int newWidth ) +{ + QButton::setText( m_actualText ); + + int actualWidth = sizeHint().width(); + int realLetterCount = origStr.length(); + int newLetterCount = ( newWidth * realLetterCount ) / actualWidth; + int w = newWidth + 1; + QString s = origStr; + while ( ( w > newWidth ) && ( newLetterCount >= 1 ) ) + { + if ( newLetterCount < realLetterCount ) + { + if ( newLetterCount > 3 ) + s = origStr.left( newLetterCount / 2 ) + "..." + origStr.right( newLetterCount / 2 ); + else + { + if ( newLetterCount > 1 ) + s = origStr.left( newLetterCount ) + ".."; + else + s = origStr.left( 1 ); + } + } + QFontMetrics fm = fontMetrics(); + w = fm.width( s ); + newLetterCount--; + } + + QButton::setText( s ); +} + +QString KMdiTaskBarButton::actualText() const +{ + return m_actualText; +} + +//#################################################################### +// +// KMdiTaskBar +// +//#################################################################### + +KMdiTaskBar::KMdiTaskBar( KMdiMainFrm *parent, QMainWindow::ToolBarDock dock ) + : KToolBar( parent, "KMdiTaskBar", /*honor_style*/ false, /*readConfig*/ true ) + , m_pCurrentFocusedWindow( 0 ) + , m_pStretchSpace( 0 ) + , m_layoutIsPending( false ) + , m_bSwitchedOn( false ) +{ + m_pFrm = parent; + m_pButtonList = new QPtrList<KMdiTaskBarButton>; + m_pButtonList->setAutoDelete( true ); + //QT30 setFontPropagation(QWidget::SameFont); + setMinimumWidth( 1 ); + setFocusPolicy( NoFocus ); + parent->moveToolBar( this, dock ); //XXX obsolete! +} + +KMdiTaskBar::~KMdiTaskBar() +{ + delete m_pButtonList; +} + +KMdiTaskBarButton * KMdiTaskBar::addWinButton( KMdiChildView *win_ptr ) +{ + if ( m_pStretchSpace ) + { + delete m_pStretchSpace; + m_pStretchSpace = 0L; + setStretchableWidget( 0L ); + } + + KMdiTaskBarButton *b = new KMdiTaskBarButton( this, win_ptr ); + QObject::connect( b, SIGNAL( clicked() ), win_ptr, SLOT( setFocus() ) ); + QObject::connect( b, SIGNAL( clicked( KMdiChildView* ) ), this, SLOT( setActiveButton( KMdiChildView* ) ) ); + QObject::connect( b, SIGNAL( leftMouseButtonClicked( KMdiChildView* ) ), m_pFrm, SLOT( activateView( KMdiChildView* ) ) ); + QObject::connect( b, SIGNAL( rightMouseButtonClicked( KMdiChildView* ) ), m_pFrm, SLOT( taskbarButtonRightClicked( KMdiChildView* ) ) ); + QObject::connect( b, SIGNAL( buttonTextChanged( int ) ), this, SLOT( layoutTaskBar( int ) ) ); + m_pButtonList->append( b ); + b->setToggleButton( true ); + b->setText( win_ptr->tabCaption() ); + + layoutTaskBar(); + + m_pStretchSpace = new QLabel( this, "empty" ); + m_pStretchSpace->setText( "" ); + setStretchableWidget( m_pStretchSpace ); + m_pStretchSpace->show(); + + if ( m_bSwitchedOn ) + { + b->show(); + show(); + } + return b; +} + +void KMdiTaskBar::removeWinButton( KMdiChildView *win_ptr, bool haveToLayoutTaskBar ) +{ + KMdiTaskBarButton * b = getButton( win_ptr ); + if ( b ) + { + m_pButtonList->removeRef( b ); + if ( haveToLayoutTaskBar ) + layoutTaskBar(); + } + if ( m_pButtonList->count() == 0 ) + { + if ( m_pStretchSpace != 0L ) + { + delete m_pStretchSpace; + m_pStretchSpace = 0L; + hide(); + } + } +} + +void KMdiTaskBar::switchOn( bool bOn ) +{ + m_bSwitchedOn = bOn; + if ( !bOn ) + { + hide(); + } + else + { + if ( m_pButtonList->count() > 0 ) + { + show(); + } + else + { + hide(); + } + } +} + +KMdiTaskBarButton * KMdiTaskBar::getButton( KMdiChildView *win_ptr ) +{ + for ( KMdiTaskBarButton * b = m_pButtonList->first();b;b = m_pButtonList->next() ) + { + if ( b->m_pWindow == win_ptr ) + return b; + } + return 0; +} + +KMdiTaskBarButton * KMdiTaskBar::getNextWindowButton( bool bRight, KMdiChildView *win_ptr ) +{ + if ( bRight ) + { + for ( KMdiTaskBarButton * b = m_pButtonList->first();b;b = m_pButtonList->next() ) + { + if ( b->m_pWindow == win_ptr ) + { + b = m_pButtonList->next(); + if ( !b ) + b = m_pButtonList->first(); + if ( win_ptr != b->m_pWindow ) + return b; + else + return 0; + } + } + } + else + { + for ( KMdiTaskBarButton * b = m_pButtonList->first();b;b = m_pButtonList->next() ) + { + if ( b->m_pWindow == win_ptr ) + { + b = m_pButtonList->prev(); + if ( !b ) + b = m_pButtonList->last(); + if ( win_ptr != b->m_pWindow ) + return b; + else + return 0; + } + } + } + return 0; +} + +void KMdiTaskBar::setActiveButton( KMdiChildView *win_ptr ) +{ + KMdiTaskBarButton * newPressedButton = 0L; + KMdiTaskBarButton* oldPressedButton = 0L; + for ( KMdiTaskBarButton * b = m_pButtonList->first();b;b = m_pButtonList->next() ) + { + if ( b->m_pWindow == win_ptr ) + newPressedButton = b; + if ( b->m_pWindow == m_pCurrentFocusedWindow ) + oldPressedButton = b; + } + + if ( newPressedButton != 0L && newPressedButton != oldPressedButton ) + { + if ( oldPressedButton != 0L ) + oldPressedButton->toggle(); // switch off + newPressedButton->toggle(); // switch on + m_pCurrentFocusedWindow = win_ptr; + } +} + +void KMdiTaskBar::layoutTaskBar( int taskBarWidth ) +{ + if ( m_layoutIsPending ) + return ; + m_layoutIsPending = true; + + if ( !taskBarWidth ) + // no width is given + taskBarWidth = width(); + + // calculate current width of all taskbar buttons + int allButtonsWidth = 0; + KMdiTaskBarButton *b = 0; + for ( b = m_pButtonList->first();b;b = m_pButtonList->next() ) + { + allButtonsWidth += b->width(); + } + + // calculate actual width of all taskbar buttons + int allButtonsWidthHint = 0; + for ( b = m_pButtonList->first();b;b = m_pButtonList->next() ) + { + QFontMetrics fm = b->fontMetrics(); + QString s = b->actualText(); + QSize sz = fm.size( ShowPrefix, s ); + int w = sz.width() + 6; + int h = sz.height() + sz.height() / 8 + 10; + w += h; + allButtonsWidthHint += w; + } + + // if there's enough space, use actual width + int buttonCount = m_pButtonList->count(); + int tbHandlePixel; + tbHandlePixel = style().pixelMetric( QStyle::PM_DockWindowHandleExtent, this ); + int buttonAreaWidth = taskBarWidth - tbHandlePixel - style().pixelMetric( QStyle::PM_DefaultFrameWidth, this ) - 5; + if ( ( ( allButtonsWidthHint ) <= buttonAreaWidth ) || ( width() < parentWidget() ->width() ) ) + { + for ( b = m_pButtonList->first();b;b = m_pButtonList->next() ) + { + b->setText( b->actualText() ); + if ( b->width() != b->sizeHint().width() ) + { + b->setFixedWidth( b->sizeHint().width() ); + b->show(); + } + } + } + else + { + // too many buttons for actual width + int newButtonWidth; + if ( buttonCount != 0 ) + newButtonWidth = buttonAreaWidth / buttonCount; + else + newButtonWidth = 0; + if ( orientation() == Qt::Vertical ) + newButtonWidth = 80; + if ( newButtonWidth > 0 ) + for ( b = m_pButtonList->first();b;b = m_pButtonList->next() ) + { + b->fitText( b->actualText(), newButtonWidth ); + if ( b->width() != newButtonWidth ) + { + b->setFixedWidth( newButtonWidth ); + b->show(); + } + } + } + m_layoutIsPending = false; +} + +void KMdiTaskBar::resizeEvent( QResizeEvent* rse ) +{ + if ( !m_layoutIsPending ) + { + if ( m_pButtonList->count() != 0 ) + { + layoutTaskBar( rse->size().width() ); + } + } + KToolBar::resizeEvent( rse ); +} + +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; diff --git a/lib/compatibility/kmdi/qextmdi/kmditaskbar.h b/lib/compatibility/kmdi/qextmdi/kmditaskbar.h new file mode 100644 index 00000000..f1aac814 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmditaskbar.h @@ -0,0 +1,219 @@ +//---------------------------------------------------------------------------- +// filename : kmditaskbar.h +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 07/1999 by Szymon Stefanek as part of kvirc +// (an IRC application) +// changes : 09/1999 by Falk Brettschneider to create an +// - 06/2000 stand-alone Qt extension set of +// classes and a Qt-based library +// 2000-2003 maintained by the KDevelop project +// +// copyright : (C) 1999-2003 by Falk Brettschneider +// and +// Szymon Stefanek (stefanek@tin.it) +// email : falkbr@kdevelop.org (Falk Brettschneider) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program 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. +// +//---------------------------------------------------------------------------- + +#ifndef _KMDITASKBAR_H_ +#define _KMDITASKBAR_H_ + +#include <ktoolbar.h> +#include <qptrlist.h> +#include <qpixmap.h> +#include <qlabel.h> +#include <qpushbutton.h> + +#include "kmdidefines.h" + +class KMdiMainFrm; +class KMdiChildView; +class KMdiTaskBar; + +class KMdiTaskBarButtonPrivate; + +/** + * @short Internal class. + * + * It's a special kind of QPushButton catching mouse clicks. + * And you have the ability to abbreviate the text that it fits in the button. + */ +class KMdiTaskBarButton : public QPushButton +{ + Q_OBJECT + // methods +public: + /** + * Constructor (sets to toggle button, adds a tooltip (caption) and sets to NoFocus + */ + KMdiTaskBarButton( KMdiTaskBar *pTaskBar, KMdiChildView *win_ptr ); + /** + * Destructor + */ + ~KMdiTaskBarButton(); + /** + * text() returns the possibly abbreviated text including the dots in it. But actualText() returns the full text. + */ + QString actualText() const; + /** + * Given the parameter newWidth this function possibly abbreviates the parameter string and sets a new button text. + */ + void fitText( const QString&, int newWidth ); + /** + * Sets the text and avoids any abbreviation. Memorizes that text in m_actualText, too. + */ + void setText( const QString& ); +signals: + /** + * Emitted when the button has been clicked. Internally connected to setFocus of the according MDI view. + */ + void clicked( KMdiChildView* ); + /** + * Internally connected with KMdiMainFrm::activateView + */ + void leftMouseButtonClicked( KMdiChildView* ); + /** + * Internally connected with KMdiMainFrm::taskbarButtonRightClicked + */ + void rightMouseButtonClicked( KMdiChildView* ); + /** + * Emitted when the button text has changed. Internally connected with KMdiTaskBar::layoutTaskBar + */ + void buttonTextChanged( int ); +public slots: + /** + * A slot version of setText + */ + void setNewText( const QString& ); +protected slots: + /** + * Reimplemented from its base class to catch right and left mouse button clicks + */ + void mousePressEvent( QMouseEvent* ); + + // attributes +public: + /** + * The according MDI view + */ + KMdiChildView *m_pWindow; +protected: + /** + * Internally we must remember the real text because the button text can be abbreviated. + */ + QString m_actualText; + +private: + KMdiTaskBarButtonPrivate *d; +}; + + +class KMdiTaskBarPrivate; +/** + * @short Internal class. + * + * It's a special kind of QToolBar that acts as taskbar for child views. + * KMdiTaskBarButtons can be added or removed dynamically.<br> + * The button sizes are adjusted dynamically, as well. + */ +class KMDI_EXPORT KMdiTaskBar : public KToolBar +{ + Q_OBJECT +public: + /** + * Constructor (NoFocus, minimum width = 1, an internal QPtrList of taskbar buttons (autodelete)) + */ + KMdiTaskBar( KMdiMainFrm *parent, QMainWindow::ToolBarDock dock ); + /** + * Destructor (deletes the taskbar button list) + */ + ~KMdiTaskBar(); + /** + *Add a new KMdiTaskBarButton . The width doesn't change. + * If there's not enough space, all taskbar buttons will be resized to a new smaller size. + * Probably button texts must be abbreviated now. + */ + KMdiTaskBarButton * addWinButton( KMdiChildView *win_ptr ); + /** + * Removes a KMdiTaskBarButton and deletes it. If the rest of the buttons are smaller + * than they usually are, all those buttons will be resized in a way that the new free size is used as well. + */ + void removeWinButton( KMdiChildView *win_ptr, bool haveToLayoutTaskBar = true ); + /** + * Returns the neighbor taskbar button of the taskbar button of the MDI view given by parameter + * bRight specifies the side, of course left is used if bRight is false. + */ + KMdiTaskBarButton * getNextWindowButton( bool bRight, KMdiChildView *win_ptr ); + /** + * Get the button belonging to the MDI view given as parameter. + */ + KMdiTaskBarButton * getButton( KMdiChildView *win_ptr ); + /** + * Switch it on or off. + */ + void switchOn( bool bOn ); + /** + * @return whether switched on or off. + */ + bool isSwitchedOn() const + { + return m_bSwitchedOn; + }; +protected: + /** + * Reimplemented from its base class to call layoutTaskBar, additionally. + */ + void resizeEvent( QResizeEvent* ); +protected slots: + /** + * Checks if all buttons fits into this. If not, it recalculates all button widths + * in a way that all buttons fits into the taskbar and have got equal width. + * The text of the buttons will be abbreviated when nessecary, all buttons get a + * fixed width and show() is called for each one. + * If one drags the taskbar to a vertical orientation, the button width is set to 80 pixel. + */ + void layoutTaskBar( int taskBarWidth = 0 ); +public slots: + /** + * Pushes the desired taskbar button down (switch on), the old one is released (switched off). + * Actually it's a radiobutton group behavior. + */ + void setActiveButton( KMdiChildView *win_ptr ); +protected: + /** + * A list of taskbar buttons. + * Note: Each button stands for one MDI view (toolviews doesn't have got a taskbar button). + */ + QPtrList<KMdiTaskBarButton>* m_pButtonList; + /** + * The belonging MDI mainframe (parent widget of this) + */ + KMdiMainFrm* m_pFrm; + /** + * The MDI view belonging to the currently pressed taskbar button + */ + KMdiChildView* m_pCurrentFocusedWindow; + /** + * A stretchable widget used as 'space' at the end of a half filled taskbar + */ + QLabel* m_pStretchSpace; + bool m_layoutIsPending; + bool m_bSwitchedOn; + +private: + KMdiTaskBarPrivate *d; +}; + +#endif //_KMDITASKBAR_H_ +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; + diff --git a/lib/compatibility/kmdi/qextmdi/kmditoolviewaccessor.cpp b/lib/compatibility/kmdi/qextmdi/kmditoolviewaccessor.cpp new file mode 100644 index 00000000..f9921e18 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmditoolviewaccessor.cpp @@ -0,0 +1,269 @@ +//---------------------------------------------------------------------------- +// filename : kmditoolviewaccessor.h +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 08/2003 by Joseph Wenninger (jowenn@kde.org) +// changes : --- +// patches : --- +// +// copyright : (C) 2003 by Joseph Wenninger (jowenn@kde.org) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program 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. +// +//---------------------------------------------------------------------------- + +#ifndef NO_KDE +# include <kdebug.h> +#endif +#include "kmditoolviewaccessor_p.h" +#include "kmdiguiclient.h" +#include "kmdimainfrm.h" + +#include "kmditoolviewaccessor.h" +#include "kmditoolviewaccessor_p.h" + +KMdiToolViewAccessor::KMdiToolViewAccessor( KMdiMainFrm *parent, QWidget *widgetToWrap, const QString& tabToolTip, const QString& tabCaption ) + : QObject( parent ) +{ + mdiMainFrm = parent; + d = new KMdiToolViewAccessorPrivate(); + if ( widgetToWrap->inherits( "KDockWidget" ) ) + { + d->widgetContainer = dynamic_cast<KDockWidget*>( widgetToWrap ); + d->widget = d->widgetContainer->getWidget(); + } + else + { + d->widget = widgetToWrap; + QString finalTabCaption; + if ( tabCaption == 0 ) + { + finalTabCaption = widgetToWrap->caption(); + if ( finalTabCaption.isEmpty() && !widgetToWrap->icon() ) + { + finalTabCaption = widgetToWrap->name(); + } + } + else + { + finalTabCaption = tabCaption; + } + d->widgetContainer = parent->createDockWidget( widgetToWrap->name(), + ( widgetToWrap->icon() ? ( *( widgetToWrap->icon() ) ) : QPixmap() ), + 0L, // parent + widgetToWrap->caption(), + finalTabCaption ); + d->widgetContainer->setWidget( widgetToWrap ); + if ( tabToolTip != 0 ) + { + d->widgetContainer->setToolTipString( tabToolTip ); + } + } + //mdiMainFrm->m_pToolViews->insert(d->widget,this); + if ( mdiMainFrm->m_mdiGUIClient ) + mdiMainFrm->m_mdiGUIClient->addToolView( this ); + else + kdDebug( 760 ) << "mdiMainFrm->m_mdiGUIClient == 0 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << endl; + + d->widget->installEventFilter( this ); +} + +KMdiToolViewAccessor::KMdiToolViewAccessor( KMdiMainFrm *parent ) +{ + mdiMainFrm = parent; + d = new KMdiToolViewAccessorPrivate(); +} + +KMdiToolViewAccessor::~KMdiToolViewAccessor() +{ + if ( mdiMainFrm->m_pToolViews ) + mdiMainFrm->m_pToolViews->remove + ( d->widget ); + delete d; + +} + +QWidget *KMdiToolViewAccessor::wrapperWidget() +{ + if ( !d->widgetContainer ) + { + d->widgetContainer = mdiMainFrm->createDockWidget( "KMdiToolViewAccessor::null", QPixmap() ); + connect( d->widgetContainer, SIGNAL( widgetSet( QWidget* ) ), this, SLOT( setWidgetToWrap( QWidget* ) ) ); + } + return d->widgetContainer; +} + +QWidget *KMdiToolViewAccessor::wrappedWidget() +{ + return d->widget; +} + + +void KMdiToolViewAccessor::setWidgetToWrap( QWidget *widgetToWrap, const QString& tabToolTip, const QString& tabCaption ) +{ + Q_ASSERT( !( d->widget ) ); + Q_ASSERT( !widgetToWrap->inherits( "KDockWidget" ) ); + disconnect( d->widgetContainer, SIGNAL( widgetSet( QWidget* ) ), this, SLOT( setWidgetToWrap( QWidget* ) ) ); + delete d->widget; + d->widget = widgetToWrap; + KDockWidget *tmp = d->widgetContainer; + + QString finalTabCaption; + if ( tabCaption == 0 ) + { + finalTabCaption = widgetToWrap->caption(); + if ( finalTabCaption.isEmpty() && !widgetToWrap->icon() ) + { + finalTabCaption = widgetToWrap->name(); + } + } + else + { + finalTabCaption = tabCaption; + } + + if ( !tmp ) + { + tmp = mdiMainFrm->createDockWidget( widgetToWrap->name(), + widgetToWrap->icon() ? ( *( widgetToWrap->icon() ) ) : QPixmap(), + 0L, // parent + widgetToWrap->caption(), + finalTabCaption ); + d->widgetContainer = tmp; + if ( tabToolTip != 0 ) + { + d->widgetContainer->setToolTipString( tabToolTip ); + } + } + else + { + tmp->setCaption( widgetToWrap->caption() ); + tmp->setTabPageLabel( finalTabCaption ); + tmp->setPixmap( widgetToWrap->icon() ? ( *( widgetToWrap->icon() ) ) : QPixmap() ); + tmp->setName( widgetToWrap->name() ); + if ( tabToolTip != 0 ) + { + d->widgetContainer->setToolTipString( tabToolTip ); + } + } + tmp->setWidget( widgetToWrap ); + mdiMainFrm->m_pToolViews->insert( widgetToWrap, this ); + if ( mdiMainFrm->m_mdiGUIClient ) + mdiMainFrm->m_mdiGUIClient->addToolView( this ); + else + kdDebug( 760 ) << "mdiMainFrm->m_mdiGUIClient == 0 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << endl; + + d->widget->installEventFilter( this ); +} + + +bool KMdiToolViewAccessor::eventFilter( QObject *, QEvent *e ) +{ + if ( e->type() == QEvent::IconChange ) + { + d->widgetContainer->setPixmap( d->widget->icon() ? ( *d->widget->icon() ) : QPixmap() ); + } + return false; +} + +void KMdiToolViewAccessor::placeAndShow( KDockWidget::DockPosition pos, QWidget* pTargetWnd , int percent ) +{ + place( pos, pTargetWnd, percent ); + show(); +} +void KMdiToolViewAccessor::place( KDockWidget::DockPosition pos, QWidget* pTargetWnd , int percent ) +{ + Q_ASSERT( d->widgetContainer ); + if ( !d->widgetContainer ) + return ; + if ( pos == KDockWidget::DockNone ) + { + d->widgetContainer->setEnableDocking( KDockWidget::DockNone ); + d->widgetContainer->reparent( mdiMainFrm, Qt::WType_TopLevel | Qt::WType_Dialog, QPoint( 0, 0 ), true ); //pToolView->isVisible()); + } + else + { // add (and dock) the toolview as DockWidget view + + KDockWidget* pCover = d->widgetContainer; + + KDockWidget* pTargetDock = 0L; + if ( pTargetWnd->inherits( "KDockWidget" ) || pTargetWnd->inherits( "KDockWidget_Compat::KDockWidget" ) ) + { + pTargetDock = ( KDockWidget* ) pTargetWnd; + } + + // Should we dock to ourself? + bool DockToOurself = false; + if ( mdiMainFrm->m_pDockbaseAreaOfDocumentViews ) + { + if ( pTargetWnd == mdiMainFrm->m_pDockbaseAreaOfDocumentViews->getWidget() ) + { + DockToOurself = true; + pTargetDock = mdiMainFrm->m_pDockbaseAreaOfDocumentViews; + } + else if ( pTargetWnd == mdiMainFrm->m_pDockbaseAreaOfDocumentViews ) + { + DockToOurself = true; + pTargetDock = mdiMainFrm->m_pDockbaseAreaOfDocumentViews; + } + } + // this is not inheriting QWidget*, its plain impossible that this condition is true + //if (pTargetWnd == this) DockToOurself = true; + if ( !DockToOurself ) + if ( pTargetWnd != 0L ) + { + pTargetDock = mdiMainFrm->dockManager->findWidgetParentDock( pTargetWnd ); + if ( !pTargetDock ) + { + if ( pTargetWnd->parentWidget() ) + { + pTargetDock = mdiMainFrm->dockManager->findWidgetParentDock( pTargetWnd->parentWidget() ); + } + } + } + if ( !pTargetDock || pTargetWnd == mdiMainFrm->getMainDockWidget() ) + { + if ( mdiMainFrm->m_managedDockPositionMode && ( mdiMainFrm->m_pMdi || mdiMainFrm->m_documentTabWidget ) ) + { + KDockWidget * dw1 = pTargetDock->findNearestDockWidget( pos ); + if ( dw1 ) + pCover->manualDock( dw1, KDockWidget::DockCenter, percent ); + else + pCover->manualDock ( pTargetDock, pos, 20 ); + return ; + } + } + pCover->manualDock( pTargetDock, pos, percent ); + //check pCover->show(); + } +} + +void KMdiToolViewAccessor::hide() +{ + Q_ASSERT( d->widgetContainer ); + if ( !d->widgetContainer ) + return ; + d->widgetContainer->undock(); +} + +void KMdiToolViewAccessor::show() +{ + Q_ASSERT( d->widgetContainer ); + if ( !d->widgetContainer ) + return ; + d->widgetContainer->makeDockVisible(); +} + + +#ifndef NO_INCLUDE_MOCFILES +#include "kmditoolviewaccessor.moc" +#endif +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; + diff --git a/lib/compatibility/kmdi/qextmdi/kmditoolviewaccessor.h b/lib/compatibility/kmdi/qextmdi/kmditoolviewaccessor.h new file mode 100644 index 00000000..d5bd49a7 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmditoolviewaccessor.h @@ -0,0 +1,86 @@ +//---------------------------------------------------------------------------- +// filename : kmditoolviewaccessor.h +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 08/2003 by Joseph Wenninger (jowenn@kde.org) +// changes : --- +// patches : --- +// +// copyright : (C) 2003 by Joseph Wenninger (jowenn@kde.org) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program 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. +// +//---------------------------------------------------------------------------- +#ifndef _KMDITOOLVIEWACCESSOR_H_ +#define _KMDITOOLVIEWACCESSOR_H_ + +#include <qwidget.h> +#include <qpixmap.h> +#include <qrect.h> +#include <qapplication.h> +#include <qdatetime.h> + +#include <kdockwidget.h> + +namespace KMDIPrivate +{ +class KMDIGUIClient; +} + + +class KMDI_EXPORT KMdiToolViewAccessor : public QObject +{ + Q_OBJECT + + + friend class KMdiMainFrm; + friend class KMDIPrivate::KMDIGUIClient; + +private: + /** + * Internally used by KMdiMainFrm to store a temporary information that the method + * activate() is unnecessary and that it can by escaped. + * This saves from unnecessary calls when activate is called directly. + */ + bool m_bInterruptActivation; + /** + * Internally used to prevent cycles between KMdiMainFrm::activateView() and KMdiChildView::activate(). + */ + bool m_bMainframesActivateViewIsPending; + /** + * + */ + bool m_bFocusInEventIsPending; + +private: + KMdiToolViewAccessor( class KMdiMainFrm *parent , QWidget *widgetToWrap, const QString& tabToolTip = 0, const QString& tabCaption = 0 ); + KMdiToolViewAccessor( class KMdiMainFrm *parent ); +public: + ~KMdiToolViewAccessor(); + QWidget *wrapperWidget(); + QWidget *wrappedWidget(); + void place( KDockWidget::DockPosition pos = KDockWidget::DockNone, QWidget* pTargetWnd = 0L, int percent = 50 ); + void placeAndShow( KDockWidget::DockPosition pos = KDockWidget::DockNone, QWidget* pTargetWnd = 0L, int percent = 50 ); + void show(); +public slots: + void setWidgetToWrap( QWidget* widgetToWrap, const QString& tabToolTip = 0, const QString& tabCaption = 0 ); + void hide(); +private: + class KMdiToolViewAccessorPrivate *d; + class KMdiMainFrm *mdiMainFrm; + +protected: + bool eventFilter( QObject *o, QEvent *e ); +}; + + +#endif //_KMDITOOLVIEWACCESSOR_H_ +// kate: space-indent off; tab-width 4; replace-tabs off; indent-mode csands; + diff --git a/lib/compatibility/kmdi/qextmdi/kmditoolviewaccessor_p.h b/lib/compatibility/kmdi/qextmdi/kmditoolviewaccessor_p.h new file mode 100644 index 00000000..913b8854 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmditoolviewaccessor_p.h @@ -0,0 +1,51 @@ +//---------------------------------------------------------------------------- +// filename : kmditoolviewaccessor_p.h +//---------------------------------------------------------------------------- +// Project : KDE MDI extension +// +// begin : 08/2003 by Joseph Wenninger (jowenn@kde.org) +// changes : --- +// patches : --- +// +// copyright : (C) 2003 by Joseph Wenninger (jowenn@kde.org) +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// +// This program 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. +// +//---------------------------------------------------------------------------- + + +#ifndef KMDI_TOOLVIEW_ACCESSOR_PRIVATE_H_ +#define KMDI_TOOLVIEW_ACCESSOR_PRIVATE_H_ + + +#include <qwidget.h> +#include <kdockwidget.h> +#include <qguardedptr.h> +#include <kaction.h> + +class KMDI_EXPORT KMdiToolViewAccessorPrivate { +public: + KMdiToolViewAccessorPrivate() { + widgetContainer=0; + widget=0; + } + ~KMdiToolViewAccessorPrivate() { + delete action; + if (!widgetContainer.isNull()) widgetContainer->undock(); + delete (KDockWidget*)widgetContainer; + } + QGuardedPtr<KDockWidget> widgetContainer; + QWidget* widget; + QGuardedPtr<KAction> action; +}; + + +#endif + + diff --git a/lib/compatibility/kmdi/qextmdi/kmultitabbar.cpp b/lib/compatibility/kmdi/qextmdi/kmultitabbar.cpp new file mode 100644 index 00000000..335f82db --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmultitabbar.cpp @@ -0,0 +1,988 @@ +/*************************************************************************** + kmultitabbar.cpp - description + ------------------- + begin : 2001 + copyright : (C) 2001,2002,2003 by Joseph Wenninger <jowenn@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 "kmultitabbar.h" +#include "kmultitabbar.moc" +#include "kmultitabbar_p.h" +#include "kmultitabbar_p.moc" +#include <qbutton.h> +#include <qpopupmenu.h> +#include <qlayout.h> +#include <qpainter.h> +#include <qtooltip.h> +#include <qfontmetrics.h> +#include <qstyle.h> + +#include <kiconloader.h> +#include <kdebug.h> +#include <qapplication.h> +#include <math.h> + +#define NEARBYINT(i) ((int(float(i) + 0.5))) + +class KMultiTabBarTabPrivate { +public: + QPixmap pix; +}; + + +KMultiTabBarInternal::KMultiTabBarInternal(QWidget *parent, KMultiTabBar::KMultiTabBarMode bm):QScrollView(parent) +{ + m_expandedTabSize=-1; + m_showActiveTabTexts=false; + m_tabs.setAutoDelete(true); + m_barMode=bm; + setHScrollBarMode(AlwaysOff); + setVScrollBarMode(AlwaysOff); + if (bm==KMultiTabBar::Vertical) + { + box=new QWidget(viewport()); + mainLayout=new QVBoxLayout(box); + mainLayout->setAutoAdd(true); + box->setFixedWidth(24); + setFixedWidth(24); + } + else + { + box=new QWidget(viewport()); + mainLayout=new QHBoxLayout(box); + mainLayout->setAutoAdd(true); + box->setFixedHeight(24); + setFixedHeight(24); + } + addChild(box); + setFrameStyle(NoFrame); + viewport()->setBackgroundMode(Qt::PaletteBackground); +/* box->setPaletteBackgroundColor(Qt::red); + setPaletteBackgroundColor(Qt::green);*/ +} + +void KMultiTabBarInternal::setStyle(enum KMultiTabBar::KMultiTabBarStyle style) +{ + m_style=style; + for (uint i=0;i<m_tabs.count();i++) + m_tabs.at(i)->setStyle(m_style); + + if ( (m_style==KMultiTabBar::KDEV3) || + (m_style==KMultiTabBar::KDEV3ICON ) ) { + delete mainLayout; + mainLayout=0; + resizeEvent(0); + } else if (mainLayout==0) { + if (m_barMode==KMultiTabBar::Vertical) + { + box=new QWidget(viewport()); + mainLayout=new QVBoxLayout(box); + box->setFixedWidth(24); + setFixedWidth(24); + } + else + { + box=new QWidget(viewport()); + mainLayout=new QHBoxLayout(box); + box->setFixedHeight(24); + setFixedHeight(24); + } + addChild(box); + for (uint i=0;i<m_tabs.count();i++) + mainLayout->add(m_tabs.at(i)); + mainLayout->setAutoAdd(true); + + } + viewport()->repaint(); +} + +void KMultiTabBarInternal::drawContents ( QPainter * paint, int clipx, int clipy, int clipw, int cliph ) +{ + QScrollView::drawContents (paint , clipx, clipy, clipw, cliph ); + + if (m_position==KMultiTabBar::Right) + { + + paint->setPen(colorGroup().shadow()); + paint->drawLine(0,0,0,viewport()->height()); + paint->setPen(colorGroup().background().dark(120)); + paint->drawLine(1,0,1,viewport()->height()); + + + } + else + if (m_position==KMultiTabBar::Left) + { + paint->setPen(colorGroup().light()); + paint->drawLine(23,0,23,viewport()->height()); + paint->drawLine(22,0,22,viewport()->height()); + + paint->setPen(colorGroup().shadow()); + paint->drawLine(0,0,0,viewport()->height()); + } + else + if (m_position==KMultiTabBar::Bottom) + { + paint->setPen(colorGroup().shadow()); + paint->drawLine(0,0,viewport()->width(),0); + paint->setPen(colorGroup().background().dark(120)); + paint->drawLine(0,1,viewport()->width(),1); + } + else + { + paint->setPen(colorGroup().light()); + paint->drawLine(0,23,viewport()->width(),23); + paint->drawLine(0,22,viewport()->width(),22); + +/* paint->setPen(colorGroup().shadow()); + paint->drawLine(0,0,0,viewport()->height());*/ + + } + + +} + +void KMultiTabBarInternal::contentsMousePressEvent(QMouseEvent *ev) +{ + ev->ignore(); +} + +void KMultiTabBarInternal::mousePressEvent(QMouseEvent *ev) +{ + ev->ignore(); +} + + +#define CALCDIFF(m_tabs,diff,i) if (m_lines>(int)lines) {\ + /*kdDebug()<<"i="<<i<<" tabCount="<<tabCount<<" space="<<space<<endl;*/ \ + uint ulen=0;\ + diff=0; \ + for (uint i2=i;i2<tabCount;i2++) {\ + uint l1=m_tabs.at(i2)->neededSize();\ + if ((ulen+l1)>space){\ + if (ulen==0) diff=0;\ + else diff=((float)(space-ulen))/(i2-i);\ + break;\ + }\ + ulen+=l1;\ + }\ + } else {diff=0; } + + +void KMultiTabBarInternal::resizeEvent(QResizeEvent *ev) { +/* kdDebug()<<"KMultiTabBarInternal::resizeEvent"<<endl; + kdDebug()<<"KMultiTabBarInternal::resizeEvent - box geometry"<<box->geometry()<<endl; + kdDebug()<<"KMultiTabBarInternal::resizeEvent - geometry"<<geometry()<<endl;*/ + if (ev) QScrollView::resizeEvent(ev); + + if ( (m_style==KMultiTabBar::KDEV3) || + (m_style==KMultiTabBar::KDEV3ICON) ){ + box->setGeometry(0,0,width(),height()); + int lines=1; + uint space; + float tmp=0; + if ((m_position==KMultiTabBar::Bottom) || (m_position==KMultiTabBar::Top)) + space=width(); + else + space=height(); + + int cnt=0; +//CALCULATE LINES + const uint tabCount=m_tabs.count(); + for (uint i=0;i<tabCount;i++) { + cnt++; + tmp+=m_tabs.at(i)->neededSize(); + if (tmp>space) { + if (cnt>1)i--; + else if (i==(tabCount-1)) break; + cnt=0; + tmp=0; + lines++; + } + } +//SET SIZE & PLACE + float diff=0; + cnt=0; + + if ((m_position==KMultiTabBar::Bottom) || (m_position==KMultiTabBar::Top)) { + + setFixedHeight(lines*24); + box->setFixedHeight(lines*24); + m_lines=height()/24-1; + lines=0; + CALCDIFF(m_tabs,diff,0) + tmp=-diff; + + //kdDebug()<<"m_lines recalculated="<<m_lines<<endl; + for (uint i=0;i<tabCount;i++) { + KMultiTabBarTab *tab=m_tabs.at(i); + cnt++; + tmp+=tab->neededSize()+diff; + if (tmp>space) { + //kdDebug()<<"about to start new line"<<endl; + if (cnt>1) { + CALCDIFF(m_tabs,diff,i) + i--; + } + else { + //kdDebug()<<"placing line on old line"<<endl; + kdDebug()<<"diff="<<diff<<endl; + tab->removeEventFilter(this); + tab->move(NEARBYINT(tmp-tab->neededSize()),lines*24); +// tab->setFixedWidth(tab->neededSize()+diff); + tab->setFixedWidth(NEARBYINT(tmp+diff)-tab->x());; + tab->installEventFilter(this); + CALCDIFF(m_tabs,diff,(i+1)) + + } + tmp=-diff; + cnt=0; + lines++; + //kdDebug()<<"starting new line:"<<lines<<endl; + + } else { + //kdDebug()<<"Placing line on line:"<<lines<<" pos: (x/y)=("<<tmp-m_tabs.at(i)->neededSize()<<"/"<<lines*24<<")"<<endl; + //kdDebug()<<"diff="<<diff<<endl; + tab->removeEventFilter(this); + tab->move(NEARBYINT(tmp-tab->neededSize()),lines*24); + tab->setFixedWidth(NEARBYINT(tmp+diff)-tab->x());; + + //tab->setFixedWidth(tab->neededSize()+diff); + tab->installEventFilter(this); + + } + } + } + else { + setFixedWidth(lines*24); + box->setFixedWidth(lines*24); + m_lines=lines=width()/24; + lines=0; + CALCDIFF(m_tabs,diff,0) + tmp=-diff; + + for (uint i=0;i<tabCount;i++) { + KMultiTabBarTab *tab=m_tabs.at(i); + cnt++; + tmp+=tab->neededSize()+diff; + if (tmp>space) { + if (cnt>1) { + CALCDIFF(m_tabs,diff,i); + tmp=-diff; + i--; + } + else { + tab->removeEventFilter(this); + tab->move(lines*24,NEARBYINT(tmp-tab->neededSize())); + tab->setFixedHeight(NEARBYINT(tmp+diff)-tab->y());; + tab->installEventFilter(this); + } + cnt=0; + tmp=-diff; + lines++; + } else { + tab->removeEventFilter(this); + tab->move(lines*24,NEARBYINT(tmp-tab->neededSize())); + tab->setFixedHeight(NEARBYINT(tmp+diff)-tab->y());; + tab->installEventFilter(this); + } + } + } + + + //kdDebug()<<"needed lines:"<<m_lines<<endl; + } else { + int size=0; /*move the calculation into another function and call it only on add tab and tab click events*/ + for (int i=0;i<(int)m_tabs.count();i++) + size+=(m_barMode==KMultiTabBar::Vertical?m_tabs.at(i)->height():m_tabs.at(i)->width()); + if ((m_position==KMultiTabBar::Bottom) || (m_position==KMultiTabBar::Top)) + box->setGeometry(0,0,size,height()); + else box->setGeometry(0,0,width(),size); + + } +} + + +void KMultiTabBarInternal::showActiveTabTexts(bool show) +{ + m_showActiveTabTexts=show; +} + + +KMultiTabBarTab* KMultiTabBarInternal::tab(int id) const +{ + for (QPtrListIterator<KMultiTabBarTab> it(m_tabs);it.current();++it){ + if (it.current()->id()==id) return it.current(); + } + return 0; +} + +bool KMultiTabBarInternal::eventFilter(QObject *, QEvent *e) { + if (e->type()==QEvent::Resize) resizeEvent(0); + return false; +} + +int KMultiTabBarInternal::appendTab(const QPixmap &pic ,int id,const QString& text) +{ + KMultiTabBarTab *tab; + m_tabs.append(tab= new KMultiTabBarTab(pic,text,id,box,m_position,m_style)); + tab->installEventFilter(this); + tab->showActiveTabText(m_showActiveTabTexts); + + if (m_style==KMultiTabBar::KONQSBC) + { + if (m_expandedTabSize<tab->neededSize()) { + m_expandedTabSize=tab->neededSize(); + for (uint i=0;i<m_tabs.count();i++) + m_tabs.at(i)->setSize(m_expandedTabSize); + + } else tab->setSize(m_expandedTabSize); + } else tab->updateState(); + tab->show(); + resizeEvent(0); + return 0; +} + +void KMultiTabBarInternal::removeTab(int id) +{ + for (uint pos=0;pos<m_tabs.count();pos++) + { + if (m_tabs.at(pos)->id()==id) + { + m_tabs.remove(pos); + resizeEvent(0); + break; + } + } +} + +void KMultiTabBarInternal::setPosition(enum KMultiTabBar::KMultiTabBarPosition pos) +{ + m_position=pos; + for (uint i=0;i<m_tabs.count();i++) + m_tabs.at(i)->setTabsPosition(m_position); + viewport()->repaint(); +} + + +KMultiTabBarButton::KMultiTabBarButton(const QPixmap& pic,const QString& text, QPopupMenu *popup, + int id,QWidget *parent,KMultiTabBar::KMultiTabBarPosition pos,KMultiTabBar::KMultiTabBarStyle style) + :QPushButton(QIconSet(),text,parent),m_style(style) +{ + setIconSet(pic); + setText(text); + m_position=pos; + if (popup) setPopup(popup); + setFlat(true); + setFixedHeight(24); + setFixedWidth(24); + m_id=id; + QToolTip::add(this,text); + connect(this,SIGNAL(clicked()),this,SLOT(slotClicked())); +} + +KMultiTabBarButton::KMultiTabBarButton(const QString& text, QPopupMenu *popup, + int id,QWidget *parent,KMultiTabBar::KMultiTabBarPosition pos,KMultiTabBar::KMultiTabBarStyle style) + :QPushButton(QIconSet(),text,parent),m_style(style) +{ + setText(text); + m_position=pos; + if (popup) setPopup(popup); + setFlat(true); + setFixedHeight(24); + setFixedWidth(24); + m_id=id; + QToolTip::add(this,text); + connect(this,SIGNAL(clicked()),this,SLOT(slotClicked())); +} + +KMultiTabBarButton::~KMultiTabBarButton() { +} + +int KMultiTabBarButton::id() const{ + return m_id; +} + +void KMultiTabBarButton::setText(const QString& text) +{ + QPushButton::setText(text); + m_text=text; + QToolTip::add(this,text); +} + +void KMultiTabBarButton::slotClicked() +{ + emit clicked(m_id); +} + +void KMultiTabBarButton::setPosition(KMultiTabBar::KMultiTabBarPosition pos) +{ + m_position=pos; + repaint(); +} + +void KMultiTabBarButton::setStyle(KMultiTabBar::KMultiTabBarStyle style) +{ + m_style=style; + repaint(); +} + +void KMultiTabBarButton::hideEvent( QHideEvent* he) { + QPushButton::hideEvent(he); + KMultiTabBar *tb=dynamic_cast<KMultiTabBar*>(parentWidget()); + if (tb) tb->updateSeparator(); +} + +void KMultiTabBarButton::showEvent( QShowEvent* he) { + QPushButton::showEvent(he); + KMultiTabBar *tb=dynamic_cast<KMultiTabBar*>(parentWidget()); + if (tb) tb->updateSeparator(); +} + + +QSize KMultiTabBarButton::sizeHint() const +{ + constPolish(); + + int w = 0, h = 0; + + // calculate contents size... +#ifndef QT_NO_ICONSET + if ( iconSet() && !iconSet()->isNull() ) { + int iw = iconSet()->pixmap( QIconSet::Small, QIconSet::Normal ).width() + 4; + int ih = iconSet()->pixmap( QIconSet::Small, QIconSet::Normal ).height(); + w += iw; + h = QMAX( h, ih ); + } +#endif + if ( isMenuButton() ) + w += style().pixelMetric(QStyle::PM_MenuButtonIndicator, this); + + if ( pixmap() ) { + QPixmap *pm = (QPixmap *)pixmap(); + w += pm->width(); + h += pm->height(); + } else { + QString s( text() ); + bool empty = s.isEmpty(); + if ( empty ) + s = QString::fromLatin1("XXXX"); + QFontMetrics fm = fontMetrics(); + QSize sz = fm.size( ShowPrefix, s ); + if(!empty || !w) + w += sz.width(); + if(!empty || !h) + h = QMAX(h, sz.height()); + } + + return (style().sizeFromContents(QStyle::CT_ToolButton, this, QSize(w, h)). + expandedTo(QApplication::globalStrut())); +} + + +KMultiTabBarTab::KMultiTabBarTab(const QPixmap& pic, const QString& text, + int id,QWidget *parent,KMultiTabBar::KMultiTabBarPosition pos, + KMultiTabBar::KMultiTabBarStyle style) + :KMultiTabBarButton(text,0,id,parent,pos,style), + m_showActiveTabText(false) +{ + d=new KMultiTabBarTabPrivate(); + setIcon(pic); + m_expandedSize=24; + setToggleButton(true); +} + +KMultiTabBarTab::~KMultiTabBarTab() { + delete d; +} + + +void KMultiTabBarTab::setTabsPosition(KMultiTabBar::KMultiTabBarPosition pos) +{ + if ((pos!=m_position) && ((pos==KMultiTabBar::Left) || (pos==KMultiTabBar::Right))) { + if (!d->pix.isNull()) { + QWMatrix temp;// (1.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F); + temp.rotate(180); + d->pix=d->pix.xForm(temp); + setIconSet(d->pix); + } + } + + setPosition(pos); +// repaint(); +} + +void KMultiTabBarTab::setIcon(const QString& icon) +{ + QPixmap pic=SmallIcon(icon); + setIcon(pic); +} + +void KMultiTabBarTab::setIcon(const QPixmap& icon) +{ + + if (m_style!=KMultiTabBar::KDEV3) { + if ((m_position==KMultiTabBar::Left) || (m_position==KMultiTabBar::Right)) { + QWMatrix rotateMatrix; + if (m_position==KMultiTabBar::Left) + rotateMatrix.rotate(90); + else + rotateMatrix.rotate(-90); + QPixmap pic=icon.xForm(rotateMatrix); //TODO FIX THIS, THIS SHOWS WINDOW + d->pix=pic; + setIconSet(pic); + } else setIconSet(icon); + } +} + +void KMultiTabBarTab::slotClicked() +{ + updateState(); + KMultiTabBarButton::slotClicked(); +} + +void KMultiTabBarTab::setState(bool b) +{ + setOn(b); + updateState(); +} + +void KMultiTabBarTab::updateState() +{ + + if (m_style!=KMultiTabBar::KONQSBC) { + if ((m_style==KMultiTabBar::KDEV3) || (m_style==KMultiTabBar::KDEV3ICON) || (isOn())) { + QPushButton::setText(m_text); + } else { + kdDebug()<<"KMultiTabBarTab::updateState(): setting text to an empty QString***************"<<endl; + QPushButton::setText(QString::null); + } + + if ((m_position==KMultiTabBar::Right || m_position==KMultiTabBar::Left)) { + setFixedWidth(24); + if ((m_style==KMultiTabBar::KDEV3) || (m_style==KMultiTabBar::KDEV3ICON) || (isOn())) { + setFixedHeight(KMultiTabBarButton::sizeHint().width()); + } else setFixedHeight(36); + } else { + setFixedHeight(24); + if ((m_style==KMultiTabBar::KDEV3) || (m_style==KMultiTabBar::KDEV3ICON) || (isOn())) { + setFixedWidth(KMultiTabBarButton::sizeHint().width()); + } else setFixedWidth(36); + } + } else { + if ((!isOn()) || (!m_showActiveTabText)) + { + setFixedWidth(24); + setFixedHeight(24); + return; + } + if ((m_position==KMultiTabBar::Right || m_position==KMultiTabBar::Left)) + setFixedHeight(m_expandedSize); + else + setFixedWidth(m_expandedSize); + } + QApplication::sendPostedEvents(0,QEvent::Paint | QEvent::Move | QEvent::Resize | QEvent::LayoutHint); + QApplication::flush(); +} + +int KMultiTabBarTab::neededSize() +{ + return (((m_style!=KMultiTabBar::KDEV3)?24:0)+QFontMetrics(QFont()).width(m_text)+6); +} + +void KMultiTabBarTab::setSize(int size) +{ + m_expandedSize=size; + updateState(); +} + +void KMultiTabBarTab::showActiveTabText(bool show) +{ + m_showActiveTabText=show; +} + +void KMultiTabBarTab::drawButtonLabel(QPainter *p) { + drawButton(p); +} +void KMultiTabBarTab::drawButton(QPainter *paint) +{ + if (m_style!=KMultiTabBar::KONQSBC) drawButtonStyled(paint); + else drawButtonClassic(paint); +} + +void KMultiTabBarTab::drawButtonStyled(QPainter *paint) { + + QSize sh; + const int width = 36; // rotated + const int height = 24; + if ((m_style==KMultiTabBar::KDEV3) || (m_style==KMultiTabBar::KDEV3ICON) || (isOn())) { + if ((m_position==KMultiTabBar::Left) || (m_position==KMultiTabBar::Right)) + sh=QSize(this->height(),this->width());//KMultiTabBarButton::sizeHint(); + else sh=QSize(this->width(),this->height()); + } + else + sh=QSize(width,height); + + QPixmap pixmap( sh.width(),height); ///,sh.height()); + pixmap.fill(eraseColor()); + QPainter painter(&pixmap); + + + QStyle::SFlags st=QStyle::Style_Default; + + st|=QStyle::Style_Enabled; + + if (isOn()) st|=QStyle::Style_On; + + style().drawControl(QStyle::CE_PushButton,&painter,this, QRect(0,0,pixmap.width(),pixmap.height()), colorGroup(),st); + style().drawControl(QStyle::CE_PushButtonLabel,&painter,this, QRect(0,0,pixmap.width(),pixmap.height()), colorGroup(),st); + + switch (m_position) { + case KMultiTabBar::Left: + paint->rotate(-90); + paint->drawPixmap(1-pixmap.width(),0,pixmap); + break; + case KMultiTabBar::Right: + paint->rotate(90); + paint->drawPixmap(0,1-pixmap.height(),pixmap); + break; + + default: + paint->drawPixmap(0,0,pixmap); + break; + } +// style().drawControl(QStyle::CE_PushButtonLabel,painter,this, QRect(0,0,pixmap.width(),pixmap.height()), +// colorGroup(),QStyle::Style_Enabled); + + +} + +void KMultiTabBarTab::drawButtonClassic(QPainter *paint) +{ + QPixmap pixmap; + if ( iconSet()) + pixmap = iconSet()->pixmap( QIconSet::Small, QIconSet::Normal ); + paint->fillRect(0, 0, 24, 24, colorGroup().background()); + + if (!isOn()) + { + + if (m_position==KMultiTabBar::Right) + { + paint->fillRect(0,0,21,21,QBrush(colorGroup().background())); + + paint->setPen(colorGroup().background().dark(150)); + paint->drawLine(0,22,23,22); + + paint->drawPixmap(12-pixmap.width()/2,12-pixmap.height()/2,pixmap); + + paint->setPen(colorGroup().shadow()); + paint->drawLine(0,0,0,23); + paint->setPen(colorGroup().background().dark(120)); + paint->drawLine(1,0,1,23); + + } + else + if ((m_position==KMultiTabBar::Bottom) || (m_position==KMultiTabBar::Top)) + { + paint->fillRect(0,1,23,22,QBrush(colorGroup().background())); + + paint->drawPixmap(12-pixmap.width()/2,12-pixmap.height()/2,pixmap); + + paint->setPen(colorGroup().background().dark(120)); + paint->drawLine(23,0,23,23); + + + paint->setPen(colorGroup().light()); + paint->drawLine(0,22,23,22); + paint->drawLine(0,23,23,23); + paint->setPen(colorGroup().shadow()); + paint->drawLine(0,0,23,0); + paint->setPen(colorGroup().background().dark(120)); + paint->drawLine(0,1,23,1); + + } + else + { + paint->setPen(colorGroup().background().dark(120)); + paint->drawLine(0,23,23,23); + paint->fillRect(0,0,23,21,QBrush(colorGroup().background())); + paint->drawPixmap(12-pixmap.width()/2,12-pixmap.height()/2,pixmap); + + paint->setPen(colorGroup().light()); + paint->drawLine(23,0,23,23); + paint->drawLine(22,0,22,23); + + paint->setPen(colorGroup().shadow()); + paint->drawLine(0,0,0,23); + + } + + + } + else + { + if (m_position==KMultiTabBar::Right) + { + paint->setPen(colorGroup().shadow()); + paint->drawLine(0,height()-1,23,height()-1); + paint->drawLine(0,height()-2,23,height()-2); + paint->drawLine(23,0,23,height()-1); + paint->drawLine(22,0,22,height()-1); + paint->fillRect(0,0,21,height()-3,QBrush(colorGroup().light())); + paint->drawPixmap(10-pixmap.width()/2,10-pixmap.height()/2,pixmap); + + if (m_showActiveTabText) + { + if (height()<25+4) return; + + QPixmap tpixmap(height()-25-3, width()-2); + QPainter painter(&tpixmap); + + painter.fillRect(0,0,tpixmap.width(),tpixmap.height(),QBrush(colorGroup().light())); + + painter.setPen(colorGroup().text()); + painter.drawText(0,+width()/2+QFontMetrics(QFont()).height()/2,m_text); + + paint->rotate(90); + kdDebug()<<"tpixmap.width:"<<tpixmap.width()<<endl; + paint->drawPixmap(25,-tpixmap.height()+1,tpixmap); + } + + } + else + if (m_position==KMultiTabBar::Top) + { + paint->fillRect(0,0,width()-1,23,QBrush(colorGroup().light())); + paint->drawPixmap(10-pixmap.width()/2,10-pixmap.height()/2,pixmap); + if (m_showActiveTabText) + { + paint->setPen(colorGroup().text()); + paint->drawText(25,height()/2+QFontMetrics(QFont()).height()/2,m_text); + } + } + else + if (m_position==KMultiTabBar::Bottom) + { + paint->setPen(colorGroup().shadow()); + paint->drawLine(0,23,width()-1,23); + paint->drawLine(0,22,width()-1,22); + paint->fillRect(0,0,width()-1,21,QBrush(colorGroup().light())); + paint->drawPixmap(10-pixmap.width()/2,10-pixmap.height()/2,pixmap); + if (m_showActiveTabText) + { + paint->setPen(colorGroup().text()); + paint->drawText(25,height()/2+QFontMetrics(QFont()).height()/2,m_text); + } + + } + else + { + + + paint->setPen(colorGroup().shadow()); + paint->drawLine(0,height()-1,23,height()-1); + paint->drawLine(0,height()-2,23,height()-2); + paint->fillRect(0,0,23,height()-3,QBrush(colorGroup().light())); + paint->drawPixmap(10-pixmap.width()/2,10-pixmap.height()/2,pixmap); + if (m_showActiveTabText) + { + + if (height()<25+4) return; + + QPixmap tpixmap(height()-25-3, width()-2); + QPainter painter(&tpixmap); + + painter.fillRect(0,0,tpixmap.width(),tpixmap.height(),QBrush(colorGroup().light())); + + painter.setPen(colorGroup().text()); + painter.drawText(tpixmap.width()-QFontMetrics(QFont()).width(m_text),+width()/2+QFontMetrics(QFont()).height()/2,m_text); + + paint->rotate(-90); + kdDebug()<<"tpixmap.width:"<<tpixmap.width()<<endl; + + paint->drawPixmap(-24-tpixmap.width(),2,tpixmap); + + } + + } + + } +} + + + + + + + +KMultiTabBar::KMultiTabBar(KMultiTabBarMode bm, QWidget *parent,const char *name):QWidget(parent,name) +{ + m_buttons.setAutoDelete(false); + if (bm==Vertical) + { + m_l=new QVBoxLayout(this); + setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding, true); +// setFixedWidth(24); + } + else + { + m_l=new QHBoxLayout(this); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed, true); +// setFixedHeight(24); + } + m_l->setMargin(0); + m_l->setAutoAdd(false); + + m_internal=new KMultiTabBarInternal(this,bm); + setPosition((bm==KMultiTabBar::Vertical)?KMultiTabBar::Right:KMultiTabBar::Bottom); + setStyle(VSNET); + // setStyle(KDEV3); + //setStyle(KONQSBC); + m_l->insertWidget(0,m_internal); + m_l->insertWidget(0,m_btnTabSep=new QFrame(this)); + m_btnTabSep->setFixedHeight(4); + m_btnTabSep->setFrameStyle(QFrame::Panel | QFrame::Sunken); + m_btnTabSep->setLineWidth(2); + m_btnTabSep->hide(); + + updateGeometry(); +} + +KMultiTabBar::~KMultiTabBar() { +} + +/*int KMultiTabBar::insertButton(QPixmap pic,int id ,const QString&) +{ + (new KToolbarButton(pic,id,m_internal))->show(); + return 0; +}*/ + +int KMultiTabBar::appendButton(const QPixmap &pic ,int id,QPopupMenu *popup,const QString&) +{ + KMultiTabBarButton *btn; + m_buttons.append(btn= new KMultiTabBarButton(pic,QString::null, + popup,id,this,m_position,m_internal->m_style)); + m_l->insertWidget(0,btn); + btn->show(); + m_btnTabSep->show(); + return 0; +} + +void KMultiTabBar::updateSeparator() { + bool hideSep=true; + for (QPtrListIterator<KMultiTabBarButton> it(m_buttons);it.current();++it){ + if (it.current()->isVisibleTo(this)) { + hideSep=false; + break; + } + } + if (hideSep) m_btnTabSep->hide(); + else m_btnTabSep->show(); + +} + +int KMultiTabBar::appendTab(const QPixmap &pic ,int id ,const QString& text) +{ + m_internal->appendTab(pic,id,text); + return 0; +} + +KMultiTabBarButton* KMultiTabBar::button(int id) const +{ + for (QPtrListIterator<KMultiTabBarButton> it(m_buttons);it.current();++it){ + if (it.current()->id()==id) return it.current(); + } + return 0; +} + +KMultiTabBarTab* KMultiTabBar::tab(int id) const +{ + return m_internal->tab(id); +} + + + +void KMultiTabBar::removeButton(int id) +{ + for (uint pos=0;pos<m_buttons.count();pos++) + { + if (m_buttons.at(pos)->id()==id) + { + m_buttons.take(pos)->deleteLater(); + break; + } + } + if (m_buttons.count()==0) m_btnTabSep->hide(); +} + +void KMultiTabBar::removeTab(int id) +{ + m_internal->removeTab(id); +} + +void KMultiTabBar::setTab(int id,bool state) +{ + KMultiTabBarTab *ttab=tab(id); + if (ttab) + { + ttab->setState(state); + } +} + +bool KMultiTabBar::isTabRaised(int id) const +{ + KMultiTabBarTab *ttab=tab(id); + if (ttab) + { + return ttab->isOn(); + } + + return false; +} + + +void KMultiTabBar::showActiveTabTexts(bool show) +{ + m_internal->showActiveTabTexts(show); +} + +void KMultiTabBar::setStyle(KMultiTabBarStyle style) +{ + m_internal->setStyle(style); +} + +void KMultiTabBar::setPosition(KMultiTabBarPosition pos) +{ + m_position=pos; + m_internal->setPosition(pos); + for (uint i=0;i<m_buttons.count();i++) + m_buttons.at(i)->setPosition(pos); +} +void KMultiTabBar::fontChange(const QFont& /* oldFont */) +{ + for (uint i=0;i<tabs()->count();i++) + tabs()->at(i)->resize(); + repaint(); +} + +QPtrList<KMultiTabBarTab>* KMultiTabBar::tabs() {return m_internal->tabs();} +QPtrList<KMultiTabBarButton>* KMultiTabBar::buttons() {return &m_buttons;} + diff --git a/lib/compatibility/kmdi/qextmdi/kmultitabbar.h b/lib/compatibility/kmdi/qextmdi/kmultitabbar.h new file mode 100644 index 00000000..0d1a6841 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmultitabbar.h @@ -0,0 +1,246 @@ +/*************************************************************************** + kmultitabbar.h - description + ------------------- + begin : 2001 + copyright : (C) 2001,2002,2003 by Joseph Wenninger <jowenn@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. + ***************************************************************************/ + +#ifndef _KMultitabbar_h_ +#define _KMultitabbar_h_ + +#include <qscrollview.h> +#include <qvbox.h> +#include <qhbox.h> +#include <qlayout.h> +#include <qstring.h> +#include <qptrlist.h> +#include <qpushbutton.h> + +#include <kdelibs_export.h> + +class QPixmap; +class QPainter; +class QFrame; + +class KMultiTabBarPrivate; +class KMultiTabBarTabPrivate; +class KMultiTabBarButtonPrivate; +class KMultiTabBarInternal; + +/** + * A Widget for horizontal and vertical tabs. + * It is possible to add normal buttons to the top/left + * The handling if only one tab at a time or multiple tabs + * should be raisable is left to the "user". + *@author Joseph Wenninger + */ +class KUTILS_EXPORT KMultiTabBar: public QWidget +{ + Q_OBJECT +public: + enum KMultiTabBarMode{Horizontal, Vertical}; + enum KMultiTabBarPosition{Left, Right, Top, Bottom}; + + /** + * VSNET == Visual Studio .Net like (only show the text of active tabs + * KDEV3 == Kdevelop 3 like (always show the text) + * KONQSBC == konqy's classic sidebar style (unthemed), this one is disabled + * at the moment, but will be renabled soon too + */ + enum KMultiTabBarStyle{VSNET=0, KDEV3=1, KONQSBC=2, KDEV3ICON=3,STYLELAST=0xffff}; + + KMultiTabBar(KMultiTabBarMode bm,QWidget *parent=0,const char *name=0); + virtual ~KMultiTabBar(); + + /** + * append a new button to the button area. The button can later on be accessed with button(ID) + * eg for connecting signals to it + * @param pic a pixmap for the button + * @param id an arbitraty ID value. It will be emitted in the clicked signal for identifying the button + * if more than one button is connected to a signals. + * @param popup A popup menu which should be displayed if the button is clicked + * @param not_used_yet will be used for a popup text in the future + */ + int appendButton(const QPixmap &pic,int id=-1,QPopupMenu* popup=0,const QString& not_used_yet=QString::null); + /** + * remove a button with the given ID + */ + void removeButton(int id); + /** + * append a new tab to the tab area. It can be accessed lateron with tabb(id); + * @param pic a bitmap for the tab + * @param id an arbitrary ID which can be used later on to identify the tab + * @param text if a mode with text is used it will be the tab text, otherwise a mouse over hint + */ + int appendTab(const QPixmap &pic,int id=-1,const QString& text=QString::null); + /** + * remove a tab with a given ID + */ + void removeTab(int id); + /** + * set a tab to "raised" + * @param id The ID of the tab to manipulate + * @param state true == activated/raised, false == not active + */ + void setTab(int id ,bool state); + /** + * return the state of a tab, identified by it's ID + */ + bool isTabRaised(int id) const; + /** + * get a pointer to a button within the button area identified by its ID + */ + class KMultiTabBarButton *button(int id) const; + + /** + * get a pointer to a tab within the tab area, identiifed by its ID + */ + class KMultiTabBarTab *tab(int id) const; + /** + * set the real position of the widget. + * @param pos if the mode is horizontal, only use top, bottom, if it is vertical use left or right + */ + void setPosition(KMultiTabBarPosition pos); + /** + * set the display style of the tabs + */ + void setStyle(KMultiTabBarStyle style); + /** + * be carefull, don't delete tabs yourself and don't delete the list itself + */ + QPtrList<KMultiTabBarTab>* tabs(); + /** + * be carefull, don't delete buttons yourself and don't delete the list itself + */ + QPtrList<KMultiTabBarButton>* buttons(); + + /** + * might vanish, not sure yet + */ + void showActiveTabTexts(bool show=true); +protected: + friend class KMultiTabBarButton; + virtual void fontChange( const QFont& ); + void updateSeparator(); +private: + class KMultiTabBarInternal *m_internal; + QBoxLayout *m_l; + QFrame *m_btnTabSep; + QPtrList<KMultiTabBarButton> m_buttons; + KMultiTabBarPosition m_position; + KMultiTabBarPrivate *d; +}; + +/** + * This class should never be created except with the appendButton call of KMultiTabBar + */ +class KUTILS_EXPORT KMultiTabBarButton: public QPushButton +{ + Q_OBJECT +public: + KMultiTabBarButton(const QPixmap& pic,const QString&, QPopupMenu *popup, + int id,QWidget *parent, KMultiTabBar::KMultiTabBarPosition pos, KMultiTabBar::KMultiTabBarStyle style); + KMultiTabBarButton(const QString&, QPopupMenu *popup, + int id,QWidget *parent, KMultiTabBar::KMultiTabBarPosition pos, KMultiTabBar::KMultiTabBarStyle style); + virtual ~KMultiTabBarButton(); + int id() const; + +public slots: + /** + * this is used internaly, but can be used by the user, if (s)he wants to + * It the according call of KMultiTabBar is invoked though this modifications will be overwritten + */ + void setPosition(KMultiTabBar::KMultiTabBarPosition); + /** + * this is used internaly, but can be used by the user, if (s)he wants to + * It the according call of KMultiTabBar is invoked though this modifications will be overwritten + */ + void setStyle(KMultiTabBar::KMultiTabBarStyle); + + /** + * modify the text of the button + */ + void setText(const QString &); + + QSize sizeHint() const; + +protected: + KMultiTabBar::KMultiTabBarPosition m_position; + KMultiTabBar::KMultiTabBarStyle m_style; + QString m_text; + virtual void hideEvent( class QHideEvent*); + virtual void showEvent( class QShowEvent*); +private: + int m_id; + KMultiTabBarButtonPrivate *d; +signals: + /** + * this is emitted if the button is clicked + * @param id the ID identifying the button + */ + void clicked(int id); +protected slots: + virtual void slotClicked(); +}; + +/** + * This class should never be created except with the appendTab call of KMultiTabBar + */ +class KUTILS_EXPORT KMultiTabBarTab: public KMultiTabBarButton +{ + Q_OBJECT +public: + KMultiTabBarTab(const QPixmap& pic,const QString&,int id,QWidget *parent, + KMultiTabBar::KMultiTabBarPosition pos,KMultiTabBar::KMultiTabBarStyle style); + virtual ~KMultiTabBarTab(); + /** + * set the active state of the tab + * @param state true==active false==not active + */ + void setState(bool state); + /** + * choose if the text should always be displayed + * this is only used in classic mode if at all + */ + void showActiveTabText(bool show); + void resize(){ setSize( neededSize() ); } +private: + bool m_showActiveTabText; + int m_expandedSize; + KMultiTabBarTabPrivate *d; +protected: + friend class KMultiTabBarInternal; + void setSize(int); + int neededSize(); + void updateState(); + virtual void drawButton(QPainter *); + virtual void drawButtonLabel(QPainter *); + void drawButtonStyled(QPainter *); + void drawButtonClassic(QPainter *); +protected slots: + virtual void slotClicked(); + void setTabsPosition(KMultiTabBar::KMultiTabBarPosition); + +public slots: + virtual void setIcon(const QString&); + virtual void setIcon(const QPixmap&); +}; + +#endif diff --git a/lib/compatibility/kmdi/qextmdi/kmultitabbar_p.h b/lib/compatibility/kmdi/qextmdi/kmultitabbar_p.h new file mode 100644 index 00000000..f47cc538 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/kmultitabbar_p.h @@ -0,0 +1,67 @@ +/*************************************************************************** + kmultitabbar_p.h - description + ------------------- + begin : 2003 + copyright : (C) 2003 by Joseph Wenninger <jowenn@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. + ***************************************************************************/ + +#ifndef K_MULTI_TAB_BAR_P_H +#define K_MULTI_TAB_BAR_P_H +#include <qscrollview.h> +#include <kmultitabbar.h> + +class KMultiTabBarInternal: public QScrollView +{ + Q_OBJECT +public: + KMultiTabBarInternal(QWidget *parent,KMultiTabBar::KMultiTabBarMode bm); + int appendTab(const QPixmap &,int=-1,const QString& =QString::null); + KMultiTabBarTab *tab(int) const; + void removeTab(int); + void setPosition(enum KMultiTabBar::KMultiTabBarPosition pos); + void setStyle(enum KMultiTabBar::KMultiTabBarStyle style); + void showActiveTabTexts(bool show); + QPtrList<KMultiTabBarTab>* tabs(){return &m_tabs;} +private: + friend class KMultiTabBar; + QWidget *box; + QBoxLayout *mainLayout; + QPtrList<KMultiTabBarTab> m_tabs; + enum KMultiTabBar::KMultiTabBarPosition m_position; + bool m_showActiveTabTexts; + enum KMultiTabBar::KMultiTabBarStyle m_style; + int m_expandedTabSize; + int m_lines; + KMultiTabBar::KMultiTabBarMode m_barMode; +protected: + virtual bool eventFilter(QObject *,QEvent*); + virtual void drawContents ( QPainter *, int, int, int, int); + + /** + * [contentsM|m]ousePressEvent are reimplemented from QScrollView + * in order to ignore all mouseEvents on the viewport, so that the + * parent can handle them. + */ + virtual void contentsMousePressEvent(QMouseEvent *); + virtual void mousePressEvent(QMouseEvent *); + virtual void resizeEvent(QResizeEvent *); +}; +#endif + diff --git a/lib/compatibility/kmdi/qextmdi/ktabbar.cpp b/lib/compatibility/kmdi/qextmdi/ktabbar.cpp new file mode 100644 index 00000000..d8ee58cd --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/ktabbar.cpp @@ -0,0 +1,426 @@ +/* This file is part of the KDE libraries + Copyright (C) 2003 Stephan Binner <binner@kde.org> + Copyright (C) 2003 Zack Rusin <zack@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 <qapplication.h> +#include <qcursor.h> +#include <qpainter.h> +#include <qstyle.h> +#include <qtimer.h> +#include <qpushbutton.h> +#include <qtooltip.h> + +#include <kglobalsettings.h> +#include <kiconloader.h> +#include <klocale.h> + +#include "ktabbar.h" +#include "ktabwidget.h" + +KTabBar::KTabBar( QWidget *parent, const char *name ) + : QTabBar( parent, name ), mReorderStartTab( -1 ), mReorderPreviousTab( -1 ), + mHoverCloseButtonTab( 0 ), mDragSwitchTab( 0 ), mHoverCloseButton( 0 ), + mHoverCloseButtonEnabled( false ), mHoverCloseButtonDelayed( true ), + mTabReorderingEnabled( false ), mTabCloseActivatePrevious( false ) +{ + setAcceptDrops( true ); + setMouseTracking( true ); + + mEnableCloseButtonTimer = new QTimer( this ); + connect( mEnableCloseButtonTimer, SIGNAL( timeout() ), SLOT( enableCloseButton() ) ); + + mActivateDragSwitchTabTimer = new QTimer( this ); + connect( mActivateDragSwitchTabTimer, SIGNAL( timeout() ), SLOT( activateDragSwitchTab() ) ); + + connect(this, SIGNAL(layoutChanged()), SLOT(onLayoutChange())); +} + +KTabBar::~KTabBar() +{ + //For the future + //delete d; +} + +void KTabBar::setTabEnabled( int id, bool enabled ) +{ + QTab * t = tab( id ); + if ( t ) { + if ( t->isEnabled() != enabled ) { + t->setEnabled( enabled ); + QRect r( t->rect() ); + if ( !enabled && id == currentTab() && count()>1 ) { + QPtrList<QTab> *tablist = tabList(); + if ( mTabCloseActivatePrevious ) + t = tablist->at( count()-2 ); + else { + int index = indexOf( id ); + index += ( index+1 == count() ) ? -1 : 1; + t = tabAt( index ); + } + + if ( t->isEnabled() ) { + r = r.unite( t->rect() ); + tablist->append( tablist->take( tablist->findRef( t ) ) ); + emit selected( t->identifier() ); + } + } + repaint( r ); + } + } +} + +void KTabBar::mouseDoubleClickEvent( QMouseEvent *e ) +{ + if( e->button() != LeftButton ) + return; + + QTab *tab = selectTab( e->pos() ); + if( tab ) { + emit( mouseDoubleClick( indexOf( tab->identifier() ) ) ); + return; + } + QTabBar::mouseDoubleClickEvent( e ); +} + +void KTabBar::mousePressEvent( QMouseEvent *e ) +{ + if( e->button() == LeftButton ) { + mEnableCloseButtonTimer->stop(); + mDragStart = e->pos(); + } + else if( e->button() == RightButton ) { + QTab *tab = selectTab( e->pos() ); + if( tab ) { + emit( contextMenu( indexOf( tab->identifier() ), mapToGlobal( e->pos() ) ) ); + return; + } + } + QTabBar::mousePressEvent( e ); +} + +void KTabBar::mouseMoveEvent( QMouseEvent *e ) +{ + if ( e->state() == LeftButton ) { + QTab *tab = selectTab( e->pos() ); + if ( mDragSwitchTab && tab != mDragSwitchTab ) { + mActivateDragSwitchTabTimer->stop(); + mDragSwitchTab = 0; + } + + int delay = KGlobalSettings::dndEventDelay(); + QPoint newPos = e->pos(); + if( newPos.x() > mDragStart.x()+delay || newPos.x() < mDragStart.x()-delay || + newPos.y() > mDragStart.y()+delay || newPos.y() < mDragStart.y()-delay ) + { + if( tab ) { + emit( initiateDrag( indexOf( tab->identifier() ) ) ); + return; + } + } + } + else if ( e->state() == MidButton ) { + if (mReorderStartTab==-1) { + int delay = KGlobalSettings::dndEventDelay(); + QPoint newPos = e->pos(); + if( newPos.x() > mDragStart.x()+delay || newPos.x() < mDragStart.x()-delay || + newPos.y() > mDragStart.y()+delay || newPos.y() < mDragStart.y()-delay ) + { + QTab *tab = selectTab( e->pos() ); + if( tab && mTabReorderingEnabled ) { + mReorderStartTab = indexOf( tab->identifier() ); + grabMouse( sizeAllCursor ); + return; + } + } + } + else { + QTab *tab = selectTab( e->pos() ); + if( tab ) { + int reorderStopTab = indexOf( tab->identifier() ); + if ( mReorderStartTab!=reorderStopTab && mReorderPreviousTab!=reorderStopTab ) { + emit( moveTab( mReorderStartTab, reorderStopTab ) ); + mReorderPreviousTab=mReorderStartTab; + mReorderStartTab=reorderStopTab; + return; + } + } + } + } + + if ( mHoverCloseButtonEnabled && mReorderStartTab==-1) { + QTab *t = selectTab( e->pos() ); + if( t && t->iconSet() && t->isEnabled() ) { + QPixmap pixmap = t->iconSet()->pixmap( QIconSet::Small, QIconSet::Normal ); + QRect rect( 0, 0, pixmap.width() + 4, pixmap.height() +4); + + int xoff = 0, yoff = 0; + // The additional offsets were found by try and error, TODO: find the rational behind them + if ( t == tab( currentTab() ) ) { + xoff = style().pixelMetric( QStyle::PM_TabBarTabShiftHorizontal, this ) + 3; + yoff = style().pixelMetric( QStyle::PM_TabBarTabShiftVertical, this ) - 4; + } + else { + xoff = 7; + yoff = 0; + } + rect.moveLeft( t->rect().left() + 2 + xoff ); + rect.moveTop( t->rect().center().y()-pixmap.height()/2 + yoff ); + if ( rect.contains( e->pos() ) ) { + if ( mHoverCloseButton ) { + if ( mHoverCloseButtonTab == t ) + return; + mEnableCloseButtonTimer->stop(); + delete mHoverCloseButton; + } + + mHoverCloseButton = new QPushButton( this ); + mHoverCloseButton->setIconSet( KGlobal::iconLoader()->loadIconSet("fileclose", KIcon::Toolbar, KIcon::SizeSmall) ); + mHoverCloseButton->setGeometry( rect ); + QToolTip::add(mHoverCloseButton,i18n("Close this tab")); + mHoverCloseButton->setFlat(true); + mHoverCloseButton->show(); + if ( mHoverCloseButtonDelayed ) { + mHoverCloseButton->setEnabled(false); + mEnableCloseButtonTimer->start( QApplication::doubleClickInterval(), true ); + } + mHoverCloseButtonTab = t; + connect( mHoverCloseButton, SIGNAL( clicked() ), SLOT( closeButtonClicked() ) ); + return; + } + } + if ( mHoverCloseButton ) { + mEnableCloseButtonTimer->stop(); + delete mHoverCloseButton; + mHoverCloseButton = 0; + } + } + + QTabBar::mouseMoveEvent( e ); +} + +void KTabBar::enableCloseButton() +{ + mHoverCloseButton->setEnabled(true); +} + +void KTabBar::activateDragSwitchTab() +{ + QTab *tab = selectTab( mapFromGlobal( QCursor::pos() ) ); + if ( tab && mDragSwitchTab == tab ) + setCurrentTab( mDragSwitchTab ); + mDragSwitchTab = 0; +} + +void KTabBar::mouseReleaseEvent( QMouseEvent *e ) +{ + if( e->button() == MidButton ) { + if ( mReorderStartTab==-1 ) { + QTab *tab = selectTab( e->pos() ); + if( tab ) { + emit( mouseMiddleClick( indexOf( tab->identifier() ) ) ); + return; + } + } + else { + releaseMouse(); + setCursor( arrowCursor ); + mReorderStartTab=-1; + mReorderPreviousTab=-1; + } + } + QTabBar::mouseReleaseEvent( e ); +} + +void KTabBar::dragMoveEvent( QDragMoveEvent *e ) +{ + QTab *tab = selectTab( e->pos() ); + if( tab ) { + bool accept = false; + // The receivers of the testCanDecode() signal has to adjust + // 'accept' accordingly. + emit testCanDecode( e, accept); + if ( accept && tab != QTabBar::tab( currentTab() ) ) { + mDragSwitchTab = tab; + mActivateDragSwitchTabTimer->start( QApplication::doubleClickInterval()*2, true ); + } + e->accept( accept ); + return; + } + e->accept( false ); + QTabBar::dragMoveEvent( e ); +} + +void KTabBar::dropEvent( QDropEvent *e ) +{ + QTab *tab = selectTab( e->pos() ); + if( tab ) { + mActivateDragSwitchTabTimer->stop(); + mDragSwitchTab = 0; + emit( receivedDropEvent( indexOf( tab->identifier() ) , e ) ); + return; + } + QTabBar::dropEvent( e ); +} + +#ifndef QT_NO_WHEELEVENT +void KTabBar::wheelEvent( QWheelEvent *e ) +{ + if ( e->orientation() == Horizontal ) + return; + + emit( wheelDelta( e->delta() ) ); +} +#endif + +void KTabBar::setTabColor( int id, const QColor& color ) +{ + QTab *t = tab( id ); + if ( t ) { + mTabColors.insert( id, color ); + repaint( t->rect(), false ); + } +} + +const QColor &KTabBar::tabColor( int id ) const +{ + if ( mTabColors.contains( id ) ) + return mTabColors[id]; + + return colorGroup().foreground(); +} + +int KTabBar::insertTab( QTab *t, int index ) +{ + int res = QTabBar::insertTab( t, index ); + + if ( mTabCloseActivatePrevious && count() > 2 ) { + QPtrList<QTab> *tablist = tabList(); + tablist->insert( count()-2, tablist->take( tablist->findRef( t ) ) ); + } + + return res; +} + +void KTabBar::removeTab( QTab *t ) +{ + mTabColors.remove( t->identifier() ); + QTabBar::removeTab( t ); +} + +void KTabBar::paintLabel( QPainter *p, const QRect& br, + QTab *t, bool has_focus ) const +{ + QRect r = br; + bool selected = currentTab() == t->identifier(); + if ( t->iconSet() ) { + // the tab has an iconset, draw it in the right mode + QIconSet::Mode mode = ( t->isEnabled() && isEnabled() ) + ? QIconSet::Normal : QIconSet::Disabled; + if ( mode == QIconSet::Normal && has_focus ) + mode = QIconSet::Active; + QPixmap pixmap = t->iconSet()->pixmap( QIconSet::Small, mode ); + int pixw = pixmap.width(); + int pixh = pixmap.height(); + r.setLeft( r.left() + pixw + 4 ); + r.setRight( r.right() + 2 ); + + int inactiveXShift = style().pixelMetric( QStyle::PM_TabBarTabShiftHorizontal, this ); + int inactiveYShift = style().pixelMetric( QStyle::PM_TabBarTabShiftVertical, this ); + + int right = t->text().isEmpty() ? br.right() - pixw : br.left() + 2; + + p->drawPixmap( right + (selected ? 0 : inactiveXShift), + br.center().y() - pixh / 2 + (selected ? 0 : inactiveYShift), + pixmap ); + } + + QStyle::SFlags flags = QStyle::Style_Default; + + if ( isEnabled() && t->isEnabled() ) + flags |= QStyle::Style_Enabled; + if ( has_focus ) + flags |= QStyle::Style_HasFocus; + + QColorGroup cg( colorGroup() ); + if ( mTabColors.contains( t->identifier() ) ) + cg.setColor( QColorGroup::Foreground, mTabColors[t->identifier()] ); + + style().drawControl( QStyle::CE_TabBarLabel, p, this, r, + t->isEnabled() ? cg : palette().disabled(), + flags, QStyleOption(t) ); +} + +bool KTabBar::isTabReorderingEnabled() const +{ + return mTabReorderingEnabled; +} + +void KTabBar::setTabReorderingEnabled( bool on ) +{ + mTabReorderingEnabled = on; +} + +bool KTabBar::tabCloseActivatePrevious() const +{ + return mTabCloseActivatePrevious; +} + +void KTabBar::setTabCloseActivatePrevious( bool on ) +{ + mTabCloseActivatePrevious = on; +} + +void KTabBar::closeButtonClicked() +{ + emit closeRequest( indexOf( mHoverCloseButtonTab->identifier() ) ); +} + +void KTabBar::setHoverCloseButton( bool button ) +{ + mHoverCloseButtonEnabled = button; + if ( !button ) + onLayoutChange(); +} + +bool KTabBar::hoverCloseButton() const +{ + return mHoverCloseButtonEnabled; +} + +void KTabBar::setHoverCloseButtonDelayed( bool delayed ) +{ + mHoverCloseButtonDelayed = delayed; +} + +bool KTabBar::hoverCloseButtonDelayed() const +{ + return mHoverCloseButtonDelayed; +} + +void KTabBar::onLayoutChange() +{ + mEnableCloseButtonTimer->stop(); + delete mHoverCloseButton; + mHoverCloseButton = 0; + mHoverCloseButtonTab = 0; + mActivateDragSwitchTabTimer->stop(); + mDragSwitchTab = 0; +} + +#include "ktabbar.moc" diff --git a/lib/compatibility/kmdi/qextmdi/ktabbar.h b/lib/compatibility/kmdi/qextmdi/ktabbar.h new file mode 100644 index 00000000..2ea300db --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/ktabbar.h @@ -0,0 +1,113 @@ +/* This file is part of the KDE libraries + Copyright (C) 2003 Stephan Binner <binner@kde.org> + Copyright (C) 2003 Zack Rusin <zack@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. +*/ + +#ifndef KTABBAR_H +#define KTABBAR_H + +#include <qtabbar.h> + +#include <kdelibs_export.h> + +class QTimer; +class QPushButton; +class KTabBarPrivate; + +/** + * @since 3.2 + */ +class KDEUI_EXPORT KTabBar: public QTabBar +{ + Q_OBJECT + +public: + KTabBar( QWidget* parent=0, const char* name=0 ); + virtual ~KTabBar(); + + virtual void setTabEnabled( int, bool ); + + const QColor &tabColor( int ) const; + void setTabColor( int, const QColor& ); + + virtual int insertTab( QTab *, int index = -1 ); + virtual void removeTab( QTab * ); + + void setTabReorderingEnabled( bool enable ); + bool isTabReorderingEnabled() const; + + void setHoverCloseButton( bool ); + bool hoverCloseButton() const; + + void setHoverCloseButtonDelayed( bool ); + bool hoverCloseButtonDelayed() const; + + void setTabCloseActivatePrevious( bool ); + bool tabCloseActivatePrevious() const; + +signals: + void contextMenu( int, const QPoint & ); + void mouseDoubleClick( int ); + void mouseMiddleClick( int ); + void initiateDrag( int ); + void testCanDecode(const QDragMoveEvent *e, bool &accept /* result */); + void receivedDropEvent( int, QDropEvent * ); + void moveTab( int, int ); + void closeRequest( int ); +#ifndef QT_NO_WHEELEVENT + void wheelDelta( int ); +#endif + +protected: + virtual void mouseDoubleClickEvent( QMouseEvent *e ); + virtual void mousePressEvent( QMouseEvent *e ); + virtual void mouseMoveEvent( QMouseEvent *e ); + virtual void mouseReleaseEvent( QMouseEvent *e ); +#ifndef QT_NO_WHEELEVENT + virtual void wheelEvent( QWheelEvent *e ); +#endif + + virtual void dragMoveEvent( QDragMoveEvent *e ); + virtual void dropEvent( QDropEvent *e ); + + virtual void paintLabel( QPainter*, const QRect&, QTab*, bool ) const; + +protected slots: + virtual void closeButtonClicked(); + virtual void onLayoutChange(); + virtual void enableCloseButton(); + virtual void activateDragSwitchTab(); + +private: + QPoint mDragStart; + int mReorderStartTab; + int mReorderPreviousTab; + QMap<int, QColor> mTabColors; + QTab *mHoverCloseButtonTab, *mDragSwitchTab; + QPushButton *mHoverCloseButton; + QTimer *mEnableCloseButtonTimer, *mActivateDragSwitchTabTimer; + + bool mHoverCloseButtonEnabled; + bool mHoverCloseButtonDelayed; + bool mTabReorderingEnabled; + bool mTabCloseActivatePrevious; + + KTabBarPrivate * d; +}; + +#endif diff --git a/lib/compatibility/kmdi/qextmdi/ktabwidget.cpp b/lib/compatibility/kmdi/qextmdi/ktabwidget.cpp new file mode 100644 index 00000000..af73e013 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/ktabwidget.cpp @@ -0,0 +1,523 @@ +/* This file is part of the KDE libraries + Copyright (C) 2003 Stephan Binner <binner@kde.org> + Copyright (C) 2003 Zack Rusin <zack@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 <qapplication.h> +#include <qstyle.h> + +#include <kconfig.h> +#include <kiconloader.h> +#include <kstringhandler.h> + +#include "ktabwidget.h" +#include "ktabbar.h" + +class KTabWidgetPrivate { +public: + bool m_automaticResizeTabs; + int m_maxLength; + int m_minLength; + unsigned int m_CurrentMaxLength; + + //holds the full names of the tab, otherwise all we + //know about is the shortened name + QStringList m_tabNames; + + KTabWidgetPrivate() { + m_automaticResizeTabs = false; + KConfigGroupSaver groupsaver(KGlobal::config(), "General"); + m_maxLength = KGlobal::config()->readNumEntry("MaximumTabLength", 30); + m_minLength = KGlobal::config()->readNumEntry("MinimumTabLength", 3); + m_CurrentMaxLength = m_minLength; + } +}; + +KTabWidget::KTabWidget( QWidget *parent, const char *name, WFlags f ) + : QTabWidget( parent, name, f ) +{ + d = new KTabWidgetPrivate; + setTabBar( new KTabBar(this, "tabbar") ); + setAcceptDrops( true ); + + connect(tabBar(), SIGNAL(contextMenu( int, const QPoint & )), SLOT(contextMenu( int, const QPoint & ))); + connect(tabBar(), SIGNAL(mouseDoubleClick( int )), SLOT(mouseDoubleClick( int ))); + connect(tabBar(), SIGNAL(mouseMiddleClick( int )), SLOT(mouseMiddleClick( int ))); + connect(tabBar(), SIGNAL(initiateDrag( int )), SLOT(initiateDrag( int ))); + connect(tabBar(), SIGNAL(testCanDecode(const QDragMoveEvent *, bool & )), SIGNAL(testCanDecode(const QDragMoveEvent *, bool & ))); + connect(tabBar(), SIGNAL(receivedDropEvent( int, QDropEvent * )), SLOT(receivedDropEvent( int, QDropEvent * ))); + connect(tabBar(), SIGNAL(moveTab( int, int )), SLOT(moveTab( int, int ))); + connect(tabBar(), SIGNAL(closeRequest( int )), SLOT(closeRequest( int ))); +#ifndef QT_NO_WHEELEVENT + connect(tabBar(), SIGNAL(wheelDelta( int )), SLOT(wheelDelta( int ))); +#endif +} + +KTabWidget::~KTabWidget() +{ + delete d; +} + +void KTabWidget::insertTab( QWidget *child, const QString &label, int index ) +{ + QTabWidget::insertTab( child, label, index ); +} + +void KTabWidget::insertTab( QWidget *child, const QIconSet& iconset, const QString &label, int index ) +{ + QTabWidget::insertTab( child, iconset, label, index ); +} + +void KTabWidget::insertTab( QWidget *child, QTab *tab, int index ) +{ + QTabWidget::insertTab( child, tab, index); + if ( d->m_automaticResizeTabs ) { + if ( index < 0 || index >= count() ) { + d->m_tabNames.append( tab->text() ); + resizeTabs( d->m_tabNames.count()-1 ); + } + else { + d->m_tabNames.insert( d->m_tabNames.at( index ), tab->text() ); + resizeTabs( index ); + } + } +} + +void KTabWidget::setTabBarHidden( bool hide ) +{ + QWidget *rightcorner = this->cornerWidget( TopRight ); + QWidget *leftcorner = this->cornerWidget( TopLeft ); + + if ( hide ) { + if ( leftcorner ) leftcorner->hide(); + if ( rightcorner ) rightcorner->hide(); + tabBar()->hide(); + } else { + tabBar()->show(); + if ( leftcorner ) leftcorner->show(); + if ( rightcorner ) rightcorner->show(); + } +} + +bool KTabWidget::isTabBarHidden() const +{ + return !( tabBar()->isVisible() ); +} + +void KTabWidget::setTabColor( QWidget *w, const QColor& color ) +{ + QTab *t = tabBar()->tabAt( indexOf( w ) ); + if (t) { + static_cast<KTabBar*>(tabBar())->setTabColor( t->identifier(), color ); + } +} + +QColor KTabWidget::tabColor( QWidget *w ) const +{ + QTab *t = tabBar()->tabAt( indexOf( w ) ); + if (t) { + return static_cast<KTabBar*>(tabBar())->tabColor( t->identifier() ); + } else { + return QColor(); + } +} + +void KTabWidget::setTabReorderingEnabled( bool on) +{ + static_cast<KTabBar*>(tabBar())->setTabReorderingEnabled( on ); +} + +bool KTabWidget::isTabReorderingEnabled() const +{ + return static_cast<KTabBar*>(tabBar())->isTabReorderingEnabled(); +} + +void KTabWidget::setTabCloseActivatePrevious( bool previous) +{ + static_cast<KTabBar*>(tabBar())->setTabCloseActivatePrevious( previous ); +} + +bool KTabWidget::tabCloseActivatePrevious() const +{ + return static_cast<KTabBar*>(tabBar())->tabCloseActivatePrevious(); +} + +unsigned int KTabWidget::tabBarWidthForMaxChars( uint maxLength ) +{ + int hframe, overlap; + hframe = tabBar()->style().pixelMetric( QStyle::PM_TabBarTabHSpace, tabBar() ); + overlap = tabBar()->style().pixelMetric( QStyle::PM_TabBarTabOverlap, tabBar() ); + + QFontMetrics fm = tabBar()->fontMetrics(); + int x = 0; + for( int i=0; i < count(); ++i ) { + QString newTitle = d->m_tabNames[ i ]; + newTitle = KStringHandler::rsqueeze( newTitle, maxLength ).leftJustify( d->m_minLength, ' ' ); + + QTab* tab = tabBar()->tabAt( i ); + int lw = fm.width( newTitle ); + int iw = 0; + if ( tab->iconSet() ) + iw = tab->iconSet()->pixmap( QIconSet::Small, QIconSet::Normal ).width() + 4; + x += ( tabBar()->style().sizeFromContents( QStyle::CT_TabBarTab, this, + QSize( QMAX( lw + hframe + iw, QApplication::globalStrut().width() ), 0 ), + QStyleOption( tab ) ) ).width(); + } + return x; +} + +void KTabWidget::changeTab( QWidget *w, const QString &label ) +{ + QTabWidget::changeTab( w, label ); + if ( d->m_automaticResizeTabs ) { + int index = indexOf( w ); + if ( index != -1 ) { + d->m_tabNames[ index ] = label; + resizeTabs( index ); + } + } +} + +void KTabWidget::changeTab( QWidget *w, const QIconSet &iconset, const QString &label ) +{ + QTabWidget::changeTab( w, iconset, label ); + if ( d->m_automaticResizeTabs ) { + int index = indexOf( w ); + if ( index != -1 ) { + d->m_tabNames[ index ] = label; + resizeTabs( index ); + } + } +} + +QString KTabWidget::label( int index ) const +{ + if ( d->m_automaticResizeTabs ) { + if ( index >= 0 && index < count() ) + return d->m_tabNames[ index ]; + else + return QString::null; + } + else + return QTabWidget::label( index ); +} + +QString KTabWidget::tabLabel( QWidget * w ) const +{ + if ( d->m_automaticResizeTabs ) { + int index = indexOf( w ); + if ( index == -1 ) + return QString::null; + else + return d->m_tabNames[ index ]; + } + else + return QTabWidget::tabLabel( w ); +} + +void KTabWidget::setTabLabel( QWidget *w, const QString &l ) +{ + QTabWidget::setTabLabel( w, l ); + if ( d->m_automaticResizeTabs ) { + int index = indexOf( w ); + if ( index != -1 ) { + d->m_tabNames[ index ] = l; + resizeTabs( index ); + } + } +} + +void KTabWidget::resizeTabs( int changeTabIndex ) +{ + uint newMaxLength; + if ( d->m_automaticResizeTabs ) { + // Calculate new max length + newMaxLength=d->m_maxLength; + uint lcw=0, rcw=0; + + int tabBarHeight = tabBar()->sizeHint().height(); + if ( cornerWidget( TopLeft ) && cornerWidget( TopLeft )->isVisible() ) + lcw = QMAX( cornerWidget( TopLeft )->width(), tabBarHeight ); + if ( cornerWidget( TopRight ) && cornerWidget( TopRight )->isVisible() ) + rcw = QMAX( cornerWidget( TopRight )->width(), tabBarHeight ); + + uint maxTabBarWidth = width() - lcw - rcw; + + for ( ; newMaxLength > (uint)d->m_minLength; newMaxLength-- ) { + if ( tabBarWidthForMaxChars( newMaxLength ) < maxTabBarWidth ) + break; + } + } + else + newMaxLength = 4711; + + // Update hinted or all tabs + if ( d->m_CurrentMaxLength != newMaxLength ) { + d->m_CurrentMaxLength = newMaxLength; + for( int i = 0; i < count(); ++i ) + updateTab( i ); + } + else if ( changeTabIndex != -1 ) + updateTab( changeTabIndex ); +} + +void KTabWidget::updateTab( int index ) +{ + QString title = d->m_automaticResizeTabs ? d->m_tabNames[ index ] : QTabWidget::label( index ); + removeTabToolTip( page( index ) ); + if ( title.length() > d->m_CurrentMaxLength ) + setTabToolTip( page( index ), title ); + + title = KStringHandler::rsqueeze( title, d->m_CurrentMaxLength ).leftJustify( d->m_minLength, ' ' ); + title.replace( '&', "&&" ); + + if ( QTabWidget::label( index ) != title ) + QTabWidget::setTabLabel( page( index ), title ); +} + +void KTabWidget::dragMoveEvent( QDragMoveEvent *e ) +{ + if ( isEmptyTabbarSpace( e->pos() ) ) { + bool accept = false; + // The receivers of the testCanDecode() signal has to adjust + // 'accept' accordingly. + emit testCanDecode( e, accept); + e->accept( accept ); + return; + } + e->accept( false ); + QTabWidget::dragMoveEvent( e ); +} + +void KTabWidget::dropEvent( QDropEvent *e ) +{ + if ( isEmptyTabbarSpace( e->pos() ) ) { + emit ( receivedDropEvent( e ) ); + return; + } + QTabWidget::dropEvent( e ); +} + +#ifndef QT_NO_WHEELEVENT +void KTabWidget::wheelEvent( QWheelEvent *e ) +{ + if ( e->orientation() == Horizontal ) + return; + + if ( isEmptyTabbarSpace( e->pos() ) ) + wheelDelta( e->delta() ); + else + e->ignore(); +} + +void KTabWidget::wheelDelta( int delta ) +{ + if ( count() < 2 ) + return; + + int page = currentPageIndex(); + if ( delta < 0 ) + page = (page + 1) % count(); + else { + page--; + if ( page < 0 ) + page = count() - 1; + } + setCurrentPage( page ); +} +#endif + +void KTabWidget::mouseDoubleClickEvent( QMouseEvent *e ) +{ + if( e->button() != LeftButton ) + return; + + if ( isEmptyTabbarSpace( e->pos() ) ) { + emit( mouseDoubleClick() ); + return; + } + QTabWidget::mouseDoubleClickEvent( e ); +} + +void KTabWidget::mousePressEvent( QMouseEvent *e ) +{ + if ( e->button() == RightButton ) { + if ( isEmptyTabbarSpace( e->pos() ) ) { + emit( contextMenu( mapToGlobal( e->pos() ) ) ); + return; + } + } else if ( e->button() == MidButton ) { + if ( isEmptyTabbarSpace( e->pos() ) ) { + emit( mouseMiddleClick() ); + return; + } + } + QTabWidget::mousePressEvent( e ); +} + +void KTabWidget::receivedDropEvent( int index, QDropEvent *e ) +{ + emit( receivedDropEvent( page( index ), e ) ); +} + +void KTabWidget::initiateDrag( int index ) +{ + emit( initiateDrag( page( index ) ) ); +} + +void KTabWidget::contextMenu( int index, const QPoint &p ) +{ + emit( contextMenu( page( index ), p ) ); +} + +void KTabWidget::mouseDoubleClick( int index ) +{ + emit( mouseDoubleClick( page( index ) ) ); +} + +void KTabWidget::mouseMiddleClick( int index ) +{ + emit( mouseMiddleClick( page( index ) ) ); +} + +void KTabWidget::moveTab( int from, int to ) +{ + QString tablabel = label( from ); + QWidget *w = page( from ); + QColor color = tabColor( w ); + QIconSet tabiconset = tabIconSet( w ); + QString tabtooltip = tabToolTip( w ); + bool current = ( w == currentPage() ); + bool enabled = isTabEnabled( w ); + blockSignals(true); + removePage( w ); + + // Work-around kmdi brain damage which calls showPage() in insertTab() + QTab * t = new QTab(); + t->setText(tablabel); + QTabWidget::insertTab( w, t, to ); + if ( d->m_automaticResizeTabs ) { + if ( to < 0 || to >= count() ) + d->m_tabNames.append( QString::null ); + else + d->m_tabNames.insert( d->m_tabNames.at( to ), QString::null ); + } + + w = page( to ); + changeTab( w, tabiconset, tablabel ); + setTabToolTip( w, tabtooltip ); + setTabColor( w, color ); + if ( current ) + showPage( w ); + setTabEnabled( w, enabled ); + blockSignals(false); + + emit ( movedTab( from, to ) ); +} + +void KTabWidget::removePage( QWidget * w ) { + if ( d->m_automaticResizeTabs ) { + int index = indexOf( w ); + if ( index != -1 ) + d->m_tabNames.remove( d->m_tabNames.at( index ) ); + } + QTabWidget::removePage( w ); + if ( d->m_automaticResizeTabs ) + resizeTabs(); +} + + +bool KTabWidget::isEmptyTabbarSpace( const QPoint &p ) const +{ + QPoint point( p ); + QSize size( tabBar()->sizeHint() ); + if ( ( tabPosition()==Top && point.y()< size.height() ) || ( tabPosition()==Bottom && point.y()>(height()-size.height() ) ) ) { + QWidget *rightcorner = cornerWidget( TopRight ); + if ( rightcorner ) { + if ( point.x()>=width()-rightcorner->width() ) + return false; + } + QWidget *leftcorner = cornerWidget( TopLeft ); + if ( leftcorner ) { + if ( point.x()<=leftcorner->width() ) + return false; + point.setX( point.x()-size.height() ); + } + if ( tabPosition()==Bottom ) + point.setY( point.y()-( height()-size.height() ) ); + QTab *tab = tabBar()->selectTab( point); + if( !tab ) + return true; + } + return false; +} + +void KTabWidget::setHoverCloseButton( bool button ) +{ + static_cast<KTabBar*>(tabBar())->setHoverCloseButton( button ); +} + +bool KTabWidget::hoverCloseButton() const +{ + return static_cast<KTabBar*>(tabBar())->hoverCloseButton(); +} + +void KTabWidget::setHoverCloseButtonDelayed( bool delayed ) +{ + static_cast<KTabBar*>(tabBar())->setHoverCloseButtonDelayed( delayed ); +} + +bool KTabWidget::hoverCloseButtonDelayed() const +{ + return static_cast<KTabBar*>(tabBar())->hoverCloseButtonDelayed(); +} + +void KTabWidget::setAutomaticResizeTabs( bool enabled ) +{ + if ( d->m_automaticResizeTabs==enabled ) + return; + + d->m_automaticResizeTabs = enabled; + if ( enabled ) { + d->m_tabNames.clear(); + for( int i = 0; i < count(); ++i ) + d->m_tabNames.append( tabBar()->tabAt( i )->text() ); + } + else + for( int i = 0; i < count(); ++i ) + tabBar()->tabAt( i )->setText( d->m_tabNames[ i ] ); + resizeTabs(); +} + +bool KTabWidget::automaticResizeTabs() const +{ + return d->m_automaticResizeTabs; +} + +void KTabWidget::closeRequest( int index ) +{ + emit( closeRequest( page( index ) ) ); +} + +void KTabWidget::resizeEvent( QResizeEvent *e ) +{ + QTabWidget::resizeEvent( e ); + resizeTabs(); +} + +#include "ktabwidget.moc" diff --git a/lib/compatibility/kmdi/qextmdi/ktabwidget.h b/lib/compatibility/kmdi/qextmdi/ktabwidget.h new file mode 100644 index 00000000..634dcda3 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/ktabwidget.h @@ -0,0 +1,291 @@ +/* This file is part of the KDE libraries + Copyright (C) 2003 Stephan Binner <binner@kde.org> + Copyright (C) 2003 Zack Rusin <zack@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. +*/ + +#ifndef KTABWIDGET_H +#define KTABWIDGET_H + +#include <qtabwidget.h> +#include <qstringlist.h> + +#include <kdelibs_export.h> + +class KTabWidgetPrivate; + +/** + * \brief A widget containing multiple tabs + * + * @since 3.2 + */ +class KDEUI_EXPORT KTabWidget : public QTabWidget +{ + Q_OBJECT + Q_PROPERTY( bool tabReorderingEnabled READ isTabReorderingEnabled WRITE setTabReorderingEnabled ) + Q_PROPERTY( bool hoverCloseButton READ hoverCloseButton WRITE setHoverCloseButton ) + Q_PROPERTY( bool hoverCloseButtonDelayed READ hoverCloseButtonDelayed WRITE setHoverCloseButtonDelayed ) + Q_PROPERTY( bool tabCloseActivatePrevious READ tabCloseActivatePrevious WRITE setTabCloseActivatePrevious ) + Q_PROPERTY( bool automaticResizeTabs READ automaticResizeTabs WRITE setAutomaticResizeTabs ) + +public: + KTabWidget( QWidget *parent = 0, const char *name = 0, WFlags f = 0 ); + /** + * Destructor. + */ + virtual ~KTabWidget(); + /*! + Set the tab of the given widget to \a color. + */ + void setTabColor( QWidget *, const QColor& color ); + QColor tabColor( QWidget * ) const; + + /*! + Returns true if tab ordering with the middle mouse button + has been enabled. + */ + bool isTabReorderingEnabled() const; + + /*! + Returns true if the close button is shown on tabs + when mouse is hovering over them. + */ + bool hoverCloseButton() const; + + /*! + Returns true if the close button is shown on tabs + after a delay. + */ + bool hoverCloseButtonDelayed() const; + + /*! + Returns true if closing the current tab activates the previous + actice tab instead of the one to the right. + @since 3.3 + */ + bool tabCloseActivatePrevious() const; + + /*! + Returns true if calling setTitle() will resize tabs + to the width of the tab bar. + @since 3.4 + */ + bool automaticResizeTabs() const; + + /*! + If \a hide is true, the tabbar is hidden along with any corner + widgets. + @since 3.4 + */ + void setTabBarHidden( bool hide ); + + /*! + Return true if the tabbar is hidden. + @since 3.4 + */ + bool isTabBarHidden() const; + + /*! + Reimplemented for internal reasons. + */ + virtual void insertTab( QWidget *, const QString &, int index = -1 ); + + /*! + Reimplemented for internal reasons. + */ + virtual void insertTab( QWidget *child, const QIconSet& iconset, + const QString &label, int index = -1 ); + /*! + Reimplemented for internal reasons. + */ + virtual void insertTab( QWidget *, QTab *, int index = -1 ); + + /*! + Reimplemented for internal reasons. + */ + void changeTab( QWidget *, const QString & ); + + /*! + Reimplemented for internal reasons. + */ + void changeTab( QWidget *child, const QIconSet& iconset, const QString &label ); + + /*! + Reimplemented for internal reasons. + */ + QString label( int ) const; + + /*! + Reimplemented for internal reasons. + */ + QString tabLabel( QWidget * ) const; + + /*! + Reimplemented for internal reasons. + */ + void setTabLabel( QWidget *, const QString & ); + +public slots: + /*! + Move a widget's tab from first to second specified index and emit + signal movedTab( int, int ) afterwards. + */ + virtual void moveTab( int, int ); + + /*! + Removes the widget, reimplemented for + internal reasons (keeping labels in sync). + */ + virtual void removePage ( QWidget * w ); + + /*! + If \a enable is true, tab reordering with middle button will be enabled. + + Note that once enabled you shouldn't rely on previously queried + currentPageIndex() or indexOf( QWidget * ) values anymore. + + You can connect to signal movedTab(int, int) which will notify + you from which index to which index a tab has been moved. + */ + void setTabReorderingEnabled( bool enable ); + + /*! + If \a enable is true, a close button will be shown on mouse hover + over tab icons which will emit signal closeRequest( QWidget * ) + when pressed. + */ + void setHoverCloseButton( bool enable ); + + /*! + If \a delayed is true, a close button will be shown on mouse hover + over tab icons after mouse double click delay else immediately. + */ + void setHoverCloseButtonDelayed( bool delayed ); + + /*! + If \a delayed is true, closing the current tab activates the + previous active tab instead of the one to the right. + @since 3.3 + */ + void setTabCloseActivatePrevious( bool previous ); + + /*! + If \a enable is true, tabs will be resized to the width of the tab bar. + + Does not work reliable with "QTabWidget* foo=new KTabWidget()" and if + you change tabs via the tabbar or by accessing tabs directly. + @since 3.4 + */ + void setAutomaticResizeTabs( bool enable ); + +signals: + /*! + Connect to this and set accept to true if you can and want to decode the event. + */ + void testCanDecode(const QDragMoveEvent *e, bool &accept /* result */); + + /*! + Received an event in the empty space beside tabbar. Usually creates a new tab. + This signal is only possible after testCanDecode and positive accept result. + */ + void receivedDropEvent( QDropEvent * ); + + /*! + Received an drop event on given widget's tab. + This signal is only possible after testCanDecode and positive accept result. + */ + void receivedDropEvent( QWidget *, QDropEvent * ); + + /*! + Request to start a drag operation on the given tab. + */ + void initiateDrag( QWidget * ); + + /*! + The right mouse button was pressed over empty space besides tabbar. + */ + void contextMenu( const QPoint & ); + + /*! + The right mouse button was pressed over a widget. + */ + void contextMenu( QWidget *, const QPoint & ); + + /*! + A tab was moved from first to second index. This signal is only + possible after you have called setTabReorderingEnabled( true ). + */ + void movedTab( int, int ); + + /*! + A double left mouse button click was performed over empty space besides tabbar. + @since 3.3 + */ + void mouseDoubleClick(); + + /*! + A double left mouse button click was performed over the widget. + */ + void mouseDoubleClick( QWidget * ); + + /*! + A middle mouse button click was performed over empty space besides tabbar. + */ + void mouseMiddleClick(); + + /*! + A middle mouse button click was performed over the widget. + */ + void mouseMiddleClick( QWidget * ); + + /*! + The close button of a widget's tab was clicked. This signal is + only possible after you have called setHoverCloseButton( true ). + */ + void closeRequest( QWidget * ); + +protected: + virtual void mouseDoubleClickEvent( QMouseEvent *e ); + virtual void mousePressEvent( QMouseEvent * ); + virtual void dragMoveEvent( QDragMoveEvent * ); + virtual void dropEvent( QDropEvent * ); + unsigned int tabBarWidthForMaxChars( uint maxLength ); +#ifndef QT_NO_WHEELEVENT + virtual void wheelEvent( QWheelEvent *e ); +#endif + virtual void resizeEvent( QResizeEvent * ); + +protected slots: + virtual void receivedDropEvent( int, QDropEvent * ); + virtual void initiateDrag( int ); + virtual void contextMenu( int, const QPoint & ); + virtual void mouseDoubleClick( int ); + virtual void mouseMiddleClick( int ); + virtual void closeRequest( int ); +#ifndef QT_NO_WHEELEVENT + virtual void wheelDelta( int ); +#endif + +private: + bool isEmptyTabbarSpace( const QPoint & ) const; + void resizeTabs( int changedTabIndex = -1 ); + void updateTab( int index ); + + KTabWidgetPrivate *d; +}; + +#endif diff --git a/lib/compatibility/kmdi/qextmdi/res/filenew.xpm b/lib/compatibility/kmdi/qextmdi/res/filenew.xpm new file mode 100644 index 00000000..b261800d --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/res/filenew.xpm @@ -0,0 +1,27 @@ +/* XPM */ +#ifndef _FILENEW_XPM_ +#define _FILENEW_XPM_ + +static const char *filenew[] = { +"10 14 5 1", +" c None", +". c #000000", +"+ c #FFFFFF", +"@ c #DCDCDC", +"# c #C0C0C0", +"....... ", +".++++@@. ", +".++++#+@. ", +".++++#++@.", +".++++#....", +".+++++###.", +".++++++++.", +".++++++++.", +".++++++++.", +".++++++++.", +".++++++++.", +".++++++++.", +".++++++++.", +".........."}; + +#endif diff --git a/lib/compatibility/kmdi/qextmdi/res/kde2_closebutton.xpm b/lib/compatibility/kmdi/qextmdi/res/kde2_closebutton.xpm new file mode 100644 index 00000000..5c05e714 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/res/kde2_closebutton.xpm @@ -0,0 +1,22 @@ +/* XPM */ +#ifndef _KDE2_CLOSEBUTTON_XPM_ +#define _KDE2_CLOSEBUTTON_XPM_ + +static const char* kde2_closebutton[]={ +"12 12 2 1", +". s None c None", +"# c #000000", +"............", +"............", +"...#....#...", +"..###..###..", +"...######...", +"....####....", +"....####....", +"...######...", +"..###..###..", +"...#....#...", +"............", +"............"}; + +#endif diff --git a/lib/compatibility/kmdi/qextmdi/res/kde2_maxbutton.xpm b/lib/compatibility/kmdi/qextmdi/res/kde2_maxbutton.xpm new file mode 100644 index 00000000..c8ef8113 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/res/kde2_maxbutton.xpm @@ -0,0 +1,22 @@ +/* XPM */ +#ifndef _KDE2_MAXBUTTON_XPM_ +#define _KDE2_MAXBUTTON_XPM_ + +static const char* kde2_maxbutton[]={ +"12 12 2 1", +". s None c None", +"# c #000000", +"............", +"............", +"..########..", +"..########..", +"..##....##..", +"..##....##..", +"..##....##..", +"..##....##..", +"..########..", +"..########..", +"............", +"............"}; + +#endif diff --git a/lib/compatibility/kmdi/qextmdi/res/kde2_minbutton.xpm b/lib/compatibility/kmdi/qextmdi/res/kde2_minbutton.xpm new file mode 100644 index 00000000..98669195 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/res/kde2_minbutton.xpm @@ -0,0 +1,22 @@ +/* XPM */ +#ifndef _KDE2_MINBUTTON_XPM_ +#define _KDE2_MINBUTTON_XPM_ + +static const char* kde2_minbutton[]={ +"12 12 2 1", +". s None c None", +"# c #000000", +"............", +"............", +"............", +"............", +"....####....", +"....####....", +"....####....", +"....####....", +"............", +"............", +"............", +"............"}; + +#endif diff --git a/lib/compatibility/kmdi/qextmdi/res/kde2_restorebutton.xpm b/lib/compatibility/kmdi/qextmdi/res/kde2_restorebutton.xpm new file mode 100644 index 00000000..a6e01fcb --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/res/kde2_restorebutton.xpm @@ -0,0 +1,22 @@ +/* XPM */ +#ifndef _KDE2_RESTOREBUTTON_XPM_ +#define _KDE2_RESTOREBUTTON_XPM_ + +static const char* kde2_restorebutton[]={ +"12 12 2 1", +". s None c None", +"# c #000000", +"............", +".########...", +".########...", +".##....##...", +".##.########", +".##.########", +".#####....##", +".#####....##", +"....##....##", +"....########", +"....########", +"............"}; + +#endif diff --git a/lib/compatibility/kmdi/qextmdi/res/kde2_undockbutton.xpm b/lib/compatibility/kmdi/qextmdi/res/kde2_undockbutton.xpm new file mode 100644 index 00000000..711bf01c --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/res/kde2_undockbutton.xpm @@ -0,0 +1,22 @@ +/* XPM */ +#ifndef _KDE2_UNDOCKBUTTON_XPM_ +#define _KDE2_UNDOCKBUTTON_XPM_ + +static const char* kde2_undockbutton[]={ +"12 12 2 1", +". s None c None", +"# c #000000", +"............", +".#####......", +".#####......", +".####.......", +".#####......", +".##.###.....", +".....###....", +"......###...", +".......###..", +"........##..", +"............", +"............"}; + +#endif diff --git a/lib/compatibility/kmdi/qextmdi/res/kde2laptop_closebutton.xpm b/lib/compatibility/kmdi/qextmdi/res/kde2laptop_closebutton.xpm new file mode 100644 index 00000000..6801e4e3 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/res/kde2laptop_closebutton.xpm @@ -0,0 +1,18 @@ +/* XPM */ +#ifndef _KDE2LAPTOP_CLOSEBUTTON_XPM_ +#define _KDE2LAPTOP_CLOSEBUTTON_XPM_ + +static const char* kde2laptop_closebutton[]={ +"20 8 2 1", +". s None c None", +"# c #000000", +".......#....#.......", +"......###..###......", +".......######.......", +"........####........", +"........####........", +".......######.......", +"......###..###......", +".......#....#......."}; + +#endif diff --git a/lib/compatibility/kmdi/qextmdi/res/kde2laptop_closebutton_menu.xpm b/lib/compatibility/kmdi/qextmdi/res/kde2laptop_closebutton_menu.xpm new file mode 100644 index 00000000..9d071231 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/res/kde2laptop_closebutton_menu.xpm @@ -0,0 +1,25 @@ +/* XPM */ +#ifndef _KDE2LAPTOP_CLOSEBUTTON_MENU_XPM_ +#define _KDE2LAPTOP_CLOSEBUTTON_MENU_XPM_ + +static const char* kde2laptop_closebutton_menu[]={ +"27 14 3 1", +". s None c None", +"+ c #303030", +"# c #000000", +"##########################.", +"#........................#+", +"#........................#+", +"#.........#....#.........#+", +"#........###..###........#+", +"#.........######.........#+", +"#..........####..........#+", +"#..........####..........#+", +"#.........######.........#+", +"#........###..###........#+", +"#.........#....#.........#+", +"#........................#+", +"##########################+", +".++++++++++++++++++++++++++"}; + +#endif diff --git a/lib/compatibility/kmdi/qextmdi/res/kde2laptop_maxbutton.xpm b/lib/compatibility/kmdi/qextmdi/res/kde2laptop_maxbutton.xpm new file mode 100644 index 00000000..b8ce6de2 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/res/kde2laptop_maxbutton.xpm @@ -0,0 +1,18 @@ +/* XPM */ +#ifndef _KDE2LAPTOP_MAXBUTTON_XPM_ +#define _KDE2LAPTOP_MAXBUTTON_XPM_ + +static const char* kde2laptop_maxbutton[]={ +"20 8 2 1", +". s None c None", +"# c #000000", +"........##..........", +".......####.........", +"......######........", +".....########.......", +".....########.......", +"....................", +".....########.......", +".....########......."}; + +#endif diff --git a/lib/compatibility/kmdi/qextmdi/res/kde2laptop_minbutton.xpm b/lib/compatibility/kmdi/qextmdi/res/kde2laptop_minbutton.xpm new file mode 100644 index 00000000..6bcf76c5 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/res/kde2laptop_minbutton.xpm @@ -0,0 +1,18 @@ +/* XPM */ +#ifndef _KDE2LAPTOP_MINBUTTON_XPM_ +#define _KDE2LAPTOP_MINBUTTON_XPM_ + +static const char* kde2laptop_minbutton[]={ +"20 8 2 1", +". s None c None", +"# c #000000", +"......########......", +"......########......", +"....................", +"......########......", +"......########......", +".......######.......", +"........####........", +".........##........."}; + +#endif diff --git a/lib/compatibility/kmdi/qextmdi/res/kde2laptop_restorebutton.xpm b/lib/compatibility/kmdi/qextmdi/res/kde2laptop_restorebutton.xpm new file mode 100644 index 00000000..803ce6db --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/res/kde2laptop_restorebutton.xpm @@ -0,0 +1,18 @@ +/* XPM */ +#ifndef _KDE2LAPTOP_RESTOREBUTTON_XPM_ +#define _KDE2LAPTOP_RESTOREBUTTON_XPM_ + +static const char* kde2laptop_restorebutton[]={ +"20 8 2 1", +". s None c None", +"# c #000000", +".......##...........", +"........##..........", +".....##..##.........", +".....###..##........", +".....####..##.......", +".....#####..#.......", +".....######.........", +".....#######........"}; + +#endif diff --git a/lib/compatibility/kmdi/qextmdi/res/kde2laptop_undockbutton.xpm b/lib/compatibility/kmdi/qextmdi/res/kde2laptop_undockbutton.xpm new file mode 100644 index 00000000..1f23ecaf --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/res/kde2laptop_undockbutton.xpm @@ -0,0 +1,18 @@ +/* XPM */ +#ifndef _KDE2LAPTOP_UNDOCKBUTTON_XPM_ +#define _KDE2LAPTOP_UNDOCKBUTTON_XPM_ + +static const char* kde2laptop_undockbutton[]={ +"20 8 2 1", +". s None c None", +"# c #000000", +".....######.........", +".....#####..........", +".....####...........", +".....#####..........", +".....##.###.........", +".....#...###........", +"..........###.......", +"...........##......."}; + +#endif diff --git a/lib/compatibility/kmdi/qextmdi/res/kde_closebutton.xpm b/lib/compatibility/kmdi/qextmdi/res/kde_closebutton.xpm new file mode 100644 index 00000000..e714359a --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/res/kde_closebutton.xpm @@ -0,0 +1,30 @@ +/* XPM */ +#ifndef _KDE_CLOSEBUTTON_XPM_ +#define _KDE_CLOSEBUTTON_XPM_ + +static const char *kde_closebutton[] = { +/* width height num_colors chars_per_pixel */ +"16 16 3 1", +/* colors */ +" s None c None", +". c white", +"X c #707070", +/* pixels */ +" ", +" ", +" .X .X ", +" .XX .XX ", +" .XX .XX ", +" .XX .XX ", +" .XX.XX ", +" .XXX ", +" .XXX ", +" .XX.XX ", +" .XX .XX ", +" .XX .XX ", +" .XX .XX ", +" .X .X ", +" ", +" "}; + +#endif diff --git a/lib/compatibility/kmdi/qextmdi/res/kde_maxbutton.xpm b/lib/compatibility/kmdi/qextmdi/res/kde_maxbutton.xpm new file mode 100644 index 00000000..2af3bf88 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/res/kde_maxbutton.xpm @@ -0,0 +1,30 @@ +/* XPM */ +#ifndef _KDE_MAXBUTTON_XPM_ +#define _KDE_MAXBUTTON_XPM_ + +static const char *kde_maxbutton[] = { +/* width height num_colors chars_per_pixel */ +"16 16 3 1", +/* colors */ +" s None c None", +". c white", +"X c #707070", +/* pixels */ +" ", +" ", +" ........... ", +" .XXXXXXXXXX ", +" .X .X ", +" .X .X ", +" .X .X ", +" .X .X ", +" .X .X ", +" .X .X ", +" .X .X ", +" .X........X ", +" .XXXXXXXXXX ", +" ", +" ", +" "}; + +#endif diff --git a/lib/compatibility/kmdi/qextmdi/res/kde_minbutton.xpm b/lib/compatibility/kmdi/qextmdi/res/kde_minbutton.xpm new file mode 100644 index 00000000..c4e609ae --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/res/kde_minbutton.xpm @@ -0,0 +1,30 @@ +/* XPM */ +#ifndef _KDE_MINBUTTON_XPM_ +#define _KDE_MINBUTTON_XPM_ + +static const char *kde_minbutton[] = { +/* width height num_colors chars_per_pixel */ +"16 16 3 1", +/* colors */ +" s None c None", +". c white", +"X c #707070", +/* pixels */ +" ", +" ", +" ", +" ", +" ", +" ", +" ... ", +" . X ", +" .XX ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; + +#endif diff --git a/lib/compatibility/kmdi/qextmdi/res/kde_restorebutton.xpm b/lib/compatibility/kmdi/qextmdi/res/kde_restorebutton.xpm new file mode 100644 index 00000000..4ec18513 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/res/kde_restorebutton.xpm @@ -0,0 +1,30 @@ +/* XPM */ +#ifndef _KDE_RESTOREBUTTON_XPM_ +#define _KDE_RESTOREBUTTON_XPM_ + +static const char *kde_restorebutton[] = { +/* width height num_colors chars_per_pixel */ +"16 16 3 1", +/* colors */ +" s None c None", +". c #707070", +"X c white", +/* pixels */ +" ", +" ", +" ........... ", +" .XXXXXXXXXX ", +" .X .X ", +" .X .X ", +" .X .X ", +" .X .X ", +" .X .X ", +" .X .X ", +" .X .X ", +" .X........X ", +" .XXXXXXXXXX ", +" ", +" ", +" "}; + +#endif diff --git a/lib/compatibility/kmdi/qextmdi/res/kde_undockbutton.xpm b/lib/compatibility/kmdi/qextmdi/res/kde_undockbutton.xpm new file mode 100644 index 00000000..de97e9e7 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/res/kde_undockbutton.xpm @@ -0,0 +1,27 @@ +/* XPM */ +#ifndef _KDE_UNDOCKBUTTON_XPM_ +#define _KDE_UNDOCKBUTTON_XPM_ + +static const char *kde_undockbutton[]={ +"16 16 3 1", +". c None", +"# c #ffffff", +"a c #707070", +"................", +"................", +"..#aaaaaaa......", +"..#aa#####......", +"..#aaa..........", +"..#a#aa.........", +"..#a.#aa........", +"..#a..#aa.......", +"..#a...#aa......", +"..#a....#aa.....", +".........#aa....", +"..........#aa...", +"...........#aa..", +"............#...", +"................", +"................"}; + +#endif diff --git a/lib/compatibility/kmdi/qextmdi/res/win_closebutton.xpm b/lib/compatibility/kmdi/qextmdi/res/win_closebutton.xpm new file mode 100644 index 00000000..d8be0243 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/res/win_closebutton.xpm @@ -0,0 +1,30 @@ +/* XPM */ +#ifndef _WIN_CLOSEBUTTON_XPM_ +#define _WIN_CLOSEBUTTON_XPM_ + +static const char *win_closebutton[] = { +/* width height num_colors chars_per_pixel */ +" 16 14 4 1", +/* colors */ +". c #000000", +"# c #808080", +"a c None", +"b c #ffffff", +/* pixels */ +"bbbbbbbbbbbbbbb.", +"baaaaaaaaaaaaa#.", +"baaaaaaaaaaaaa#.", +"baaa..aaaa..aa#.", +"baaaa..aa..aaa#.", +"baaaaa....aaaa#.", +"baaaaaa..aaaaa#.", +"baaaaa....aaaa#.", +"baaaa..aa..aaa#.", +"baaa..aaaa..aa#.", +"baaaaaaaaaaaaa#.", +"baaaaaaaaaaaaa#.", +"b##############.", +"................" +}; + +#endif diff --git a/lib/compatibility/kmdi/qextmdi/res/win_maxbutton.xpm b/lib/compatibility/kmdi/qextmdi/res/win_maxbutton.xpm new file mode 100644 index 00000000..95e501a8 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/res/win_maxbutton.xpm @@ -0,0 +1,30 @@ +/* XPM */ +#ifndef _WIN_MAXBUTTON_XPM_ +#define _WIN_MAXBUTTON_XPM_ + +static const char *win_maxbutton[] = { +/* width height num_colors chars_per_pixel */ +" 16 14 4 1", +/* colors */ +". c #000000", +"# c #808080", +"a c None", +"b c #ffffff", +/* pixels */ +"bbbbbbbbbbbbbbb.", +"baaaaaaaaaaaaa#.", +"baa.........aa#.", +"baa.........aa#.", +"baa.aaaaaaa.aa#.", +"baa.aaaaaaa.aa#.", +"baa.aaaaaaa.aa#.", +"baa.aaaaaaa.aa#.", +"baa.aaaaaaa.aa#.", +"baa.aaaaaaa.aa#.", +"baa.........aa#.", +"baaaaaaaaaaaaa#.", +"b##############.", +"................" +}; + +#endif diff --git a/lib/compatibility/kmdi/qextmdi/res/win_minbutton.xpm b/lib/compatibility/kmdi/qextmdi/res/win_minbutton.xpm new file mode 100644 index 00000000..1e8787e7 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/res/win_minbutton.xpm @@ -0,0 +1,30 @@ +/* XPM */ +#ifndef _WIN_MINBUTTON_XPM_ +#define _WIN_MINBUTTON_XPM_ + +static const char *win_minbutton[] = { +/* width height num_colors chars_per_pixel */ +" 16 14 4 1", +/* colors */ +". c #000000", +"# c #808080", +"a c None", +"b c #ffffff", +/* pixels */ +"bbbbbbbbbbbbbbb.", +"baaaaaaaaaaaaa#.", +"baaaaaaaaaaaaa#.", +"baaaaaaaaaaaaa#.", +"baaaaaaaaaaaaa#.", +"baaaaaaaaaaaaa#.", +"baaaaaaaaaaaaa#.", +"baaaaaaaaaaaaa#.", +"baaaaaaaaaaaaa#.", +"baaa......aaaa#.", +"baaa......aaaa#.", +"baaaaaaaaaaaaa#.", +"b##############.", +"................" +}; + +#endif diff --git a/lib/compatibility/kmdi/qextmdi/res/win_restorebutton.xpm b/lib/compatibility/kmdi/qextmdi/res/win_restorebutton.xpm new file mode 100644 index 00000000..87bb5b30 --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/res/win_restorebutton.xpm @@ -0,0 +1,30 @@ +/* XPM */ +#ifndef _WIN_RESTOREBUTTON_XPM_ +#define _WIN_RESTOREBUTTON_XPM_ + +static const char *win_restorebutton[] = { +/* width height num_colors chars_per_pixel */ +" 16 14 4 1", +/* colors */ +". c #000000", +"# c #808080", +"a c None", +"b c #ffffff", +/* pixels */ +"bbbbbbbbbbbbbbb.", +"baaaaaaaaaaaaa#.", +"baaaa......aaa#.", +"baaaa......aaa#.", +"baaaa.aaaa.aaa#.", +"baa......a.aaa#.", +"baa......a.aaa#.", +"baa.aaaa...aaa#.", +"baa.aaaa.aaaaa#.", +"baa.aaaa.aaaaa#.", +"baa......aaaaa#.", +"baaaaaaaaaaaaa#.", +"b##############.", +"................" +}; + +#endif diff --git a/lib/compatibility/kmdi/qextmdi/res/win_undockbutton.xpm b/lib/compatibility/kmdi/qextmdi/res/win_undockbutton.xpm new file mode 100644 index 00000000..386ebd8a --- /dev/null +++ b/lib/compatibility/kmdi/qextmdi/res/win_undockbutton.xpm @@ -0,0 +1,26 @@ +/* XPM */ +#ifndef _WIN_UNDOCKBUTTON_XPM_ +#define _WIN_UNDOCKBUTTON_XPM_ + +static const char* win_undockbutton[]={ +"16 14 4 1", +"b c #808080", +"# c #000000", +"a c None", +". c #ffffff", +"...............#", +".aaaaaaaaaaaaab#", +".aaaaaaaaaaaaab#", +".aaa####aaaaaab#", +".aaa###aaaaaaab#", +".aaa####aaaaaab#", +".aaa#a###aaaaab#", +".aaaaaa###aaaab#", +".aaaaaaa###aaab#", +".aaaaaaaa###aab#", +".aaaaaaaaa#aaab#", +".aaaaaaaaaaaaab#", +".bbbbbbbbbbbbbb#", +"################"}; + +#endif diff --git a/lib/compatibility/knewstuff/Makefile.am b/lib/compatibility/knewstuff/Makefile.am new file mode 100644 index 00000000..d0718429 --- /dev/null +++ b/lib/compatibility/knewstuff/Makefile.am @@ -0,0 +1,13 @@ +AM_CPPFLAGS = -I$(srcdir)/.. $(all_includes) + +METASOURCES = AUTO + +noinst_LTLIBRARIES = libknewstuff.la + +libknewstuff_la_LDFLAGS = $(all_libraries) +libknewstuff_la_LIBADD = $(LIB_KIO) +libknewstuff_la_SOURCES = engine.cpp entry.cpp downloaddialog.cpp \ + uploaddialog.cpp providerdialog.cpp provider.cpp knewstuff.cpp \ + knewstuffgeneric.cpp knewstuffsecure.cpp security.cpp + +KDE_ICON=AUTO diff --git a/lib/compatibility/knewstuff/cr16-action-knewstuff.png b/lib/compatibility/knewstuff/cr16-action-knewstuff.png Binary files differnew file mode 100644 index 00000000..ef5ea45e --- /dev/null +++ b/lib/compatibility/knewstuff/cr16-action-knewstuff.png diff --git a/lib/compatibility/knewstuff/cr32-action-knewstuff.png b/lib/compatibility/knewstuff/cr32-action-knewstuff.png Binary files differnew file mode 100644 index 00000000..757e9266 --- /dev/null +++ b/lib/compatibility/knewstuff/cr32-action-knewstuff.png diff --git a/lib/compatibility/knewstuff/cr64-action-knewstuff.png b/lib/compatibility/knewstuff/cr64-action-knewstuff.png Binary files differnew file mode 100644 index 00000000..ad6d5e56 --- /dev/null +++ b/lib/compatibility/knewstuff/cr64-action-knewstuff.png diff --git a/lib/compatibility/knewstuff/downloaddialog.cpp b/lib/compatibility/knewstuff/downloaddialog.cpp new file mode 100644 index 00000000..be3cf66d --- /dev/null +++ b/lib/compatibility/knewstuff/downloaddialog.cpp @@ -0,0 +1,628 @@ +/* + This file is part of KNewStuff. + Copyright (c) 2003 Josef Spillner <spillner@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 "downloaddialog.h" +#include "downloaddialog.moc" + +#include <klocale.h> +#include <ktabctl.h> +#include <klistview.h> +#include <kdebug.h> +#include <kio/job.h> +#include <kio/netaccess.h> +#include <kmessagebox.h> +#include <kurl.h> +#include <kconfig.h> +#include <kapplication.h> +#include <kiconloader.h> + +#include <knewstuff/entry.h> +#include <knewstuff/knewstuffgeneric.h> +#include <knewstuff/engine.h> + +#include <qlayout.h> +#include <qpushbutton.h> +#include <qdom.h> +#include <qlabel.h> +#include <qtextbrowser.h> +#include <qtimer.h> // hack + +using namespace KNS; + +class NumSortListViewItem : public KListViewItem +{ + public: + NumSortListViewItem( QListView * parent, QString label1, QString label2 = QString::null, QString label3 = QString::null, QString label4 = QString::null, QString label5 = QString::null, QString label6 = QString::null, QString label7 = QString::null, QString label8 = QString::null ) : + KListViewItem( parent, label1, label2, label3, label4, label5, label6, label7, label8 ) + { + } + + QString key(int col, bool asc) const { + if (col == 2) + { + + QString s; + s.sprintf("%08d", text(col).toInt()); + return s; + } + return KListViewItem::key( col, asc ); + } +}; + +// BEGIN deprecated for KDE 4 +DownloadDialog::DownloadDialog(Engine *engine, QWidget *) +: KDialogBase(KDialogBase::IconList, i18n("Get Hot New Stuff"), + KDialogBase::Close, KDialogBase::Close) +{ + init(engine); +} + +DownloadDialog::DownloadDialog(QWidget *) +: KDialogBase(KDialogBase::IconList, i18n("Get Hot New Stuff"), + KDialogBase::Close, KDialogBase::Close) +{ + init(0); +} + +void DownloadDialog::open(QString type) +{ + DownloadDialog d; + d.setType(type); + d.load(); + d.exec(); +} +// END deprecated for KDE 4 + +DownloadDialog::DownloadDialog(Engine *engine, QWidget *, const QString& caption) +: KDialogBase(KDialogBase::IconList, (caption.isNull() ? i18n("Get Hot New Stuff") : caption), + KDialogBase::Close, KDialogBase::Close) +{ + init(engine); +} + +DownloadDialog::DownloadDialog(QWidget *, const QString& caption) +: KDialogBase(KDialogBase::IconList, (caption.isNull() ? i18n("Get Hot New Stuff") : caption), + KDialogBase::Close, KDialogBase::Close) +{ + init(0); +} + +void DownloadDialog::init(Engine *engine) +{ + resize(700, 400); + + m_engine = engine; + m_page = NULL; + + connect(this, SIGNAL(aboutToShowPage(QWidget*)), SLOT(slotPage(QWidget*))); + + if(!engine) + { + m_loader = new ProviderLoader(this); + connect(m_loader, SIGNAL(providersLoaded(Provider::List*)), SLOT(slotProviders(Provider::List*))); + } +} + +DownloadDialog::~DownloadDialog() +{ +} + +void DownloadDialog::load() +{ + m_loader->load(m_filter, m_providerlist); +} + +void DownloadDialog::load(QString providerList) +{ + m_loader->load(m_filter, providerList); +} + +void DownloadDialog::clear() +{ + QMap<QWidget*, QValueList<KListView*>* >::Iterator it; + for(it = m_map.begin(); it != m_map.end(); ++it) + { + QValueList<KListView*> *v = it.data(); + kdDebug() << "clear listviews in " << v << endl; + if(v) + { + (*(v->at(0)))->clear(); + (*(v->at(1)))->clear(); + (*(v->at(2)))->clear(); + + //delete (*it); + } + + delete it.key(); + } + m_map.clear(); +} + +void DownloadDialog::slotProviders(Provider::List *list) +{ + Provider *p; + /*QFrame *frame;*/ + + for(p = list->first(); p; p = list->next()) + { + kdDebug() << "++ provider ++ " << p->name() << endl; + + if(!m_filter.isEmpty()) + loadProvider(p); + else + addProvider(p); + /*if(p == list->getFirst()) + slotPage(m_frame);*/ // only if !qtbug + } +} + +void DownloadDialog::addProvider(Provider *p) +{ + QFrame *frame; + KTabCtl *ctl; + QWidget *w_d, *w_r, *w_l; + QWidget *w2; + KListView *lvtmp_r, *lvtmp_d, *lvtmp_l; + QTextBrowser *rt; + QString tmp; + int ret; + QPixmap pix; + + if(m_map.count() == 0) + { + frame = addPage(i18n("Welcome"), i18n("Welcome"), QPixmap("")); + delete frame; + } + + kdDebug() << "addProvider()/begin" << endl; + + ret = true; + if(!p->icon().isValid()) ret = false; + else ret = KIO::NetAccess::download(p->icon(), tmp, this); + if(ret) pix = QPixmap(tmp); + else pix = KGlobal::iconLoader()->loadIcon("knewstuff", KIcon::Panel); + frame = addPage(p->name(), p->name(), pix); + m_frame = frame; + + w2 = new QWidget(frame); + w_d = new QWidget(frame); + w_r = new QWidget(frame); + w_l = new QWidget(frame); + + ctl = new KTabCtl(frame); + ctl->addTab(w_r, i18n("Highest Rated")); + ctl->addTab(w_d, i18n("Most Downloads")); + ctl->addTab(w_l, i18n("Latest")); + + m_curtab = 0; + connect(ctl, SIGNAL(tabSelected(int)), SLOT(slotTab(int))); + + QHBoxLayout *box = new QHBoxLayout(frame); + box->add(ctl); + + lvtmp_r = new KListView(w_r); + lvtmp_r->addColumn(i18n("Name")); + lvtmp_r->addColumn(i18n("Version")); + lvtmp_r->addColumn(i18n("Rating")); + lvtmp_r->setSorting(2, false); + + lvtmp_d = new KListView(w_d); + lvtmp_d->addColumn(i18n("Name")); + lvtmp_d->addColumn(i18n("Version")); + lvtmp_d->addColumn(i18n("Downloads")); + lvtmp_d->setSorting(2, false); + + lvtmp_l = new KListView(w_l); + lvtmp_l->addColumn(i18n("Name")); + lvtmp_l->addColumn(i18n("Version")); + lvtmp_l->addColumn(i18n("Release Date")); + lvtmp_l->setSorting(2, false); + + connect(lvtmp_r, SIGNAL(selectionChanged()), SLOT(slotSelected())); + connect(lvtmp_d, SIGNAL(selectionChanged()), SLOT(slotSelected())); + connect(lvtmp_l, SIGNAL(selectionChanged()), SLOT(slotSelected())); + + rt = new QTextBrowser(frame); + rt->setMinimumWidth(150); + + QPushButton *in = new QPushButton(i18n("Install"), frame); + QPushButton *de = new QPushButton(i18n("Details"), frame); + in->setEnabled(false); + de->setEnabled(false); + + box->addSpacing(spacingHint()); + QVBoxLayout *vbox = new QVBoxLayout(box); + vbox->add(rt); + vbox->addSpacing(spacingHint()); + vbox->add(de); + vbox->add(in); + + connect(in, SIGNAL(clicked()), SLOT(slotInstall())); + connect(de, SIGNAL(clicked()), SLOT(slotDetails())); + + QVBoxLayout *box2 = new QVBoxLayout(w_r); + box2->add(lvtmp_r); + QVBoxLayout *box3 = new QVBoxLayout(w_d); + box3->add(lvtmp_d); + QVBoxLayout *box4 = new QVBoxLayout(w_l); + box4->add(lvtmp_l); + + QValueList<KListView*> *v = new QValueList<KListView*>; + *v << lvtmp_r << lvtmp_d << lvtmp_l; + m_map[frame] = v; + m_rts[frame] = rt; + QValueList<QPushButton*> *vb = new QValueList<QPushButton*>; + *vb << in << de; + m_buttons[frame] = vb; + m_providers[frame] = p; + + kdDebug() << "addProvider()/end; lvtmp_r = " << lvtmp_r << endl; + + if(m_engine) slotPage(frame); + + QTimer::singleShot(100, this, SLOT(slotFinish())); +} + +void DownloadDialog::slotResult(KIO::Job *job) +{ + QDomDocument dom; + QDomElement knewstuff; + + kdDebug() << "got data: " << m_data[job] << endl; + + kapp->config()->setGroup("KNewStuffStatus"); + + dom.setContent(m_data[job]); + knewstuff = dom.documentElement(); + + for(QDomNode pn = knewstuff.firstChild(); !pn.isNull(); pn = pn.nextSibling()) + { + QDomElement stuff = pn.toElement(); + + kdDebug() << "element: " << stuff.tagName() << endl; + + if(stuff.tagName() == "stuff") + { + Entry *entry = new Entry(stuff); + kdDebug() << "TYPE::" << entry->type() << " FILTER::" << m_filter << endl; + if(!entry->type().isEmpty()) + { + if((!m_filter.isEmpty()) && (entry->type() != m_filter)) continue; + } + + if((!m_filter.isEmpty()) && (m_jobs[job])) + { + Provider *p = m_jobs[job]; + addProvider(p); + slotPage(m_frame); + m_jobs[job] = 0; + } + addEntry(entry); + } + } + + m_data[job] = ""; +} + +int DownloadDialog::installStatus(Entry *entry) +{ + QDate date; + QString datestring; + int installed; + + kapp->config()->setGroup("KNewStuffStatus"); + datestring = kapp->config()->readEntry(entry->name()); + if(datestring.isNull()) installed = 0; + else + { + date = QDate::fromString(datestring, Qt::ISODate); + if(!date.isValid()) installed = 0; + else if(date < entry->releaseDate()) installed = -1; + else installed = 1; + } + + return installed; +} + +void DownloadDialog::addEntry(Entry *entry) +{ + QPixmap pix; + int installed; + + /*if(m_engine) + { + if(m_map.count() == 0) + { + m_frame = addPage(i18n("Welcome"), i18n("Welcome"), QPixmap("")); + Provider *p = new Provider(); + p->setName(i18n("Generic")); + addProvider(p); + slotPage(m_frame); + } + }*/ + installed = installStatus(entry); + + if(installed > 0) pix = KGlobal::iconLoader()->loadIcon("ok", KIcon::Small); + else if(installed < 0) pix = KGlobal::iconLoader()->loadIcon("history", KIcon::Small); + else pix = QPixmap(); + + KListViewItem *tmp_r = new KListViewItem(lv_r, + entry->name(), entry->version(), QString("%1").arg(entry->rating())); + KListViewItem *tmp_d = new NumSortListViewItem(lv_d, + entry->name(), entry->version(), QString("%1").arg(entry->downloads())); + KListViewItem *tmp_l = new KListViewItem(lv_l, + entry->name(), entry->version(), KGlobal::locale()->formatDate(entry->releaseDate())); + + tmp_r->setPixmap(0, pix); + tmp_d->setPixmap(0, pix); + tmp_l->setPixmap(0, pix); + + m_entries.append(entry); + + kdDebug() << "added entry " << entry->name() << endl; +} + +void DownloadDialog::slotData(KIO::Job *job, const QByteArray &a) +{ + QCString tmp(a, a.size() + 1); + m_data[job].append(QString::fromUtf8(tmp)); +} + +void DownloadDialog::slotDetails() +{ + Entry *e = getEntry(); + if(!e) return; + + QString lang = KGlobal::locale()->language(); + + QString info = i18n + ( + "Name: %1\n" + "Author: %2\n" + "License: %3\n" + "Version: %4\n" + "Release: %5\n" + "Rating: %6\n" + "Downloads: %7\n" + "Release date: %8\n" + "Summary: %9\n" + ).arg(e->name() + ).arg(e->author() + ).arg(e->license() + ).arg(e->version() + ).arg(e->release() + ).arg(e->rating() + ).arg(e->downloads() + ).arg(KGlobal::locale()->formatDate(e->releaseDate()) + ).arg(e->summary(lang) + ); + + info.append(i18n + ( + "Preview: %1\n" + "Payload: %2\n" + ).arg(e->preview().url() + ).arg(e->payload().url() + )); + + KMessageBox::information(this, info, i18n("Details")); +} + +void DownloadDialog::slotInstall() +{ + Entry *e = getEntry(); + if(!e) return; + + kdDebug() << "download entry now" << endl; + + if(m_engine) + { + m_engine->download(e); + install(e); + } + else + { + m_s = new KNewStuffGeneric(e->type(), this); + + m_entry = e; + + KURL source = e->payload(); + KURL dest = KURL(m_s->downloadDestination(e)); + + KIO::FileCopyJob *job = KIO::file_copy(source, dest, -1, true); + connect(job, SIGNAL(result(KIO::Job*)), SLOT(slotInstalled(KIO::Job*))); + } +} + +void DownloadDialog::install(Entry *e) +{ + kapp->config()->setGroup("KNewStuffStatus"); + kapp->config()->writeEntry(m_entryname, e->releaseDate().toString(Qt::ISODate)); + kapp->config()->sync(); + + QPixmap pix = KGlobal::iconLoader()->loadIcon("ok", KIcon::Small); + m_entryitem = lv_r->findItem(m_entryname, 0); + if(m_entryitem) m_entryitem->setPixmap(0, pix); + m_entryitem = lv_d->findItem(m_entryname, 0); + if(m_entryitem) m_entryitem->setPixmap(0, pix); + m_entryitem = lv_l->findItem(m_entryname, 0); + if(m_entryitem) m_entryitem->setPixmap(0, pix); + + + QPushButton *in; + in = *(m_buttons[m_page]->at(0)); + if(in) in->setEnabled(false); +} + +void DownloadDialog::slotInstalled(KIO::Job *job) +{ + bool ret = (job->error() == 0); + KIO::FileCopyJob *cjob; + + if(ret) + { + cjob = static_cast<KIO::FileCopyJob*>(job); + if(cjob) + { + ret = m_s->install(cjob->destURL().path()); + } + else ret = false; + } + + if(ret) + { + install(m_entry); + + KMessageBox::information(this, i18n("Installation successful."), i18n("Installation")); + } + else KMessageBox::error(this, i18n("Installation failed."), i18n("Installation")); + + delete m_s; +} + +void DownloadDialog::slotTab(int tab) +{ + kdDebug() << "switch tab to: " << tab << endl; + m_curtab = tab; +} + +void DownloadDialog::slotSelected() +{ + QString tmp; + bool enabled; + Entry *e = getEntry(); + QString lang = KGlobal::locale()->language(); + + if(e) + { + if(!e->preview(lang).isValid()) + { + m_rt->setText(QString("<b>%1</b><br>%2<br>%3<br><br><i>%4</i><br>(%5)").arg( + e->name()).arg(e->author()).arg(KGlobal::locale()->formatDate(e->releaseDate())).arg(e->summary(lang)).arg(e->license())); + } + else + { + KIO::NetAccess::download(e->preview(lang), tmp, this); + m_rt->setText(QString("<b>%1</b><br>%2<br>%3<br><br><img src='%4'><br><i>%5</i><br>(%6)").arg( + e->name()).arg(e->author()).arg(KGlobal::locale()->formatDate(e->releaseDate())).arg(tmp).arg(e->summary(lang)).arg(e->license())); + } + + if(installStatus(e) == 1) enabled = false; + else enabled = true; + + QPushButton *de, *in; + in = *(m_buttons[m_page]->at(0)); + de = *(m_buttons[m_page]->at(1)); + if(in) in->setEnabled(enabled); + if(de) de->setEnabled(true); + } +} + +Entry *DownloadDialog::getEntry() +{ + if(m_curtab == 0) m_entryitem = lv_r->currentItem(); + else if(m_curtab == 1) m_entryitem = lv_d->currentItem(); + else if(m_curtab == 2) m_entryitem = lv_l->currentItem(); + else return 0; + + m_entryname = m_entryitem->text(0); + + for(Entry *e = m_entries.first(); e; e = m_entries.next()) + { + if(e->name() == m_entryname) return e; + } + + return 0; +} + +void DownloadDialog::slotPage(QWidget *w) +{ + Provider *p; + + kdDebug() << "changed widget!!!" << endl; + + if(m_map.find(w) == m_map.end()) return; + + m_page = w; + + lv_r = *(m_map[w]->at(0)); + lv_d = *(m_map[w]->at(1)); + lv_l = *(m_map[w]->at(2)); + p = m_providers[w]; + m_rt = m_rts[w]; + + kdDebug() << "valid change!!!; lv_r = " << lv_r << endl; + + if(m_engine) return; + + if(!m_filter.isEmpty()) return; + + lv_r->clear(); + lv_d->clear(); + lv_l->clear(); + + kdDebug() << "-- fetch -- " << p->downloadUrl() << endl; + + loadProvider(p); +} + +void DownloadDialog::loadProvider(Provider *p) +{ + KIO::TransferJob *job = KIO::get(p->downloadUrl()); + + m_jobs[job] = p; + + connect(job, SIGNAL(result(KIO::Job*)), SLOT(slotResult(KIO::Job*))); + connect(job, SIGNAL(data(KIO::Job*, const QByteArray&)), + SLOT(slotData(KIO::Job*, const QByteArray&))); +} + +void DownloadDialog::setType(QString type) +{ + m_filter = type; +} + +void DownloadDialog::setProviderList(const QString& providerList) +{ + m_providerlist = providerList; +} + +void DownloadDialog::slotOk() +{ +} + +void DownloadDialog::slotApply() +{ +} + +void DownloadDialog::open(const QString& type, const QString& caption) +{ + DownloadDialog d(0, caption); + d.setType(type); + d.load(); + d.exec(); +} + +void DownloadDialog::slotFinish() +{ + showPage(1); + //updateBackground(); +} + diff --git a/lib/compatibility/knewstuff/downloaddialog.h b/lib/compatibility/knewstuff/downloaddialog.h new file mode 100644 index 00000000..34b2b22b --- /dev/null +++ b/lib/compatibility/knewstuff/downloaddialog.h @@ -0,0 +1,237 @@ +/* + This file is part of KNewStuff. + Copyright (c) 2003 Josef Spillner <spillner@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. +*/ +#ifndef KNEWSTUFF_DOWNLOADDIALOG_H +#define KNEWSTUFF_DOWNLOADDIALOG_H + +#include <kdialogbase.h> +#include <knewstuff/provider.h> + +namespace KIO +{ + class Job; +} + +class KListView; +class QTextBrowser; +class QFrame; +class KNewStuffGeneric; + +namespace KNS +{ + +class ProviderLoader; +class Entry; +class Provider; +class Engine; + +/** + * @short Common download dialog for data browsing and installation. + * + * It provides an easy-to-use convenience method named open() which does all + * the work, unless a more complex operation is needed. + * \code + * KNewStuff::DownloadDialog::open("kdesktop/wallpapers"); + * \endcode + * + * @author Josef Spillner (spillner@kde.org) + * \par Maintainer: + * Josef Spillner (spillner@kde.org) + */ +class KDE_EXPORT DownloadDialog : public KDialogBase +{ + Q_OBJECT + public: + /** + Constructor. + + @param engine a pre-built engine object, or NULL if the download + dialog should create an engine on its own + @param parent the parent window + @param caption the dialog caption + */ + DownloadDialog(Engine *engine, QWidget *parent, const QString& caption); + + /** + Alternative constructor. + Always uses an internal engine. + + @param parent the parent window + @param caption the dialog caption + */ + DownloadDialog(QWidget *parent, const QString& caption); + + /** + Destructor. + */ + ~DownloadDialog(); + + /** + Restricts the display of available data to a certain data type. + + @param type a Hotstuff data type such as "korganizer/calendar" + */ + void setType(QString type); + // ### KDE 4.0: use const QString& + + /** + Fetches descriptions of all available data, optionally considering + a previously set type. + */ + void load(); + + /** + Explicitly uses this provider list instead of the one read from + the application configuration. + + @param providerList the URL of the provider list + + @since 3.4 + */ + void setProviderList(const QString& providerList); + + /** + Fetches descriptions of all available data, optionally considering + a previously set type. + + @param providerList the URl to the list of providers; if empty + we first try the ProvidersUrl from KGlobal::config, then we + fall back to a hardcoded value. + */ + void load(QString providerList); // KDE4: merge with load() above + + /** + Adds another provider to the download dialog. + This is normally done internally. + + @param p the Hotstuff provider to be added + */ + void addProvider(Provider *p); + + /** + Adds an additional entry to the current provider. + This is normally done internally. + + @param entry a Hotstuff data entry to be added + */ + void addEntry(Entry *entry); + + /** + Clears the entry list of the current provider. + This is normally done internally. + */ + void clear(); + + /** + Opens the download dialog. + This is a convenience method which automatically sets up the dialog. + @see setType() + @see load() + + @param type a data type such as "korganizer/calendar" + @param caption the dialog caption + */ + static void open(const QString& type, const QString& caption); + + /** + Constructor. + + @param engine a pre-built engine object, or NULL if the download + dialog should create an engine on its own + @param parent the parent window + */ + DownloadDialog(Engine *engine, QWidget *parent = 0); + // ### KDE 4.0: remove and make caption/parent argument optional + + /** + Alternative constructor. + Always uses an internal engine. + + @param parent the parent window + */ + DownloadDialog(QWidget *parent = 0); + // ### KDE 4.0: remove and make caption/parent argument optional + + /** + Opens the download dialog. + This is a convenience method which automatically sets up the dialog. + @see setType() + @see load() + + @param type a data type such as "korganizer/calendar" + */ + static void open(QString type); + // ### KDE 4.0: remove and make caption/parent argument optional + + public slots: + /** + Availability of the provider list. + + @param list list of Hotstuff providers + */ + void slotProviders(Provider::List *list); + + protected slots: + void slotApply(); + void slotOk(); + + private slots: + void slotResult(KIO::Job *job); + void slotData(KIO::Job *job, const QByteArray &a); + void slotInstall(); + void slotDetails(); + void slotInstalled(KIO::Job *job); + void slotTab(int tab); + void slotSelected(); + void slotPage(QWidget *w); + void slotFinish(); + + private: + void init(Engine *e); + Entry *getEntry(); + void loadProvider(Provider *p); + void install(Entry *e); + int installStatus(Entry *e); + + ProviderLoader *m_loader; + QString m_entryname; + KListView *lv_r, *lv_d, *lv_l; + QTextBrowser *m_rt; + QFrame *m_frame; + QListViewItem *m_entryitem; + QPtrList<Entry> m_entries; + Entry *m_entry; + KNewStuffGeneric *m_s; + int m_curtab; + QMap<QWidget*, QValueList<KListView*>* > m_map; + QMap<QWidget*, Provider*> m_providers; + QMap<QWidget*, QTextBrowser*> m_rts; + QMap<QWidget*, QValueList<QPushButton*>* > m_buttons; + QMap<KIO::Job*, Provider*> m_jobs; + QMap<KIO::Job*, QString> m_data; + QString m_filter; + QString m_providerlist; + Engine *m_engine; + QWidget *m_page; +}; + +} + +#endif + diff --git a/lib/compatibility/knewstuff/engine.cpp b/lib/compatibility/knewstuff/engine.cpp new file mode 100644 index 00000000..c141aeeb --- /dev/null +++ b/lib/compatibility/knewstuff/engine.cpp @@ -0,0 +1,420 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <schumacher@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 <qcstring.h> +#include <qdom.h> +#include <qfileinfo.h> + +#include <kapplication.h> +#include <kdebug.h> +#include <kio/job.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> + +#include "knewstuff.h" +#include "downloaddialog.h" +#include "uploaddialog.h" +#include "providerdialog.h" + +#include "engine.h" +#include "engine.moc" + +using namespace KNS; + +Engine::Engine( KNewStuff *newStuff, const QString &type, + QWidget *parentWidget ) : + mParentWidget( parentWidget ), mDownloadDialog( 0 ), + mUploadDialog( 0 ), mProviderDialog( 0 ), mUploadProvider( 0 ), + mNewStuff( newStuff ), mType( type ) +{ + mProviderLoader = new ProviderLoader( mParentWidget ); + + mNewStuffList.setAutoDelete( true ); +} + +Engine::Engine( KNewStuff *newStuff, const QString &type, + const QString &providerList, QWidget *parentWidget ) : + mParentWidget( parentWidget ), + mDownloadDialog( 0 ), mUploadDialog( 0 ), + mProviderDialog( 0 ), mUploadProvider( 0 ), + mProviderList( providerList ), mNewStuff( newStuff ), + mType( type ) +{ + mProviderLoader = new ProviderLoader( mParentWidget ); + mNewStuffList.setAutoDelete( true ); +} + +Engine::~Engine() +{ + delete mProviderLoader; + + delete mUploadDialog; + delete mDownloadDialog; +} + +void Engine::download() +{ + kdDebug(5850) << "Engine::download()" << endl; + + connect( mProviderLoader, + SIGNAL( providersLoaded( Provider::List * ) ), + SLOT( getMetaInformation( Provider::List * ) ) ); + mProviderLoader->load( mType, mProviderList ); +} + +void Engine::getMetaInformation( Provider::List *providers ) +{ + mProviderLoader->disconnect(); + + mNewStuffJobData.clear(); + + if ( !mDownloadDialog ) { + mDownloadDialog = new DownloadDialog( this, mParentWidget ); + mDownloadDialog->show(); + } + mDownloadDialog->clear(); + + Provider *p; + for ( p = providers->first(); p; p = providers->next() ) { + if ( p->downloadUrl().isEmpty() ) continue; + + KIO::TransferJob *job = KIO::get( p->downloadUrl() ); + connect( job, SIGNAL( result( KIO::Job * ) ), + SLOT( slotNewStuffJobResult( KIO::Job * ) ) ); + connect( job, SIGNAL( data( KIO::Job *, const QByteArray & ) ), + SLOT( slotNewStuffJobData( KIO::Job *, const QByteArray & ) ) ); + + mNewStuffJobData.insert( job, "" ); + mProviderJobs[ job ] = p; + } +} + +void Engine::slotNewStuffJobData( KIO::Job *job, const QByteArray &data ) +{ + if ( data.isEmpty() ) return; + + kdDebug(5850) << "Engine:slotNewStuffJobData()" << endl; + + QCString str( data, data.size() + 1 ); + + mNewStuffJobData[ job ].append( QString::fromUtf8( str ) ); +} + +void Engine::slotNewStuffJobResult( KIO::Job *job ) +{ + if ( job->error() ) { + kdDebug(5850) << "Error downloading new stuff descriptions." << endl; + job->showErrorDialog( mParentWidget ); + } else { + QString knewstuffDoc = mNewStuffJobData[ job ]; + + kdDebug(5850) << "---START---" << endl << knewstuffDoc << "---END---" << endl; + + mDownloadDialog->addProvider( mProviderJobs[ job ] ); + + QDomDocument doc; + if ( !doc.setContent( knewstuffDoc ) ) { + kdDebug(5850) << "Error parsing knewstuff.xml." << endl; + return; + } else { + QDomElement knewstuff = doc.documentElement(); + + if ( knewstuff.isNull() ) { + kdDebug(5850) << "No document in knewstuffproviders.xml." << endl; + } else { + QDomNode p; + for ( p = knewstuff.firstChild(); !p.isNull(); p = p.nextSibling() ) { + QDomElement stuff = p.toElement(); + if ( stuff.tagName() != "stuff" ) continue; + if ( stuff.attribute("type", mType) != mType ) continue; + + Entry *entry = new Entry( stuff ); + mNewStuffList.append( entry ); + + mDownloadDialog->show(); + + mDownloadDialog->addEntry( entry ); + + kdDebug(5850) << "KNEWSTUFF: " << entry->name() << endl; + + kdDebug(5850) << " SUMMARY: " << entry->summary() << endl; + kdDebug(5850) << " VERSION: " << entry->version() << endl; + kdDebug(5850) << " RELEASEDATE: " << entry->releaseDate().toString() << endl; + kdDebug(5850) << " RATING: " << entry->rating() << endl; + + kdDebug(5850) << " LANGS: " << entry->langs().join(", ") << endl; + } + } + } + } + + mNewStuffJobData.remove( job ); + mProviderJobs.remove( job ); + + if ( mNewStuffJobData.count() == 0 ) { + mDownloadDialog->show(); + mDownloadDialog->raise(); + } +} + +void Engine::download( Entry *entry ) +{ + kdDebug(5850) << "Engine::download(entry)" << endl; + + KURL source = entry->payload(); + mDownloadDestination = mNewStuff->downloadDestination( entry ); + + if ( mDownloadDestination.isEmpty() ) { + kdDebug(5850) << "Empty downloadDestination. Cancelling download." << endl; + return; + } + + KURL destination = KURL( mDownloadDestination ); + + kdDebug(5850) << " SOURCE: " << source.url() << endl; + kdDebug(5850) << " DESTINATION: " << destination.url() << endl; + + KIO::FileCopyJob *job = KIO::file_copy( source, destination, -1, true ); + connect( job, SIGNAL( result( KIO::Job * ) ), + SLOT( slotDownloadJobResult( KIO::Job * ) ) ); +} + +void Engine::slotDownloadJobResult( KIO::Job *job ) +{ + if ( job->error() ) { + kdDebug(5850) << "Error downloading new stuff payload." << endl; + job->showErrorDialog( mParentWidget ); + return; + } + + if ( mNewStuff->install( mDownloadDestination ) ) { + if ( !mIgnoreInstallResult ) { + KMessageBox::information( mParentWidget, + i18n("Successfully installed hot new stuff.") ); + } + } else + if ( !mIgnoreInstallResult ){ + KMessageBox::error( mParentWidget, + i18n("Failed to install hot new stuff.") ); + } +} + +void Engine::upload(const QString &fileName, const QString &previewName ) +{ + mUploadFile = fileName; + mPreviewFile = previewName; + + connect( mProviderLoader, + SIGNAL( providersLoaded( Provider::List * ) ), + SLOT( selectUploadProvider( Provider::List * ) ) ); + mProviderLoader->load( mType ); +} + +void Engine::selectUploadProvider( Provider::List *providers ) +{ + kdDebug(5850) << "Engine:selectUploadProvider()" << endl; + + mProviderLoader->disconnect(); + + if ( !mProviderDialog ) { + mProviderDialog = new ProviderDialog( this, mParentWidget ); + } + + mProviderDialog->clear(); + + mProviderDialog->show(); + mProviderDialog->raise(); + + for( Provider *p = providers->first(); p; p = providers->next() ) { + mProviderDialog->addProvider( p ); + } +} + +void Engine::requestMetaInformation( Provider *provider ) +{ + mUploadProvider = provider; + + if ( !mUploadDialog ) { + mUploadDialog = new UploadDialog( this, mParentWidget ); + } + mUploadDialog->setPreviewFile( mPreviewFile ); + mUploadDialog->show(); + mUploadDialog->raise(); +} + +void Engine::upload( Entry *entry ) +{ + if ( mUploadFile.isNull()) { + mUploadFile = entry->fullName(); + mUploadFile = locateLocal( "data", QString(kapp->instanceName()) + "/upload/" + mUploadFile ); + + if ( !mNewStuff->createUploadFile( mUploadFile ) ) { + KMessageBox::error( mParentWidget, i18n("Unable to create file to upload.") ); + emit uploadFinished( false ); + return; + } + } + + QString lang = entry->langs().first(); + QFileInfo fi( mUploadFile ); + entry->setPayload( KURL::fromPathOrURL( fi.fileName() ), lang ); + + if ( !createMetaFile( entry ) ) { + emit uploadFinished( false ); + return; + } + + QString text = i18n("The files to be uploaded have been created at:\n"); + text.append( i18n("Data file: %1\n").arg( mUploadFile) ); + if (!mPreviewFile.isEmpty()) { + text.append( i18n("Preview image: %1\n").arg( mPreviewFile) ); + } + text.append( i18n("Content information: %1\n").arg( mUploadMetaFile) ); + text.append( i18n("Those files can now be uploaded.\n") ); + text.append( i18n("Beware that any people might have access to them at any time.") ); + + QString caption = i18n("Upload Files"); + + if ( mUploadProvider->noUpload() ) { + KURL noUploadUrl = mUploadProvider->noUploadUrl(); + if ( noUploadUrl.isEmpty() ) { + text.append( i18n("Please upload the files manually.") ); + KMessageBox::information( mParentWidget, text, caption ); + } else { + int result = KMessageBox::questionYesNo( mParentWidget, text, caption, + i18n("Upload Info"), + KStdGuiItem::close() ); + if ( result == KMessageBox::Yes ) { + kapp->invokeBrowser( noUploadUrl.url() ); + } + } + } else { + int result = KMessageBox::questionYesNo( mParentWidget, text, caption, + i18n("&Upload"), KStdGuiItem::cancel() ); + if ( result == KMessageBox::Yes ) { + KURL destination = mUploadProvider->uploadUrl(); + destination.setFileName( fi.fileName() ); + + KIO::FileCopyJob *job = KIO::file_copy( KURL::fromPathOrURL( mUploadFile ), destination ); + connect( job, SIGNAL( result( KIO::Job * ) ), + SLOT( slotUploadPayloadJobResult( KIO::Job * ) ) ); + } else { + emit uploadFinished( false ); + } + } +} + +bool Engine::createMetaFile( Entry *entry ) +{ + QDomDocument doc("knewstuff"); + doc.appendChild( doc.createProcessingInstruction( + "xml", "version=\"1.0\" encoding=\"UTF-8\"" ) ); + QDomElement de = doc.createElement("knewstuff"); + doc.appendChild( de ); + + entry->setType(type()); + de.appendChild( entry->createDomElement( doc, de ) ); + + kdDebug(5850) << "--DOM START--" << endl << doc.toString() + << "--DOM_END--" << endl; + + if ( mUploadMetaFile.isNull() ) { + mUploadMetaFile = entry->fullName() + ".meta"; + mUploadMetaFile = locateLocal( "data", QString(kapp->instanceName()) + "/upload/" + mUploadMetaFile ); + } + + QFile f( mUploadMetaFile ); + if ( !f.open( IO_WriteOnly ) ) { + mUploadMetaFile = QString::null; + return false; + } + + QTextStream ts( &f ); + ts.setEncoding( QTextStream::UnicodeUTF8 ); + ts << doc.toString(); + + f.close(); + + return true; +} + +void Engine::slotUploadPayloadJobResult( KIO::Job *job ) +{ + if ( job->error() ) { + kdDebug(5850) << "Error uploading new stuff payload." << endl; + job->showErrorDialog( mParentWidget ); + emit uploadFinished( false ); + return; + } + + if (mPreviewFile.isEmpty()) { + slotUploadPreviewJobResult(job); + return; + } + + QFileInfo fi( mPreviewFile ); + + KURL previewDestination = mUploadProvider->uploadUrl(); + previewDestination.setFileName( fi.fileName() ); + + KIO::FileCopyJob *newJob = KIO::file_copy( KURL::fromPathOrURL( mPreviewFile ), previewDestination ); + connect( newJob, SIGNAL( result( KIO::Job * ) ), + SLOT( slotUploadPreviewJobResult( KIO::Job * ) ) ); +} + +void Engine::slotUploadPreviewJobResult( KIO::Job *job ) +{ + if ( job->error() ) { + kdDebug(5850) << "Error uploading new stuff preview." << endl; + job->showErrorDialog( mParentWidget ); + emit uploadFinished( true ); + return; + } + + QFileInfo fi( mUploadMetaFile ); + + KURL metaDestination = mUploadProvider->uploadUrl(); + metaDestination.setFileName( fi.fileName() ); + + KIO::FileCopyJob *newJob = KIO::file_copy( KURL::fromPathOrURL( mUploadMetaFile ), metaDestination ); + connect( newJob, SIGNAL( result( KIO::Job * ) ), + SLOT( slotUploadMetaJobResult( KIO::Job * ) ) ); +} + +void Engine::slotUploadMetaJobResult( KIO::Job *job ) +{ + mUploadMetaFile = QString::null; + if ( job->error() ) { + kdDebug(5850) << "Error uploading new stuff metadata." << endl; + job->showErrorDialog( mParentWidget ); + emit uploadFinished( false ); + return; + } + + KMessageBox::information( mParentWidget, + i18n("Successfully uploaded new stuff.") ); + emit uploadFinished( true ); +} + +void Engine::ignoreInstallResult(bool ignore) +{ + mIgnoreInstallResult = ignore; +} diff --git a/lib/compatibility/knewstuff/engine.h b/lib/compatibility/knewstuff/engine.h new file mode 100644 index 00000000..dd3f2b30 --- /dev/null +++ b/lib/compatibility/knewstuff/engine.h @@ -0,0 +1,189 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <schumacher@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. +*/ +#ifndef KNEWSTUFF_ENGINE_H +#define KNEWSTUFF_ENGINE_H + +#include <qmap.h> +#include <qobject.h> +#include <qstring.h> + +#include "entry.h" +#include "provider.h" + +namespace KIO { class Job; } + +class KNewStuff; + +namespace KNS { + +class DownloadDialog; +class UploadDialog; +class ProviderDialog; + +/** + * @short Central class combining all possible KNewStuff operations. + * + * In most cases, Engine objects are built and used internally. + * Using this class explicitely does however give fine-grained control about the + * upload and download operations. + * + * @author Cornelius Schumacher (schumacher@kde.org) + * \par Maintainer: + * Josef Spillner (spillner@kde.org) + */ +class Engine : public QObject +{ + Q_OBJECT + public: + /** + Constructor. + + @param newStuff a KNewStuff object + @param type the Hotstuff data type such as "korganizer/calendar" + @param parentWidget the parent window + */ + Engine( KNewStuff *newStuff, const QString &type, QWidget *parentWidget = 0 ); + /** + Constructor. + + @param newStuff a KNewStuff object + @param type the Hotstuff data type such as "korganizer/calendar" + @param providerList the URL of the provider list + @param parentWidget the parent window + */ + Engine( KNewStuff *newStuff, const QString &type, const QString &providerList, QWidget *parentWidget = 0 ); + + /** + Destructor. + */ + virtual ~Engine(); + + /** + Returns the previously set data type. + + @return the Hotstuff data type + */ + QString type() const { return mType; } + + /** + Returns the previously set parent widget. + + @return parent widget + */ + QWidget *parentWidget() const { return mParentWidget; } + + /** + Initiates the download process, retrieving provider lists and invoking + the download dialog. + */ + void download(); + + /** + Initiates the upload process, invoking the provider selection dialog + and the file upload dialog. + + @param fileName name of the payload data file + @param previewName name of the preview image file + */ + void upload( const QString &fileName = QString::null, const QString &previewName = QString::null ); + + /** + Downloads the specified data file. + + @param entry the Hotstuff data object to be downloaded + */ + void download( Entry *entry ); + + /** + Asynchronous lookup of provider information such as upload and + download locations, icon etc. + + @param provider the Hotstuff provider to request information from + */ + void requestMetaInformation( Provider *provider ); + + /** + Uploads the specified data file to the provider-dependent location. + + @param entry the Hotstuff data object to be uploaded + */ + void upload( Entry *entry ); + + /** + Ignores the return value of the install method. Used internally to + avoid showing of the success/failure dialog when installation is done + in another place, like in @ref KNewStuffSecure + */ + void ignoreInstallResult(bool ignore); + + signals: + /** Emitted when the upload has finished. + @param result indicates the success/failure of the upload + */ + void uploadFinished( bool result ); + protected slots: + void getMetaInformation( Provider::List *providers ); + void selectUploadProvider( Provider::List *providers ); + + void slotNewStuffJobData( KIO::Job *job, const QByteArray &data ); + void slotNewStuffJobResult( KIO::Job *job ); + + void slotDownloadJobResult( KIO::Job *job ); + + void slotUploadPayloadJobResult( KIO::Job *job ); + void slotUploadPreviewJobResult (KIO::Job *job ); + void slotUploadMetaJobResult( KIO::Job *job ); + + protected: + bool createMetaFile( Entry * ); + + private: + QWidget *mParentWidget; + + ProviderLoader *mProviderLoader; + + QMap<KIO::Job *,QString> mNewStuffJobData; + QMap<KIO::Job *,Provider *> mProviderJobs; + + QPtrList<Entry> mNewStuffList; + + DownloadDialog *mDownloadDialog; + UploadDialog *mUploadDialog; + ProviderDialog *mProviderDialog; + + QString mDownloadDestination; + + Provider *mUploadProvider; + + QString mUploadMetaFile; + QString mUploadFile; + QString mPreviewFile; + QString mProviderList; + + KNewStuff *mNewStuff; + + QString mType; + + bool mIgnoreInstallResult; +}; + +} + +#endif diff --git a/lib/compatibility/knewstuff/entry.cpp b/lib/compatibility/knewstuff/entry.cpp new file mode 100644 index 00000000..1d4f7e72 --- /dev/null +++ b/lib/compatibility/knewstuff/entry.cpp @@ -0,0 +1,294 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <schumacher@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 "entry.h" + +#include <kglobal.h> +#include <klocale.h> + +using namespace KNS; + +Entry::Entry() : + mRelease( 0 ), mReleaseDate( QDate::currentDate() ), mRating( 0 ), + mDownloads( 0 ) +{ +} + +Entry::Entry( const QDomElement &e ) +{ + parseDomElement( e ); +} + +Entry::~Entry() +{ +} + + +void Entry::setName( const QString &name ) +{ + mName = name; +} + +QString Entry::name() const +{ + return mName; +} + + +void Entry::setType( const QString &type ) +{ + mType = type; +} + +QString Entry::type() const +{ + return mType; +} + + +void Entry::setAuthor( const QString &author ) +{ + mAuthor = author; +} + +QString Entry::author() const +{ + return mAuthor; +} + + +void Entry::setLicence( const QString &license ) +{ + mLicence = license; +} + +QString Entry::license() const +{ + return mLicence; +} + + +void Entry::setSummary( const QString &text, const QString &lang ) +{ + mSummaryMap.insert( lang, text ); + + if ( mLangs.find( lang ) == mLangs.end() ) mLangs.append( lang ); +} + +QString Entry::summary( const QString &lang ) const +{ + if ( mSummaryMap.isEmpty() ) return QString::null; + + if ( !mSummaryMap[ lang ].isEmpty() ) return mSummaryMap[ lang ]; + else { + QStringList langs = KGlobal::locale()->languageList(); + for(QStringList::Iterator it = langs.begin(); it != langs.end(); ++it) + if( !mSummaryMap[ *it ].isEmpty() ) return mSummaryMap[ *it ]; + } + if ( !mSummaryMap[ QString::null ].isEmpty() ) return mSummaryMap[ QString::null ]; + else return *(mSummaryMap.begin()); +} + + +void Entry::setVersion( const QString &version ) +{ + mVersion = version; +} + +QString Entry::version() const +{ + return mVersion; +} + + +void Entry::setRelease( int release ) +{ + mRelease = release; +} + +int Entry::release() const +{ + return mRelease; +} + + +void Entry::setReleaseDate( const QDate &d ) +{ + mReleaseDate = d; +} + +QDate Entry::releaseDate() const +{ + return mReleaseDate; +} + + +void Entry::setPayload( const KURL &url, const QString &lang ) +{ + mPayloadMap.insert( lang, url ); + + if ( mLangs.find( lang ) == mLangs.end() ) mLangs.append( lang ); +} + +KURL Entry::payload( const QString &lang ) const +{ + KURL payload = mPayloadMap[ lang ]; + if ( payload.isEmpty() ) { + QStringList langs = KGlobal::locale()->languageList(); + for(QStringList::Iterator it = langs.begin(); it != langs.end(); ++it) + if( !mPayloadMap[ *it ].isEmpty() ) return mPayloadMap[ *it ]; + } + if ( payload.isEmpty() ) payload = mPayloadMap [ QString::null ]; + if ( payload.isEmpty() && !mPayloadMap.isEmpty() ) { + payload = *(mPayloadMap.begin()); + } + return payload; +} + + +void Entry::setPreview( const KURL &url, const QString &lang ) +{ + mPreviewMap.insert( lang, url ); + + if ( mLangs.find( lang ) == mLangs.end() ) mLangs.append( lang ); +} + +KURL Entry::preview( const QString &lang ) const +{ + KURL preview = mPreviewMap[ lang ]; + if ( preview.isEmpty() ) { + QStringList langs = KGlobal::locale()->languageList(); + for(QStringList::Iterator it = langs.begin(); it != langs.end(); ++it) + if( !mPreviewMap[ *it ].isEmpty() ) return mPreviewMap[ *it ]; + } + if ( preview.isEmpty() ) preview = mPreviewMap [ QString::null ]; + if ( preview.isEmpty() && !mPreviewMap.isEmpty() ) { + preview = *(mPreviewMap.begin()); + } + return preview; +} + + +void Entry::setRating( int rating ) +{ + mRating = rating; +} + +int Entry::rating() +{ + return mRating; +} + + +void Entry::setDownloads( int downloads ) +{ + mDownloads = downloads; +} + +int Entry::downloads() +{ + return mDownloads; +} + +QString Entry::fullName() +{ + return name() + "-" + version() + "-" + QString::number( release() ); +} + +QStringList Entry::langs() +{ + return mLangs; +} + +void Entry::parseDomElement( const QDomElement &element ) +{ + if ( element.tagName() != "stuff" ) return; + mType = element.attribute("type"); + + QDomNode n; + for( n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) { + QDomElement e = n.toElement(); + if ( e.tagName() == "name" ) setName( e.text().stripWhiteSpace() ); + if ( e.tagName() == "author" ) setAuthor( e.text().stripWhiteSpace() ); + if ( e.tagName() == "licence" ) setLicence( e.text().stripWhiteSpace() ); + if ( e.tagName() == "summary" ) { + QString lang = e.attribute( "lang" ); + setSummary( e.text().stripWhiteSpace(), lang ); + } + if ( e.tagName() == "version" ) setVersion( e.text().stripWhiteSpace() ); + if ( e.tagName() == "release" ) setRelease( e.text().toInt() ); + if ( e.tagName() == "releasedate" ) { + QDate date = QDate::fromString( e.text().stripWhiteSpace(), Qt::ISODate ); + setReleaseDate( date ); + } + if ( e.tagName() == "preview" ) { + QString lang = e.attribute( "lang" ); + setPreview( KURL( e.text().stripWhiteSpace() ), lang ); + } + if ( e.tagName() == "payload" ) { + QString lang = e.attribute( "lang" ); + setPayload( KURL( e.text().stripWhiteSpace() ), lang ); + } + if ( e.tagName() == "rating" ) setRating( e.text().toInt() ); + if ( e.tagName() == "downloads" ) setDownloads( e.text().toInt() ); + } +} + +QDomElement Entry::createDomElement( QDomDocument &doc, + QDomElement &parent ) +{ + QDomElement entry = doc.createElement( "stuff" ); + entry.setAttribute("type", mType); + parent.appendChild( entry ); + + addElement( doc, entry, "name", name() ); + addElement( doc, entry, "author", author() ); + addElement( doc, entry, "licence", license() ); + addElement( doc, entry, "version", version() ); + addElement( doc, entry, "release", QString::number( release() ) ); + addElement( doc, entry, "rating", QString::number( rating() ) ); + addElement( doc, entry, "downloads", QString::number( downloads() ) ); + + addElement( doc, entry, "releasedate", + releaseDate().toString( Qt::ISODate ) ); + + QStringList ls = langs(); + QStringList::ConstIterator it; + for( it = ls.begin(); it != ls.end(); ++it ) { + QDomElement e = addElement( doc, entry, "summary", summary( *it ) ); + e.setAttribute( "lang", *it ); + e = addElement( doc, entry, "preview", preview( *it ).url() ); + e.setAttribute( "lang", *it ); + e = addElement( doc, entry, "payload", payload( *it ).url() ); + e.setAttribute( "lang", *it ); + } + + return entry; +} + +QDomElement Entry::addElement( QDomDocument &doc, QDomElement &parent, + const QString &tag, const QString &value ) +{ + QDomElement n = doc.createElement( tag ); + n.appendChild( doc.createTextNode( value ) ); + parent.appendChild( n ); + + return n; +} diff --git a/lib/compatibility/knewstuff/entry.h b/lib/compatibility/knewstuff/entry.h new file mode 100644 index 00000000..3a16964d --- /dev/null +++ b/lib/compatibility/knewstuff/entry.h @@ -0,0 +1,257 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <schumacher@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. +*/ +#ifndef KNEWSTUFF_ENTRY_H +#define KNEWSTUFF_ENTRY_H + +#include <qdatetime.h> +#include <qdom.h> +#include <qmap.h> +#include <qstring.h> +#include <qstringlist.h> + +#include <kurl.h> + +namespace KNS { + +/** + * @short KNewStuff data entry container. + * + * This class provides accessor methods to the data objects + * as used by KNewStuff. + * It should probably not be used directly by the application. + * + * @author Cornelius Schumacher (schumacher@kde.org) + * \par Maintainer: + * Josef Spillner (spillner@kde.org) + */ +class KDE_EXPORT Entry +{ + public: + Entry(); + /** + * Constructor. + */ + Entry( const QDomElement & ); + + /** + * Destructor. + */ + ~Entry(); + + /** + * Sets the (unique) name for this data object. + */ + void setName( const QString & ); + + /** + * Retrieve the name of the data object. + * + * @return object name + */ + QString name() const; + + /** + * Sets the application type, e.g. 'kdesktop/wallpaper'. + */ + void setType( const QString & ); + + /** + * Retrieve the type of the data object. + * + * @return object type + */ + QString type() const; + + /** + * Sets the full name of the object's author. + */ + void setAuthor( const QString & ); + + /** + * Retrieve the author's name of the object. + * + * @return object author + */ + QString author() const; + + /** + * Sets the license (abbreviation) applicable to the object. + */ + void setLicence( const QString & ); + + /** + * Retrieve the license name of the object. + * + * @return object license + */ + QString license() const; + + /** + * Sets a short description on what the object is all about. + */ + void setSummary( const QString &, const QString &lang = QString::null ); + + /** + * Retrieve a short description about the object. + * + * @param lang preferred language, or QString::null for KDE default + * @return object description + */ + QString summary( const QString &lang = QString::null ) const; + + /** + * Sets the version number. + */ + void setVersion( const QString & ); + + /** + * Retrieve the version string of the object. + * + * @return object version + */ + QString version() const; + + /** + * Sets the release number, which is increased for feature-equal objects + * with the same version number, but slightly updated contents. + */ + void setRelease( int ); + + /** + * Retrieve the release number of the object + * + * @return object release + */ + int release() const; + + /** + * Sets the release date. + */ + void setReleaseDate( const QDate & ); + + /** + * Retrieve the date of the object's publication. + * + * @return object release date + */ + QDate releaseDate() const; + + /** + * Sets the object's file. + */ + void setPayload( const KURL &, const QString &lang = QString::null ); + + /** + * Retrieve the file name of the object. + * + * @param lang preferred language, or QString::null for KDE default + * @return object filename + */ + KURL payload( const QString &lang = QString::null ) const; + + /** + * Sets the object's preview file, if available. This should be a + * picture file. + */ + void setPreview( const KURL &, const QString &lang = QString::null ); + + /** + * Retrieve the file name of an image containing a preview of the object. + * + * @param lang preferred language, or QString::null for KDE default + * @return object preview filename + */ + KURL preview( const QString &lang = QString::null ) const; + + /** + * Sets the rating between 0 (worst) and 10 (best). + * + * @internal + */ + void setRating( int ); + + /** + * Retrieve the rating for the object, which has been determined by its + * users and thus might change over time. + * + * @return object rating + */ + int rating(); + + /** + * Sets the number of downloads. + * + * @internal + */ + void setDownloads( int ); + + /** + * Retrieve the download count for the object, which has been determined + * by its hosting sites and thus might change over time. + * + * @return object download count + */ + int downloads(); + + /** + * Return the full name for the meta information. It is constructed as + * name-version-release. + */ + QString fullName(); + + /** + * Return the list of languages this object supports. + */ + QStringList langs(); + + /** + * @internal + */ + void parseDomElement( const QDomElement & ); + + /** + * @internal + */ + QDomElement createDomElement( QDomDocument &, QDomElement &parent ); + + protected: + QDomElement addElement( QDomDocument &doc, QDomElement &parent, + const QString &tag, const QString &value ); + + private: + QString mName; + QString mType; + QString mAuthor; + QString mLicence; + QMap<QString,QString> mSummaryMap; + QString mVersion; + int mRelease; + QDate mReleaseDate; + QMap<QString,KURL> mPayloadMap; + QMap<QString,KURL> mPreviewMap; + int mRating; + int mDownloads; + + QStringList mLangs; +}; + +} + +#endif diff --git a/lib/compatibility/knewstuff/knewstuff.cpp b/lib/compatibility/knewstuff/knewstuff.cpp new file mode 100644 index 00000000..5387e647 --- /dev/null +++ b/lib/compatibility/knewstuff/knewstuff.cpp @@ -0,0 +1,86 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <schumacher@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 <kaction.h> +#include <kapplication.h> +#include <kdebug.h> +#include <klocale.h> +#include <kstandarddirs.h> + +#include "engine.h" + +#include "knewstuff.h" + +using namespace KNS; + +KAction* KNS::standardAction(const QString& what, + const QObject *recvr, + const char *slot, KActionCollection* parent, + const char *name) +{ + return new KAction(i18n("Download New %1").arg(what), "knewstuff", + 0, recvr, slot, parent, name); +} + +KNewStuff::KNewStuff( const QString &type, QWidget *parentWidget ) +{ + mEngine = new Engine( this, type, parentWidget ); +} + +KNewStuff::KNewStuff( const QString &type, const QString &providerList, QWidget *parentWidget ) +{ + mEngine = new Engine( this, type, providerList, parentWidget ); +} + +QString KNewStuff::type() const +{ + return mEngine->type(); +} + +QWidget *KNewStuff::parentWidget() const +{ + return mEngine->parentWidget(); +} + +KNewStuff::~KNewStuff() +{ + delete mEngine; +} + +void KNewStuff::download() +{ + mEngine->download(); +} + +QString KNewStuff::downloadDestination( Entry * ) +{ + return KGlobal::dirs()->saveLocation( "tmp" ) + + KApplication::randomString( 10 ); +} + +void KNewStuff::upload() +{ + mEngine->upload(); +} + +void KNewStuff::upload( const QString &fileName, const QString previewName ) +{ + mEngine->upload(fileName, previewName); +} diff --git a/lib/compatibility/knewstuff/knewstuff.h b/lib/compatibility/knewstuff/knewstuff.h new file mode 100644 index 00000000..9d2d10ed --- /dev/null +++ b/lib/compatibility/knewstuff/knewstuff.h @@ -0,0 +1,161 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <schumacher@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. +*/ +#ifndef KNEWSTUFF_H +#define KNEWSTUFF_H + +#include <qstring.h> + +#include <kdemacros.h> + +class QObject; +class QWidget; +class KAction; +class KActionCollection; + +namespace KNS { +class Engine; +class Entry; + +KAction* standardAction(const QString& what, + const QObject *recvr, + const char *slot, + KActionCollection* parent, + const char *name = 0); +} + +/** + * @short This class provides the functionality to download and upload "new stuff". + * + * Applications have to subclass KNewStuff, implement the pure virtual functions + * and link to against libknewstuff. + * + * By calling download() the download process is started which means that a list + * of "providers" is fetched from a "master server", information about new stuff + * is collected from the providers and presented to the user. Selected entries + * get downloaded and installed to the application. The required functions to + * install new stuff are provided by implementing install(). The location where + * the downloaded files are stored can be customized by reimplementing + * downloadDestination(). + * + * By calling upload() the upload process is started which means the user has to + * select a provider from the list fetched from the master server and to put in + * information about the entry to be uploaded. Then the file to be uploaded is + * fetched from the application by calling createUploadFile() and transfered to + * the upload destination specified in the provider list. + * + * @author Cornelius Schumacher (schumacher@kde.org) + * \par Maintainer: + * Josef Spillner (spillner@kde.org) + * + * @since 3.3 + */ +class KDE_EXPORT KNewStuff +{ + public: + /** + Constructor. + + @param type type of data to be handled, should be something like + korganizer/calendar, kword/template, kdesktop/wallpaper + @param parentWidget parent widget of dialogs opened by the KNewStuff + engine + */ + KNewStuff( const QString &type, QWidget *parentWidget = 0 ); + + /** + Constructor. + + @param type type of data to be handled, should be something like + korganizer/calendar, kword/template, kdesktop/wallpaper + @param providerList the URL of the provider list + @param parentWidget parent widget of dialogs opened by the KNewStuff + engine + */ + KNewStuff( const QString &type, const QString &providerList, QWidget *parentWidget = 0 ); + virtual ~KNewStuff(); + + /** + Return type of data. + */ + QString type() const; + + /** + Return parent widget. + */ + QWidget *parentWidget() const; + + /** + Start download process. + */ + void download(); + + /** + Start upload process. + */ + void upload(); + + /** + Upload with pre-defined files. + */ + void upload( const QString &fileName, const QString previewName ); + + /** + Install file to application. The given fileName points to the file + downloaded by the KNewStuff engine. This is a temporary file by default. + The application can do whatever is needed to handle the information + contained in the file. + + The function returns true, when the installation + was successful and false if were errors. + + @param fileName name of downloaded file + */ + virtual bool install( const QString &fileName ) = 0; + /** + Create a file to be uploaded to a "new stuff provider" and return the + filename. The format of the file is application specific. The only + constraint is that the corresponding install() implementation is able to + use the file. + + @param fileName name of the file to be written + @return @c true on success, @c false on error. + */ + virtual bool createUploadFile( const QString &fileName ) = 0; + + /** + Return a filename which should be used as destination for downloading the + specified new stuff entry. Reimplement this function, if you don't want + the new stuff to be downloaded to a temporary file. + */ + virtual QString downloadDestination( KNS::Entry *entry ); + + + protected: + /** + Get the pointer to the engine. Needed by subclasses to access the KNS::Engine object. + */ + KNS::Engine *engine() { return mEngine; } + + + private: + KNS::Engine *mEngine; +}; + +#endif diff --git a/lib/compatibility/knewstuff/knewstuffgeneric.cpp b/lib/compatibility/knewstuff/knewstuffgeneric.cpp new file mode 100644 index 00000000..22673dac --- /dev/null +++ b/lib/compatibility/knewstuff/knewstuffgeneric.cpp @@ -0,0 +1,140 @@ +/* + This file is part of KDE. + + Copyright (c) 2003 Cornelius Schumacher <schumacher@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 <qfile.h> +#include <qtextstream.h> +#include <qdir.h> + +#include <kdebug.h> +#include <klocale.h> +#include <kprocess.h> +#include <kconfig.h> +#include <kstandarddirs.h> +#include <kmessagebox.h> +#include <ktar.h> + +#include "entry.h" + +#include "knewstuffgeneric.h" + +using namespace std; + +KNewStuffGeneric::KNewStuffGeneric( const QString &type, QWidget *parent ) + : KNewStuff( type, parent ) +{ + mConfig = KGlobal::config(); +} + +KNewStuffGeneric::~KNewStuffGeneric() +{ +} + +bool KNewStuffGeneric::install( const QString &fileName ) +{ + kdDebug(5850) << "KNewStuffGeneric::install(): " << fileName << endl; + QStringList list, list2; + + mConfig->setGroup("KNewStuff"); + + QString uncompress = mConfig->readEntry( "Uncompress" ); + if ( !uncompress.isEmpty() ) { + kdDebug(5850) << "Uncompression method: " << uncompress << endl; + KTar tar(fileName, uncompress); + tar.open(IO_ReadOnly); + const KArchiveDirectory *dir = tar.directory(); + dir->copyTo(destinationPath(0)); + tar.close(); + QFile::remove(fileName); + } + + QString cmd = mConfig->readEntry( "InstallationCommand" ); + if ( !cmd.isEmpty() ) { + kdDebug(5850) << "InstallationCommand: " << cmd << endl; + list = QStringList::split( " ", cmd ); + for ( QStringList::iterator it = list.begin(); it != list.end(); ++it) { + list2 << (*it).replace("%f", fileName); + } + KProcess proc; + proc << list2; + proc.start( KProcess::Block ); + } + + return true; +} + +bool KNewStuffGeneric::createUploadFile( const QString & /*fileName*/ ) +{ + return false; +} + +QString KNewStuffGeneric::destinationPath( KNS::Entry *entry ) +{ + QString path, file, target; + + mConfig->setGroup("KNewStuff"); + + if( entry ) target = entry->fullName(); + else target = "/"; + QString res = mConfig->readEntry( "StandardResource" ); + if ( res.isEmpty() ) + { + target = mConfig->readEntry("TargetDir"); + if ( !target.isEmpty()) + { + res = "data"; + if ( entry ) target.append("/" + entry->fullName()); + else target.append("/"); + } + } + if ( res.isEmpty() ) + { + path = mConfig->readEntry( "InstallPath" ); + } + if ( res.isEmpty() && path.isEmpty() ) + { + if ( !entry ) return QString::null; + else return KNewStuff::downloadDestination( entry ); + } + + if ( !path.isEmpty() ) + { + file = QDir::home().path() + "/" + path + "/"; + if ( entry ) file += entry->fullName(); + } + else file = locateLocal( res.utf8() , target ); + + return file; +} + +QString KNewStuffGeneric::downloadDestination( KNS::Entry *entry ) +{ + QString file = destinationPath(entry); + + if ( KStandardDirs::exists( file ) ) { + int result = KMessageBox::warningContinueCancel( parentWidget(), + i18n("The file '%1' already exists. Do you want to override it?") + .arg( file ), + QString::null, i18n("Overwrite") ); + if ( result == KMessageBox::Cancel ) return QString::null; + } + + return file; +} diff --git a/lib/compatibility/knewstuff/knewstuffgeneric.h b/lib/compatibility/knewstuff/knewstuffgeneric.h new file mode 100644 index 00000000..5443e24a --- /dev/null +++ b/lib/compatibility/knewstuff/knewstuffgeneric.h @@ -0,0 +1,86 @@ +/* + This file is part of KDE. + + Copyright (c) 2003 Cornelius Schumacher <schumacher@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. +*/ +#ifndef KNEWSTUFFGENERIC_H +#define KNEWSTUFFGENERIC_H + +#include "knewstuff.h" + +class KConfig; + +/** + * @short Basic KNewStuff class with predefined actions. + * + * This class is used for data uploads and installation. + * \code + * QString payload, preview; + * KNewStuffGeneric *ns = new KNewStuffGeneric("kamikaze/level", this); + * ns->upload(payload, preview); + * \endcode + * + * @author Cornelius Schumacher (schumacher@kde.org) + * \par Maintainer: + * Josef Spillner (spillner@kde.org) + */ +class KDE_EXPORT KNewStuffGeneric : public KNewStuff +{ + public: + /** + Constructor. + + @param type a Hotstuff data type such as "korganizer/calendar" + @param parent the parent window. + */ + KNewStuffGeneric( const QString &type, QWidget *parent = 0 ); + ~KNewStuffGeneric(); + + /** + Installs a downloaded file according to the application's configuration. + + @param fileName filename of the donwloaded file + @return @c true in case of installation success, @c false otherwise + */ + bool install( const QString &fileName ); + + /** + Creates a file suitable for upload. + Note that this method always fails, since using KNewStuffGeneric + means that the provided file must already be in a usable format. + + @param fileName the name of the file to upload after its creation + @return @c true in case of creation success, @c false otherwise + */ + bool createUploadFile( const QString &fileName ); + + /** + Queries the preferred destination file for a download. + + @param entry a Hotstuff data entry + @return destination filename, or 0 to return directory only + */ + QString downloadDestination( KNS::Entry *entry ); + + private: + QString destinationPath( KNS::Entry *entry ); + + KConfig *mConfig; +}; + +#endif diff --git a/lib/compatibility/knewstuff/knewstuffsecure.cpp b/lib/compatibility/knewstuff/knewstuffsecure.cpp new file mode 100644 index 00000000..270d9449 --- /dev/null +++ b/lib/compatibility/knewstuff/knewstuffsecure.cpp @@ -0,0 +1,240 @@ +/*************************************************************************** + knewstuffsecure.cpp - description + ------------------- + begin : Tue Jun 22 12:19:55 2004 + copyright : (C) 2004, 2005 by Andras Mantia <amantia@kde.org> + ***************************************************************************/ + +/*************************************************************************** + * * + * This program 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; version 2 of the License. * + * * + ***************************************************************************/ +//qt includes +#include <qfileinfo.h> + +//kde includes +#include <kconfig.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kio/netaccess.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <ktar.h> +#include <ktempdir.h> + +//app includes +#include "engine.h" +#include "knewstuffsecure.h" +#include "security.h" + +using namespace KNS; + +KNewStuffSecure::KNewStuffSecure(const QString &type, QWidget *parentWidget) + : KNewStuff(type, parentWidget) +{ + m_tempDir = 0L; + connect(engine(), SIGNAL(uploadFinished(bool)), SLOT(slotUploadFinished(bool))); +} + + +KNewStuffSecure::~KNewStuffSecure() +{ + removeTempDirectory(); +} + +bool KNewStuffSecure::install(const QString &fileName) +{ + bool ok = true; + + removeTempDirectory(); + m_tempDir = new KTempDir(); + m_tempDir->setAutoDelete(true); + KTar tar(fileName, "application/x-gzip"); + if (tar.open(IO_ReadOnly)) + { + const KArchiveDirectory *directory = tar.directory(); + directory->copyTo(m_tempDir->name(), true); + m_tarName = ""; + QStringList entries = directory->entries(); + for (QStringList::Iterator it = entries.begin(); it != entries.end(); ++it) + { + if (*it != "signature" && *it != "md5sum") + { + m_tarName = *it; + break; + } + } + tar.close(); + if (m_tarName.isEmpty()) + ok = false; + else + { + m_tarName.prepend(m_tempDir->name()); + connect(Security::ref(), SIGNAL(validityResult(int)), this, SLOT(slotValidated(int))); + Security::ref()->checkValidity(m_tarName); + } + } else + ok = false; + if (!ok) + KMessageBox::error(parentWidget(), i18n("There was an error with the downloaded resource tarball file. Possible causes are damaged archive or invalid directory structure in the archive."), i18n("Resource Installation Error")); + return ok; +} + +void KNewStuffSecure::slotValidated(int result) +{ + QString errorString; + QString signatureStr; + bool valid = true; + if (result == -1) + { + errorString ="<br>- " + i18n("No keys were found."); + valid = false; + } else + if (result == 0) + { + errorString ="<br>- " + i18n("The validation failed for unknown reason."); + valid = false; + } else + { + KeyStruct key = Security::ref()->signatureKey(); + if (!(result & Security::MD5_OK )) + { + errorString = "<br>- " + i18n("The MD5SUM check failed, the archive might be broken."); + valid = false; + } + if (result & Security::SIGNED_BAD) + { + errorString += "<br>- " + i18n("The signature is bad, the archive might be broken or altered."); + valid = false; + } + if (result & Security::SIGNED_OK) + { + if (result & Security::TRUSTED) + { + kdDebug() << "Signed and trusted " << endl; + } else + { + errorString += "<br>- " + i18n("The signature is valid, but untrusted."); + valid = false; + } + } + if (result & Security::UNKNOWN) + { + errorString += "<br>- " + i18n("The signature is unknown."); + valid = false; + } else + { + signatureStr = i18n("The resource was signed with key <i>0x%1</i>, belonging to <i>%2 <%3></i>.").arg(key.id.right(8)).arg(key.name).arg(key.mail); + } + } + if (!valid) + { + signatureStr.prepend( "<br>"); + if (KMessageBox::warningContinueCancel(parentWidget(), i18n("<qt>There is a problem with the resource file you have downloaded. The errors are :<b>%1</b><br>%2<br><br>Installation of the resource is <b>not recommended</b>.<br><br>Do you want to proceed with the installation?</qt>").arg(errorString).arg(signatureStr), i18n("Problematic Resource File")) == KMessageBox::Continue) + valid = true; + } else + KMessageBox::information(parentWidget(), i18n("<qt>%1<br><br>Press OK to install it.</qt>").arg(signatureStr), i18n("Valid Resource"), "Show Valid Signature Information"); + if (valid) + { + installResource(); + emit installFinished(); + } else + { + KConfig *cfg = KGlobal::config(); + cfg->deleteGroup("KNewStuffStatus"); + cfg->setGroup("KNewStuffStatus"); + for (QMap<QString, QString>::ConstIterator it = m_installedResources.constBegin(); it != m_installedResources.constEnd(); ++it) + { + cfg->writeEntry(it.key(), it.data()); + } + cfg->sync(); + } + removeTempDirectory(); + disconnect(Security::ref(), SIGNAL(validityResult(int)), this, SLOT(slotValidated(int))); +} + +void KNewStuffSecure::downloadResource() +{ + KConfig *cfg = KGlobal::config(); + m_installedResources = cfg->entryMap("KNewStuffStatus"); + engine()->ignoreInstallResult(true); + KNewStuff::download(); +} + +bool KNewStuffSecure::createUploadFile(const QString &fileName) +{ + Q_UNUSED(fileName); + return true; +} + +void KNewStuffSecure::uploadResource(const QString& fileName) +{ + connect(Security::ref(), SIGNAL(fileSigned(int)), this, SLOT(slotFileSigned(int))); + removeTempDirectory(); + m_tempDir = new KTempDir(); + m_tempDir->setAutoDelete(true); + QFileInfo f(fileName); + m_signedFileName = m_tempDir->name() + "/" + f.fileName(); + KIO::NetAccess::file_copy(KURL::fromPathOrURL(fileName), KURL::fromPathOrURL(m_signedFileName), -1, true); + Security::ref()->signFile(m_signedFileName); +} + +void KNewStuffSecure::slotFileSigned(int result) +{ + if (result == 0) + { + KMessageBox::error(parentWidget(), i18n("The signing failed for unknown reason.")); + } else + { + if (result & Security::BAD_PASSPHRASE) + { + if (KMessageBox::warningContinueCancel(parentWidget(), i18n("There are no keys usable for signing or you did not entered the correct passphrase.\nProceed without signing the resource?")) == KMessageBox::Cancel) + { + disconnect(Security::ref(), SIGNAL(fileSigned(int)), this, SLOT(slotFileSigned(int))); + removeTempDirectory(); + return; + } + } + KTar tar(m_signedFileName + ".signed", "application/x-gzip"); + tar.open(IO_WriteOnly); + QStringList files; + files << m_signedFileName; + files << m_tempDir->name() + "/md5sum"; + files << m_tempDir->name() + "/signature"; + + for (QStringList::Iterator it_f = files.begin(); it_f != files.end(); ++it_f) + { + QFile file(*it_f); + file.open(IO_ReadOnly); + QByteArray bArray = file.readAll(); + tar.writeFile(QFileInfo(file).fileName(), "user", "group", bArray.size(), bArray.data()); + file.close(); + } + tar.close(); + KIO::NetAccess::file_move(KURL::fromPathOrURL(m_signedFileName + ".signed"), KURL::fromPathOrURL(m_signedFileName), -1, true); + KNewStuff::upload(m_signedFileName, QString::null); + disconnect(Security::ref(), SIGNAL(fileSigned(int)), this, SLOT(slotFileSigned(int))); + } +} + +void KNewStuffSecure::slotUploadFinished(bool result) +{ + Q_UNUSED(result); + removeTempDirectory(); +} + +void KNewStuffSecure::removeTempDirectory() +{ + if (m_tempDir) + { + KIO::NetAccess::del(KURL().fromPathOrURL(m_tempDir->name()), parentWidget()); + delete m_tempDir; + m_tempDir = 0L; + } +} + +#include "knewstuffsecure.moc" diff --git a/lib/compatibility/knewstuff/knewstuffsecure.h b/lib/compatibility/knewstuff/knewstuffsecure.h new file mode 100644 index 00000000..2aed131a --- /dev/null +++ b/lib/compatibility/knewstuff/knewstuffsecure.h @@ -0,0 +1,101 @@ +/*************************************************************************** + knewstuffsecure.h - description + ------------------- + begin : Tue Jun 22 12:19:55 2004 + copyright : (C) 2004, 2005 by Andras Mantia <amantia@kde.org> + ***************************************************************************/ + +/*************************************************************************** + * * + * This program 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; version 2 of the License. * + * * + ***************************************************************************/ + +#ifndef KNEWSTUFFSECURE_H +#define KNEWSTUFFSECURE_H + +//qt includes +#include <qobject.h> + +//kde includes +#include "knewstuff.h" + +class KTempDir; +/** +Makes possible downloading and installing signed resource files from a server. +You must subclass it and implement the @ref installResource() pure +virtual method to install a resource. For uploading you must create a resource +tarball (which is installabale by @ref installResource()) and call the +@ref uploadResource() method with this tarball as the argument. +Signing and verification is done by the gpg application, so the user must +have it installed, otherwise this class does not give any extra security compared +to the standard KNewStuff class. + +@since 3.4 + +@author Andras Mantia <amantia@kde.org> +*/ +class KDE_EXPORT KNewStuffSecure : public QObject, public KNewStuff +{ + Q_OBJECT + +public: + /** Constructor. + + @param type type of data to be handled, should be something like + korganizer/calendar, kword/template, kdesktop/wallpaper + @param parentWidget parent widget of dialogs opened by the KNewStuff + engine + */ + KNewStuffSecure(const QString &type, QWidget *parentWidget=0); + virtual ~KNewStuffSecure(); + + /** Installs the downloaded resource. Do not call or reimplement directly. + It's reimplemented from KNewStuff for internal reasons. + */ + bool install( const QString &fileName ); + + /** Reimplemented for internal reasons. */ + bool createUploadFile(const QString &fileName); + + /** Initiates a download. This is the method that must be called in + * order to download a signed resource. */ + void downloadResource(); + + /** Signs the file and uploads to the central server. + * @param fileName The file to be signed and uploaded + */ + void uploadResource(const QString &fileName); + + +private slots: + /** Checks the validity of the downloaded tarball and installs it*/ + void slotValidated(int result); + /** The file is signed, so it can be uploaded.*/ + void slotFileSigned(int result); + /** Called when the upload has finished. + @param result the result of the upload + Be careful if you reimplement it, as it deletes the temporary directory + m_tempDir used for upload. You must also delete it (call the parent's method) + if you reimplement it. + */ + void slotUploadFinished(bool result); + +signals: + void installFinished(); + +protected: + /** Installs the resource specified by m_tarName. Implement it in the subclass. */ + virtual void installResource() = 0; + /** Removes the temporary directory m_tempDir. */ + void removeTempDirectory(); + + KTempDir *m_tempDir; + QString m_tarName; + QString m_signedFileName; + QMap<QString, QString> m_installedResources; +}; + +#endif diff --git a/lib/compatibility/knewstuff/provider.cpp b/lib/compatibility/knewstuff/provider.cpp new file mode 100644 index 00000000..2ab48f18 --- /dev/null +++ b/lib/compatibility/knewstuff/provider.cpp @@ -0,0 +1,223 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <schumacher@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 <kconfig.h> +#include <kdebug.h> +#include <kio/job.h> +#include <kglobal.h> +#include <kmessagebox.h> +#include <klocale.h> + +#include "provider.h" +#include "provider.moc" + +using namespace KNS; + +Provider::Provider() : mNoUpload( false ) +{ +} + +Provider::Provider( const QDomElement &e ) : mNoUpload( false ) +{ + parseDomElement( e ); +} + +Provider::~Provider() +{ +} + + +void Provider::setName( const QString &name ) +{ + mName = name; +} + +QString Provider::name() const +{ + return mName; +} + + +void Provider::setIcon( const KURL &url ) +{ + mIcon = url; +} + +KURL Provider::icon() const +{ + return mIcon; +} + + +void Provider::setDownloadUrl( const KURL &url ) +{ + mDownloadUrl = url; +} + +KURL Provider::downloadUrl() const +{ + return mDownloadUrl; +} + + +void Provider::setUploadUrl( const KURL &url ) +{ + mUploadUrl = url; +} + +KURL Provider::uploadUrl() const +{ + return mUploadUrl; +} + + +void Provider::setNoUploadUrl( const KURL &url ) +{ + mNoUploadUrl = url; +} + +KURL Provider::noUploadUrl() const +{ + return mNoUploadUrl; +} + + +void Provider::setNoUpload( bool enabled ) +{ + mNoUpload = enabled; +} + +bool Provider::noUpload() const +{ + return mNoUpload; +} + + +void Provider::parseDomElement( const QDomElement &element ) +{ + if ( element.tagName() != "provider" ) return; + + setDownloadUrl( KURL( element.attribute("downloadurl") ) ); + setUploadUrl( KURL( element.attribute("uploadurl") ) ); + setNoUploadUrl( KURL( element.attribute("nouploadurl") ) ); + setIcon( KURL( element.attribute("icon") ) ); + + QDomNode n; + for ( n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) { + QDomElement p = n.toElement(); + + if ( p.tagName() == "noupload" ) setNoUpload( true ); + if ( p.tagName() == "title" ) setName( p.text().stripWhiteSpace() ); + } +} + +QDomElement Provider::createDomElement( QDomDocument &doc, QDomElement &parent ) +{ + QDomElement entry = doc.createElement( "stuff" ); + parent.appendChild( entry ); + + QDomElement n = doc.createElement( "name" ); + n.appendChild( doc.createTextNode( name() ) ); + entry.appendChild( n ); + + return entry; +} + + +ProviderLoader::ProviderLoader( QWidget *parentWidget ) : + mParentWidget( parentWidget ) +{ + mProviders.setAutoDelete( true ); +} + +void ProviderLoader::load( const QString &type, const QString &providersList ) +{ + kdDebug(5850) << "ProviderLoader::load()" << endl; + + mProviders.clear(); + mJobData = ""; + + KConfig *cfg = KGlobal::config(); + cfg->setGroup("KNewStuff"); + + QString providersUrl = providersList; + if( providersUrl.isEmpty() ) + providersUrl = cfg->readEntry( "ProvidersUrl" ); + + if ( providersUrl.isEmpty() ) { + // TODO: Replace the default by the real one. + QString server = cfg->readEntry( "MasterServer", + "http://korganizer.kde.org" ); + + providersUrl = server + "/knewstuff/" + type + "/providers.xml"; + } + + kdDebug(5850) << "ProviderLoader::load(): providersUrl: " << providersUrl << endl; + + KIO::TransferJob *job = KIO::get( KURL( providersUrl ) ); + connect( job, SIGNAL( result( KIO::Job * ) ), + SLOT( slotJobResult( KIO::Job * ) ) ); + connect( job, SIGNAL( data( KIO::Job *, const QByteArray & ) ), + SLOT( slotJobData( KIO::Job *, const QByteArray & ) ) ); + +// job->dumpObjectInfo(); +} + +void ProviderLoader::slotJobData( KIO::Job *, const QByteArray &data ) +{ + kdDebug(5850) << "ProviderLoader::slotJobData()" << endl; + + if ( data.size() == 0 ) return; + + QCString str( data, data.size() + 1 ); + + mJobData.append( QString::fromUtf8( str ) ); +} + +void ProviderLoader::slotJobResult( KIO::Job *job ) +{ + if ( job->error() ) { + job->showErrorDialog( mParentWidget ); + } + + kdDebug(5850) << "--PROVIDERS-START--" << endl << mJobData << "--PROV_END--" + << endl; + + QDomDocument doc; + if ( !doc.setContent( mJobData ) ) { + KMessageBox::error( mParentWidget, i18n("Error parsing providers list.") ); + return; + } + + QDomElement providers = doc.documentElement(); + + if ( providers.isNull() ) { + kdDebug(5850) << "No document in Providers.xml." << endl; + } + + QDomNode n; + for ( n = providers.firstChild(); !n.isNull(); n = n.nextSibling() ) { + QDomElement p = n.toElement(); + + mProviders.append( new Provider( p ) ); + } + + emit providersLoaded( &mProviders ); +} diff --git a/lib/compatibility/knewstuff/provider.h b/lib/compatibility/knewstuff/provider.h new file mode 100644 index 00000000..69898bc4 --- /dev/null +++ b/lib/compatibility/knewstuff/provider.h @@ -0,0 +1,206 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <schumacher@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. +*/ +#ifndef KNEWSTUFF_PROVIDER_H +#define KNEWSTUFF_PROVIDER_H + +#include <qcstring.h> +#include <qdom.h> +#include <qobject.h> +#include <qptrlist.h> +#include <qstring.h> + +#include <kurl.h> + +namespace KIO { class Job; } + +namespace KNS { + +/** + * @short KNewStuff provider container. + * + * This class provides accessors for the provider object. + * as used by KNewStuff. + * It should probably not be used directly by the application. + * + * @author Cornelius Schumacher (schumacher@kde.org) + * \par Maintainer: + * Josef Spillner (spillner@kde.org) + */ +class Provider +{ + public: + typedef QPtrList<Provider> List; + + /** + * Constructor. + */ + Provider(); + + /** + * Constructor with XML feed. + */ + Provider( const QDomElement & ); + + /** + * Destructor. + */ + ~Provider(); + + /** + * Sets the common name of the provider. + */ + void setName( const QString & ); + + /** + * Retrieves the common name of the provider. + * + * @return provider name + */ + QString name() const; + + /** + * Sets the download URL. + */ + void setDownloadUrl( const KURL & ); + + /** + * Retrieves the download URL. + * + * @return download URL + */ + KURL downloadUrl() const; + + /** + * Sets the upload URL. + */ + void setUploadUrl( const KURL & ); + + /** + * Retrieves the upload URL. + * + * @return upload URL + */ + KURL uploadUrl() const; + + /** + * Sets the URL where a user is led if the provider does not support + * uploads. + * + * @see setNoUpload + */ + void setNoUploadUrl( const KURL & ); + + /** + * Retrieves the URL where a user is led if the provider does not + * support uploads. + * + * @return website URL + */ + KURL noUploadUrl() const; + + /** + * Indicate whether provider supports uploads. + */ + void setNoUpload( bool ); + + /** + * Query whether provider supports uploads. + * + * @return upload support status + */ + bool noUpload() const; + + /** + * Sets the URL for an icon for this provider. + * The icon should be in 32x32 format. If not set, the default icon + * of KDialogBase is used. + */ + void setIcon( const KURL & ); + + /** + * Retrieves the icon URL for this provider. + * + * @return icon URL + */ + KURL icon() const; + + protected: + void parseDomElement( const QDomElement & ); + + QDomElement createDomElement( QDomDocument &, QDomElement &parent ); + + private: + QString mName; + KURL mDownloadUrl; + KURL mUploadUrl; + KURL mNoUploadUrl; + KURL mIcon; + bool mNoUpload; +}; + +/** + * KNewStuff provider loader. + * This class sets up a list of all possible providers by querying + * the main provider database for this specific application. + * It should probably not be used directly by the application. + */ +class ProviderLoader : public QObject +{ + Q_OBJECT + public: + /** + * Constructor. + * + * @param parentWidget the parent widget + */ + ProviderLoader( QWidget *parentWidget ); + + /** + * Starts asynchronously loading the list of providers of the + * specified type. + * + * @param type data type such as 'kdesktop/wallpaper'. + * @param providerList the URl to the list of providers; if empty + * we first try the ProvidersUrl from KGlobal::config, then we + * fall back to a hardcoded value. + */ + void load( const QString &type, const QString &providerList = QString::null ); + + signals: + /** + * Indicates that the list of providers has been successfully loaded. + */ + void providersLoaded( Provider::List * ); + + protected slots: + void slotJobData( KIO::Job *, const QByteArray & ); + void slotJobResult( KIO::Job * ); + + private: + QWidget *mParentWidget; + + QString mJobData; + + Provider::List mProviders; +}; + +} + +#endif diff --git a/lib/compatibility/knewstuff/providerdialog.cpp b/lib/compatibility/knewstuff/providerdialog.cpp new file mode 100644 index 00000000..00374a34 --- /dev/null +++ b/lib/compatibility/knewstuff/providerdialog.cpp @@ -0,0 +1,95 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <schumacher@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 <qlayout.h> +#include <qstring.h> +#include <qlabel.h> + +#include <klistview.h> +#include <klocale.h> +#include <kmessagebox.h> + +#include "engine.h" +#include "provider.h" + +#include "providerdialog.h" +#include "providerdialog.moc" + +using namespace KNS; + +class ProviderItem : public KListViewItem +{ + public: + ProviderItem( KListView *parent, Provider *provider ) : + KListViewItem( parent ), mProvider( provider ) + { + setText( 0, provider->name() ); + } + + Provider *provider() { return mProvider; } + + private: + Provider *mProvider; +}; + +ProviderDialog::ProviderDialog( Engine *engine, QWidget *parent ) : + KDialogBase( Plain, i18n("Hot New Stuff Providers"), Ok | Cancel, Cancel, + parent, 0, false, true ), + mEngine( engine ) +{ + QFrame *topPage = plainPage(); + + QBoxLayout *topLayout = new QVBoxLayout( topPage ); + + QLabel *description = new QLabel( i18n("Please select one of the providers listed below:"), topPage ); + topLayout->addWidget( description ); + + mListView = new KListView( topPage ); + mListView->addColumn( i18n("Name") ); + topLayout->addWidget( mListView ); +} + +void ProviderDialog::clear() +{ + mListView->clear(); +} + +void ProviderDialog::addProvider( Provider *provider ) +{ + new ProviderItem( mListView, provider ); + if ( mListView->childCount() == 1 ) { + mListView->setSelected(mListView->firstChild(), true); + } else if (mListView->childCount() > 1) { + mListView->setSelected(mListView->firstChild(), false); + } +} + +void ProviderDialog::slotOk() +{ + ProviderItem *item = static_cast<ProviderItem *>( mListView->selectedItem() ); + if ( !item ) { + KMessageBox::error( this, i18n("No provider selected.") ); + return; + } + + mEngine->requestMetaInformation( item->provider() ); + + accept(); +} diff --git a/lib/compatibility/knewstuff/providerdialog.h b/lib/compatibility/knewstuff/providerdialog.h new file mode 100644 index 00000000..c75cc3a1 --- /dev/null +++ b/lib/compatibility/knewstuff/providerdialog.h @@ -0,0 +1,76 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <schumacher@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. +*/ +#ifndef KNEWSTUFF_PROVIDERDIALOG_H +#define KNEWSTUFF_PROVIDERDIALOG_H + +#include <kdialogbase.h> + +class KListView; + +namespace KNS { + +class Provider; +class Engine; + +/** + * @short Dialog displaying a list of Hotstuff providers. + * + * This is normally used in the process of uploading data, thus limiting the + * list to providers which support uploads. + * One of the providers is then chosen by the user for further operation. + * + * @author Cornelius Schumacher (schumacher@kde.org) + * \par Maintainer: + * Josef Spillner (spillner@kde.org) + */ +class ProviderDialog : public KDialogBase +{ + Q_OBJECT + public: + /** + Constructor. + + @param engine a KNewStuff engine object + @param parent the parent window + */ + ProviderDialog( Engine *engine, QWidget *parent ); + + /** + Clears the list of providers. + */ + void clear(); + + /** + Adds a Hotstuff provider to the list. + */ + void addProvider( Provider * ); + + protected slots: + void slotOk(); + + private: + Engine *mEngine; + + KListView *mListView; +}; + +} + +#endif diff --git a/lib/compatibility/knewstuff/security.cpp b/lib/compatibility/knewstuff/security.cpp new file mode 100644 index 00000000..f7099c72 --- /dev/null +++ b/lib/compatibility/knewstuff/security.cpp @@ -0,0 +1,344 @@ +/*************************************************************************** + security.cpp - description + ------------------- + begin : Thu Jun 24 11:22:12 2004 + copyright : (C) 2004, 2005 by Andras Mantia <amantia@kde.org> + ***************************************************************************/ + +/*************************************************************************** + * * + * This program 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; version 2 of the License. * + * * + ***************************************************************************/ + + //qt includes +#include <qfile.h> +#include <qfileinfo.h> +#include <qstringlist.h> +#include <qtimer.h> + + //kde includes +#include <kdebug.h> +#include <kinputdialog.h> +#include <klocale.h> +#include <kmdcodec.h> +#include <kmessagebox.h> +#include <kpassdlg.h> +#include <kprocio.h> + + //app includes +#include "security.h" + +using namespace KNS; + +Security::Security() +{ + m_keysRead = false; + m_gpgRunning = false; + readKeys(); + readSecretKeys(); +} + + +Security::~Security() +{ +} + +void Security::readKeys() +{ + if (m_gpgRunning) + { + QTimer::singleShot(5, this, SLOT(readKeys())); + return; + } + m_runMode = List; + m_keys.clear(); + KProcIO *readProcess=new KProcIO(); + *readProcess << "gpg"<<"--no-secmem-warning"<<"--no-tty"<<"--with-colon"<<"--list-keys"; + connect(readProcess, SIGNAL(processExited(KProcess *)), this, SLOT(slotProcessExited(KProcess *))); + connect(readProcess, SIGNAL(readReady(KProcIO *)) ,this, SLOT(slotDataArrived(KProcIO *))); + if (!readProcess->start(KProcess::NotifyOnExit, true)) + KMessageBox::error(0L, i18n("<qt>Cannot start <i>gpg</i> and retrieve the available keys. Make sure that <i>gpg</i> is installed, otherwise verification of downloaded resources will not be possible.</qt>")); + else + m_gpgRunning = true; +} + +void Security::readSecretKeys() +{ + if (m_gpgRunning) + { + QTimer::singleShot(5, this, SLOT(readSecretKeys())); + return; + } + m_runMode = ListSecret; + KProcIO *readProcess=new KProcIO(); + *readProcess << "gpg"<<"--no-secmem-warning"<<"--no-tty"<<"--with-colon"<<"--list-secret-keys"; + connect(readProcess, SIGNAL(processExited(KProcess *)), this, SLOT(slotProcessExited(KProcess *))); + connect(readProcess, SIGNAL(readReady(KProcIO *)) ,this, SLOT(slotDataArrived(KProcIO *))); + if (readProcess->start(KProcess::NotifyOnExit, true)) + m_gpgRunning = true; +} + +void Security::slotProcessExited(KProcess *process) +{ + switch (m_runMode) + { + case ListSecret: + m_keysRead = true; + break; + case Verify: emit validityResult(m_result); + break; + case Sign: emit fileSigned(m_result); + break; + + } + m_gpgRunning = false; + delete process; +} + +void Security::slotDataArrived(KProcIO *procIO) +{ + QString data; + while (procIO->readln(data, true) != -1) + { + switch (m_runMode) + { + case List: + case ListSecret: + if (data.startsWith("pub") || data.startsWith("sec")) + { + KeyStruct key; + if (data.startsWith("pub")) + key.secret = false; + else + key.secret = true; + QStringList line = QStringList::split(":", data, true); + key.id = line[4]; + QString shortId = key.id.right(8); + QString trustStr = line[1]; + key.trusted = false; + if (trustStr == "u" || trustStr == "f") + key.trusted = true; + data = line[9]; + key.mail=data.section('<', -1, -1); + key.mail.truncate(key.mail.length() - 1); + key.name=data.section('<',0,0); + if (key.name.find("(")!=-1) + key.name=key.name.section('(',0,0); + m_keys[shortId] = key; + } + break; + case Verify: + data = data.section("]",1,-1).stripWhiteSpace(); + if (data.startsWith("GOODSIG")) + { + m_result &= SIGNED_BAD_CLEAR; + m_result |= SIGNED_OK; + QString id = data.section(" ", 1 , 1).right(8); + if (!m_keys.contains(id)) + { + m_result |= UNKNOWN; + } else + { + m_signatureKey = m_keys[id]; + } + } else + if (data.startsWith("NO_PUBKEY")) + { + m_result &= SIGNED_BAD_CLEAR; + m_result |= UNKNOWN; + } else + if (data.startsWith("BADSIG")) + { + m_result |= SIGNED_BAD; + QString id = data.section(" ", 1 , 1).right(8); + if (!m_keys.contains(id)) + { + m_result |= UNKNOWN; + } else + { + m_signatureKey = m_keys[id]; + } + } else + if (data.startsWith("TRUST_ULTIMATE")) + { + m_result &= SIGNED_BAD_CLEAR; + m_result |= TRUSTED; + } + break; + + case Sign: + if (data.find("passphrase.enter") != -1) + { + QCString password; + KeyStruct key = m_keys[m_secretKey]; + int result = KPasswordDialog::getPassword(password, i18n("<qt>Enter passphrase for key <b>0x%1</b>, belonging to<br><i>%2<%3></i>:</qt>").arg(m_secretKey).arg(key.name).arg(key.mail)); + if (result == KPasswordDialog::Accepted) + { + procIO->writeStdin(password, true); + password.fill(' '); + } + else + { + m_result |= BAD_PASSPHRASE; + slotProcessExited(procIO); + return; + } + } else + if (data.find("BAD_PASSPHRASE") != -1) + { + m_result |= BAD_PASSPHRASE; + } + break; + } + } +} + +void Security::checkValidity(const QString& filename) +{ + m_fileName = filename; + slotCheckValidity(); +} + +void Security::slotCheckValidity() +{ + if (!m_keysRead || m_gpgRunning) + { + QTimer::singleShot(5, this, SLOT(slotCheckValidity())); + return; + } + if (m_keys.count() == 0) + { + emit validityResult(-1); + return; + } + + m_result = 0; + m_runMode = Verify; + QFileInfo f(m_fileName); + //check the MD5 sum + QString md5sum; + const char* c = ""; + KMD5 context(c); + QFile file(m_fileName); + if (file.open(IO_ReadOnly)) + { + context.reset(); + context.update(file); + md5sum = context.hexDigest(); + file.close(); + } + file.setName(f.dirPath() + "/md5sum"); + if (file.open(IO_ReadOnly)) + { + QString md5sum_file; + file.readLine(md5sum_file, 50); + if (!md5sum.isEmpty() && !md5sum_file.isEmpty() && md5sum_file.startsWith(md5sum)) + m_result |= MD5_OK; + file.close(); + } + m_result |= SIGNED_BAD; + m_signatureKey.id = ""; + m_signatureKey.name = ""; + m_signatureKey.mail = ""; + m_signatureKey.trusted = false; + + //verify the signature + KProcIO *verifyProcess=new KProcIO(); + *verifyProcess<<"gpg"<<"--no-secmem-warning"<<"--status-fd=2"<<"--command-fd=0"<<"--verify" << f.dirPath() + "/signature"<< m_fileName; + connect(verifyProcess, SIGNAL(processExited(KProcess *)),this, SLOT(slotProcessExited(KProcess *))); + connect(verifyProcess, SIGNAL(readReady(KProcIO *)),this, SLOT(slotDataArrived(KProcIO *))); + if (verifyProcess->start(KProcess::NotifyOnExit,true)) + m_gpgRunning = true; + else + { + KMessageBox::error(0L, i18n("<qt>Cannot start <i>gpg</i> and check the validity of the file. Make sure that <i>gpg</i> is installed, otherwise verification of downloaded resources will not be possible.</qt>")); + emit validityResult(0); + delete verifyProcess; + } +} + +void Security::signFile(const QString &fileName) +{ + m_fileName = fileName; + slotSignFile(); +} + +void Security::slotSignFile() +{ + if (!m_keysRead || m_gpgRunning) + { + QTimer::singleShot(5, this, SLOT(slotSignFile())); + return; + } + + QStringList secretKeys; + for (QMap<QString, KeyStruct>::Iterator it = m_keys.begin(); it != m_keys.end(); ++it) + { + if (it.data().secret) + secretKeys.append(it.key()); + } + + if (secretKeys.count() == 0) + { + emit fileSigned(-1); + return; + } + + m_result = 0; + QFileInfo f(m_fileName); + + //create the MD5 sum + QString md5sum; + const char* c = ""; + KMD5 context(c); + QFile file(m_fileName); + if (file.open(IO_ReadOnly)) + { + context.reset(); + context.update(file); + md5sum = context.hexDigest(); + file.close(); + } + file.setName(f.dirPath() + "/md5sum"); + if (file.open(IO_WriteOnly)) + { + QTextStream stream(&file); + stream << md5sum; + m_result |= MD5_OK; + file.close(); + } + + if (secretKeys.count() > 1) + { + bool ok; + secretKeys = KInputDialog::getItemList(i18n("Select Signing Key"), i18n("Key used for signing:"), secretKeys, secretKeys[0], false, &ok); + if (ok) + m_secretKey = secretKeys[0]; + else + { + emit fileSigned(0); + return; + } + } else + m_secretKey = secretKeys[0]; + + //verify the signature + KProcIO *signProcess=new KProcIO(); + *signProcess<<"gpg"<<"--no-secmem-warning"<<"--status-fd=2"<<"--command-fd=0"<<"--no-tty"<<"--detach-sign" << "-u" << m_secretKey << "-o" << f.dirPath() + "/signature" << m_fileName; + connect(signProcess, SIGNAL(processExited(KProcess *)),this, SLOT(slotProcessExited(KProcess *))); + connect(signProcess, SIGNAL(readReady(KProcIO *)),this, SLOT(slotDataArrived(KProcIO *))); + m_runMode = Sign; + if (signProcess->start(KProcess::NotifyOnExit,true)) + m_gpgRunning = true; + else + { + KMessageBox::error(0L, i18n("<qt>Cannot start <i>gpg</i> and sign the file. Make sure that <i>gpg</i> is installed, otherwise signing of the resources will not be possible.</qt>")); + emit fileSigned(0); + delete signProcess; + } +} + +#include "security.moc" diff --git a/lib/compatibility/knewstuff/security.h b/lib/compatibility/knewstuff/security.h new file mode 100644 index 00000000..5eea64ae --- /dev/null +++ b/lib/compatibility/knewstuff/security.h @@ -0,0 +1,141 @@ +/*************************************************************************** + security.h - description + ------------------- + begin : Thu Jun 24 11:22:12 2004 + copyright : (C) 2004, 2005 by Andras Mantia <amantia@kde.org> + ***************************************************************************/ + +/*************************************************************************** + * * + * This program 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; version 2 of the License. * + * * + ***************************************************************************/ + + +#ifndef SECURITY_H +#define SECURITY_H + +//qt includes +#include <qmap.h> +#include <qobject.h> + +class KProcIO; +class KProcess; + +struct KeyStruct { + QString id; + QString name; + QString mail; + bool trusted; + bool secret; +}; + +/** +Handles security releated issues, like signing, verifying. +It is a private class, not meant to be used by third party applications. + +@author Andras Mantia <amantia@kde.org> +*/ + +namespace KNS { + +class Security : public QObject +{ +Q_OBJECT +public: + static Security* const ref() + { + static Security *m_ref; + if (!m_ref) m_ref = new Security(); + return m_ref; + } + ~Security(); + + + /** Verifies the integrity and the signature of a tarball file. + * @param fileName the file to be verified. It should be a tar.gz (.tgz) file. The directory where + * the file is should contain a "signature" and a "md5sum" file, otherwise verification will fail. + * The method is asynchronous and the result is signalled with @ref validityResult. + */ + void checkValidity(const QString &fileName); + + /** Creates a signature and an md5sum file for the fileName and packs + * everything into a gzipped tarball. + * @param fileName the file with full path to sign + * + * The method is asynchronous and the result is signalled with @ref fileSigned. + */ + void signFile(const QString &fileName); + /** Get the key used for signing. This method is valid only if: + * - the checkValidity was called + * - the result of the validity check does not have the UNKNOWN bit set + * + * @return the key used for signing the file + */ + KeyStruct signatureKey() {return m_signatureKey;} + + enum Results { + MD5_OK = 1, /// The MD5 sum check is OK + SIGNED_OK = 2, /// The file is signed with a good signature + SIGNED_BAD = 4, /// The file is signed with a bad signature + TRUSTED = 8, /// The signature is trusted + UNKNOWN = 16, ///The key is unknown + SIGNED_BAD_CLEAR = 27, ///used to clear the SIGNED_BAD flag + BAD_PASSPHRASE = 32 ///wrong passhprase entered + }; + +public slots: + /** Reads the available public keys */ + void readKeys(); + /** Reads the available secret keys */ + void readSecretKeys(); + /** Verifies the integrity and the signature of a tarball file (@see m_fileName). + */ + void slotCheckValidity(); + + /** Creates a signature and an md5sum file for the @see m_fileName and packs + * everything into a gzipped tarball. + */ + void slotSignFile(); + +private: + Security(); + + enum RunMode { + List = 0, ///read the public keys + ListSecret, ///read the secret keys + Verify, ///verify the signature + Sign ///create signature + }; + + KeyStruct m_signatureKey; + int m_result; + int m_runMode; + bool m_gpgRunning; /// true if gpg is currently running + bool m_keysRead; /// true if all the keys were read + QMap<QString, KeyStruct> m_keys; /// holds information about the available key + QString m_fileName; /// the file to sign/verify + QString m_secretKey; /// the key used for signing + +private slots: + void slotProcessExited(KProcess *process); + void slotDataArrived(KProcIO *process); + +signals: + /** Sent when the validity check is done. + * + * @return the result of the check. See @ref Results + */ + void validityResult(int result); + /** Sent when the signing is done. + * + * @return the result of the operation. See @ref Results + */ + void fileSigned(int result); +}; + +} + +#endif diff --git a/lib/compatibility/knewstuff/uploaddialog.cpp b/lib/compatibility/knewstuff/uploaddialog.cpp new file mode 100644 index 00000000..5116785d --- /dev/null +++ b/lib/compatibility/knewstuff/uploaddialog.cpp @@ -0,0 +1,176 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <schumacher@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 <qcombobox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlineedit.h> +#include <qspinbox.h> +#include <qstring.h> +#include <ktextedit.h> + +#include <klistview.h> +#include <klocale.h> +#include <kdebug.h> +#include <kurlrequester.h> +#include <kmessagebox.h> +#include <kconfig.h> +#include <kapplication.h> + +#include "engine.h" +#include "entry.h" + +#include "uploaddialog.h" +#include "uploaddialog.moc" + +using namespace KNS; + +UploadDialog::UploadDialog( Engine *engine, QWidget *parent ) : + KDialogBase( Plain, i18n("Share Hot New Stuff"), Ok | Cancel, Cancel, + parent, 0, false, true ), + mEngine( engine ) +{ + mEntryList.setAutoDelete( true ); + + QFrame *topPage = plainPage(); + + QGridLayout *topLayout = new QGridLayout( topPage ); + topLayout->setSpacing( spacingHint() ); + + QLabel *nameLabel = new QLabel( i18n("Name:"), topPage ); + topLayout->addWidget( nameLabel, 0, 0 ); + mNameEdit = new QLineEdit( topPage ); + topLayout->addWidget( mNameEdit, 0, 1 ); + + QLabel *authorLabel = new QLabel( i18n("Author:"), topPage ); + topLayout->addWidget( authorLabel, 1, 0 ); + mAuthorEdit = new QLineEdit( topPage ); + topLayout->addWidget( mAuthorEdit, 1, 1 ); + + QLabel *versionLabel = new QLabel( i18n("Version:"), topPage ); + topLayout->addWidget( versionLabel, 2, 0 ); + mVersionEdit = new QLineEdit( topPage ); + topLayout->addWidget( mVersionEdit, 2, 1 ); + + QLabel *releaseLabel = new QLabel( i18n("Release:"), topPage ); + topLayout->addWidget( releaseLabel, 3, 0 ); + mReleaseSpin = new QSpinBox( topPage ); + mReleaseSpin->setMinValue( 1 ); + topLayout->addWidget( mReleaseSpin, 3, 1 ); + + QLabel *licenceLabel = new QLabel( i18n("License:"), topPage ); + topLayout->addWidget( licenceLabel, 4, 0 ); + mLicenceCombo = new QComboBox( topPage ); + mLicenceCombo->setEditable( true ); + mLicenceCombo->insertItem( i18n("GPL") ); + mLicenceCombo->insertItem( i18n("LGPL") ); + mLicenceCombo->insertItem( i18n("BSD") ); + topLayout->addWidget( mLicenceCombo, 4, 1 ); + + QLabel *languageLabel = new QLabel( i18n("Language:"), topPage ); + topLayout->addWidget( languageLabel, 5, 0 ); + mLanguageCombo = new QComboBox( topPage ); + topLayout->addWidget( mLanguageCombo, 5, 1 ); + mLanguageCombo->insertStringList( KGlobal::locale()->languageList() ); + + QLabel *previewLabel = new QLabel( i18n("Preview URL:"), topPage ); + topLayout->addWidget( previewLabel, 6, 0 ); + mPreviewUrl = new KURLRequester( topPage ); + topLayout->addWidget( mPreviewUrl, 6, 1 ); + + QLabel *summaryLabel = new QLabel( i18n("Summary:"), topPage ); + topLayout->addMultiCellWidget( summaryLabel, 7, 7, 0, 1 ); + mSummaryEdit = new KTextEdit( topPage ); + topLayout->addMultiCellWidget( mSummaryEdit, 8, 8, 0, 1 ); + + KConfig *conf = kapp->config(); + conf->setGroup("KNewStuffUpload"); + QString name = conf->readEntry("name"); + QString author = conf->readEntry("author"); + QString version = conf->readEntry("version"); + QString release = conf->readEntry("release"); + QString preview = conf->readEntry("preview"); + QString summary = conf->readEntry("summary"); + QString lang = conf->readEntry("language"); + QString licence = conf->readEntry("licence"); + + if(!name.isNull()) + { + int prefill = KMessageBox::questionYesNo(this, i18n("Old upload information found, fill out fields?"), QString::null, i18n("Fill Out Fields"), i18n("Do Not Fill Out")); + if(prefill == KMessageBox::Yes) + { + mNameEdit->setText(name); + mAuthorEdit->setText(author); + mVersionEdit->setText(version); + mReleaseSpin->setValue(release.toInt()); + mPreviewUrl->setURL(preview); + mSummaryEdit->setText(summary); + if(!lang.isEmpty()) mLanguageCombo->setCurrentText(lang); + if(!licence.isEmpty()) mLicenceCombo->setCurrentText(licence); + } + } +} + +UploadDialog::~UploadDialog() +{ + mEntryList.clear(); +} + +void UploadDialog::slotOk() +{ + if ( mNameEdit->text().isEmpty() ) { + KMessageBox::error( this, i18n("Please put in a name.") ); + return; + } + + Entry *entry = new Entry; + + mEntryList.append( entry ); + + entry->setName( mNameEdit->text() ); + entry->setAuthor( mAuthorEdit->text() ); + entry->setVersion( mVersionEdit->text() ); + entry->setRelease( mReleaseSpin->value() ); + entry->setLicence( mLicenceCombo->currentText() ); + entry->setPreview( KURL( mPreviewUrl->url().section("/", -1) ), mLanguageCombo->currentText() ); + entry->setSummary( mSummaryEdit->text(), mLanguageCombo->currentText() ); + + KConfig *conf = kapp->config(); + conf->setGroup("KNewStuffUpload"); + conf->writeEntry("name", mNameEdit->text()); + conf->writeEntry("author", mAuthorEdit->text()); + conf->writeEntry("version", mVersionEdit->text()); + conf->writeEntry("release", mReleaseSpin->value()); + conf->writeEntry("licence", mLicenceCombo->currentText()); + conf->writeEntry("preview", mPreviewUrl->url()); + conf->writeEntry("summary", mSummaryEdit->text()); + conf->writeEntry("language", mLanguageCombo->currentText()); + conf->sync(); + + mEngine->upload( entry ); + + accept(); +} + +void UploadDialog::setPreviewFile( const QString &previewFile ) +{ + mPreviewUrl->setURL( previewFile ); +} + diff --git a/lib/compatibility/knewstuff/uploaddialog.h b/lib/compatibility/knewstuff/uploaddialog.h new file mode 100644 index 00000000..8e962ccb --- /dev/null +++ b/lib/compatibility/knewstuff/uploaddialog.h @@ -0,0 +1,92 @@ +/* + This file is part of KOrganizer. + Copyright (c) 2002 Cornelius Schumacher <schumacher@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. +*/ +#ifndef KNEWSTUFF_UPLOADDIALOG_H +#define KNEWSTUFF_UPLOADDIALOG_H + +#include <kdialogbase.h> + +class QLineEdit; +class QSpinBox; +class KURLRequester; +class QTextEdit; +class QComboBox; + +namespace KNS { + +class Engine; +class Entry; + +/** + * @short KNewStuff file upload dialog. + * + * Using this dialog, data can easily be uploaded to the Hotstuff servers. + * It should however not be used on its own, instead a KNewStuff (or + * KNewStuffGeneric) object invokes it. + * + * @author Cornelius Schumacher (schumacher@kde.org) + * \par Maintainer: + * Josef Spillner (spillner@kde.org) + */ +class UploadDialog : public KDialogBase +{ + Q_OBJECT + public: + /** + Constructor. + + @param engine a KNewStuff engine object to be used for uploads + @param parent the parent window + */ + UploadDialog( Engine *engine, QWidget *parent ); + + /** + Destructor. + */ + ~UploadDialog(); + + /** + Sets the preview filename. + This is only meaningful if the application supports previews. + + @param previewFile the preview image file + */ + void setPreviewFile( const QString &previewFile ); + + protected slots: + void slotOk(); + + private: + Engine *mEngine; + + QLineEdit *mNameEdit; + QLineEdit *mAuthorEdit; + QLineEdit *mVersionEdit; + QSpinBox *mReleaseSpin; + KURLRequester *mPreviewUrl; + QTextEdit *mSummaryEdit; + QComboBox *mLanguageCombo; + QComboBox *mLicenceCombo; + + QPtrList<Entry> mEntryList; +}; + +} + +#endif diff --git a/lib/ksavealldialog.cpp b/lib/ksavealldialog.cpp new file mode 100644 index 00000000..620f018e --- /dev/null +++ b/lib/ksavealldialog.cpp @@ -0,0 +1,189 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Harald Fernengel <harry@kdevelop.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 <qvbox.h> +#include <qlabel.h> +#include <qheader.h> + +#include <klocale.h> +#include <kpushbutton.h> +#include <klistbox.h> +#include <klistview.h> +#include <kstdguiitem.h> + +#include "ksavealldialog.h" + +namespace +{ + +class CheckURL : public QCheckListItem +{ +public: + CheckURL( QListView * lv, KURL const & url ) + : QCheckListItem( lv, url.path(), QCheckListItem::CheckBox), + _url( url ) + {} + + KURL const & url() const { return _url; } + +private: + KURL _url; +}; + +} + + +KSaveSelectDialog::KSaveSelectDialog( KURL::List const & filelist, KURL::List const & ignorelist, QWidget * parent ) : + KDialogBase( parent, "SaveAllDialog", true, i18n("Save Modified Files?"), + Ok | User1 | Close ) +{ + QVBox *top = makeVBoxMainWidget(); + + (void)new QLabel( i18n("The following files have been modified. Save them?"), top ); + + _listview = new KListView( top ); + _listview->addColumn( "" ); + _listview->header()->hide(); + _listview->setResizeMode( QListView::LastColumn ); + + setButtonOKText( i18n("Save &Selected"), i18n("Saves all selected files") ); + setButtonText( User1, i18n("Save &None") ); + setButtonText( Close, KStdGuiItem::cancel().text() ); + setButtonTip( User1, i18n("Lose all modifications") ); + setButtonTip( Close, i18n("Cancels the action") ); + + KURL::List::ConstIterator it = filelist.begin(); + while ( it != filelist.end() ) + { + if ( !ignorelist.contains( *it ) ) + { + QCheckListItem * x = new CheckURL( _listview, *it ); + x->setOn( true ); + } + ++it; + } + + connect( this, SIGNAL(closeClicked()), this, SLOT(cancel()) ); + connect( this, SIGNAL(okClicked()), this, SLOT(save()) ); + connect( this, SIGNAL(user1Clicked()), this, SLOT(saveNone()) ); +} + +KSaveSelectDialog::~KSaveSelectDialog() {} + +void KSaveSelectDialog::saveNone( ) +{ + // deselect all + CheckURL * item = static_cast<CheckURL*>( _listview->firstChild() ); + while ( item ) + { + item->setOn( false ); + item = static_cast<CheckURL*>( item->nextSibling() ); + } + + QDialog::accept(); +} + +void KSaveSelectDialog::save( ) +{ + QDialog::accept(); +} + +void KSaveSelectDialog::cancel( ) +{ + QDialog::reject(); +} + +KURL::List KSaveSelectDialog::filesToSave( ) +{ + KURL::List filelist; + CheckURL const * item = static_cast<CheckURL*>( _listview->firstChild() ); + while ( item ) + { + if ( item->isOn() ) + { + filelist << item->url(); + } + item = static_cast<CheckURL*>( item->nextSibling() ); + } + return filelist; +} + +KURL::List KSaveSelectDialog::filesNotToSave( ) +{ + KURL::List filelist; + CheckURL const * item = static_cast<CheckURL*>( _listview->firstChild() ); + while ( item ) + { + if ( ! item->isOn() ) + { + filelist << item->url(); + } + item = static_cast<CheckURL*>( item->nextSibling() ); + } + return filelist; +} + + +KSaveAllDialog::KSaveAllDialog( const QStringList& filenames, QWidget* parent ) : + KDialogBase( parent, "SaveAllDialog", true, i18n("Save Modified Files?"), + Ok | User1 | Close ) +{ + m_result = Cancel; + + QVBox *top = makeVBoxMainWidget(); + + (void)new QLabel( i18n("The following files have been modified. Save them?"), top ); + KListBox* lb = new KListBox( top ); + lb->setMinimumHeight( lb->fontMetrics().height() * 5 ); + lb->insertStringList( filenames ); + + setButtonOKText( i18n("Save &All"), i18n("Saves all modified files") ); + setButtonText( User1, i18n("Save &None") ); + setButtonText( Close, KStdGuiItem::cancel().text() ); + setButtonTip( User1, i18n("Lose all modifications") ); + setButtonTip( Close, i18n("Cancels the action") ); + + connect( this, SIGNAL(closeClicked()), this, SLOT(cancel()) ); + connect( this, SIGNAL(okClicked()), this, SLOT(saveAll()) ); + connect( this, SIGNAL(user1Clicked()), this, SLOT(revert()) ); +} + +KSaveAllDialog::~KSaveAllDialog() +{ +} + +void KSaveAllDialog::revert() +{ + m_result = Revert; + QDialog::accept(); +} + +void KSaveAllDialog::saveAll() +{ + m_result = SaveAll; + QDialog::accept(); +} + +void KSaveAllDialog::cancel() +{ + m_result = Cancel; + QDialog::reject(); +} + +#include "ksavealldialog.moc" diff --git a/lib/ksavealldialog.h b/lib/ksavealldialog.h new file mode 100644 index 00000000..9d7860cf --- /dev/null +++ b/lib/ksavealldialog.h @@ -0,0 +1,83 @@ +/* This file is part of the KDE project + Copyright (C) 2002 Harald Fernengel <harry@kdevelop.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. +*/ + +#ifndef SAVEALLDIALOG_H +#define SAVEALLDIALOG_H + +#include <qstringlist.h> +#include <kdialogbase.h> +#include <kurl.h> + +class KListView; +/** +@file ksavealldialog.h +Dialogs to save multiple files. +*/ + +/** +Dialog to save selected files. +*/ +class KSaveSelectDialog : public KDialogBase +{ + Q_OBJECT + +public: + KSaveSelectDialog( KURL::List const & filelist, KURL::List const & ignorelist, QWidget * parent ); + virtual ~KSaveSelectDialog(); + + KURL::List filesToSave(); + KURL::List filesNotToSave(); + +private slots: + void saveNone(); + void save(); + void cancel(); + +private: + KListView * _listview; + +}; + + +/** +Dialog to save all files. +*/ +class KSaveAllDialog : public KDialogBase +{ + Q_OBJECT + +public: + enum SaveAllResult{ SaveAll, Cancel, Revert }; + + KSaveAllDialog( const QStringList& filenames, QWidget* parent ); + virtual ~KSaveAllDialog(); + + SaveAllResult result() const { return m_result; } + +private slots: + void revert(); + void saveAll(); + void cancel(); + +private: + SaveAllResult m_result; + +}; + +#endif diff --git a/lib/qextfileinfo.cpp b/lib/qextfileinfo.cpp new file mode 100644 index 00000000..b7c7e741 --- /dev/null +++ b/lib/qextfileinfo.cpp @@ -0,0 +1,619 @@ +/* + From WebMaker - KDE HTML Editor + Copyright (C) 1998, 1999 Alexei Dets <dets@services.ru> + + Rewritten for Quanta Plus: (C) 2002 Andras Mantia <amantia@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. +*/ + + +//qt includes +#include <qdir.h> +#include <qapplication.h> +#include <qptrlist.h> +#include <qstringlist.h> +#include <qregexp.h> +#include <qtimer.h> + +//kde includes +#include <kurl.h> +#include <kio/job.h> +#include <kio/netaccess.h> +#include <kio/scheduler.h> +#include <kdirlister.h> +#include <kfileitem.h> +#include <kglobal.h> +#include <kdebug.h> + +//app includes +#include "qextfileinfo.h" + +QString QExtFileInfo::lastErrorMsg = ""; + +QString QExtFileInfo::canonicalPath(const QString& path) +{ + if (!path.startsWith("/") || path == "/") + return path; + bool endsWithSlash = path.endsWith("/"); + QDir dir(path); + if (dir.exists() || QFileInfo(path).exists()) + { + QString s = dir.canonicalPath(); + if (endsWithSlash) + s.append("/"); + return s; + } else + { + KURL u = KURL::fromPathOrURL(path).upURL(); + QString s = u.path(-1) + "/"; + if (s == "//") s = "/"; + QString s2 = path.mid(s.length()); + s2 = QExtFileInfo::canonicalPath(s) + s2; + return s2; + } +} + +QString QExtFileInfo::homeDirPath() +{ + return QDir(QDir::homeDirPath()).canonicalPath(); +} + +/** create a relative short url based in baseURL*/ +KURL QExtFileInfo::toRelative(const KURL& _urlToConvert,const KURL& _baseURL, bool resolveSymlinks) +{ + KURL urlToConvert = _urlToConvert; + KURL baseURL = _baseURL; + KURL resultURL = urlToConvert; + if (urlToConvert.protocol() == baseURL.protocol()) + { + if (urlToConvert.isLocalFile()) + { + QString path; + if (resolveSymlinks) + path = QExtFileInfo::canonicalPath(urlToConvert.path()); + else + path = urlToConvert.path(); + if (!path.isEmpty()) + urlToConvert.setPath(path); + if (resolveSymlinks) + path = QExtFileInfo::canonicalPath(baseURL.path()); + else + path = baseURL.path(); + if (!path.isEmpty()) + baseURL.setPath(path); + } + QString path = urlToConvert.path(); + QString basePath = baseURL.path(1); + if (path.startsWith("/")) + { + path.remove(0, 1); + basePath.remove(0, 1); + if ( basePath.right(1) != "/" ) basePath.append("/"); + + int pos=0; + int pos1=0; + for (;;) + { + pos=path.find("/"); + pos1=basePath.find("/"); + if ( pos<0 || pos1<0 ) break; + if ( path.left(pos+1 ) == basePath.left(pos1+1) ) + { + path.remove(0, pos+1); + basePath.remove(0, pos1+1); + } + else + break; + }; + + if ( basePath == "/" ) basePath=""; + int level = basePath.contains("/"); + for (int i=0; i<level; i++) + { + path="../"+path; + }; + } + + resultURL.setPath(QDir::cleanDirPath(path)); + } + + if (urlToConvert.path().endsWith("/") && !resultURL.path().isEmpty()) + resultURL.adjustPath(1); + return resultURL; +} +/** convert relative filename to absolute */ +KURL QExtFileInfo::toAbsolute(const KURL& _urlToConvert,const KURL& _baseURL) +{ + KURL urlToConvert = _urlToConvert; + KURL baseURL = _baseURL; + KURL resultURL = urlToConvert; + + if (urlToConvert.protocol() == baseURL.protocol() && !urlToConvert.path().startsWith("/")) + { + if (urlToConvert.isLocalFile()) + { + QString path = QExtFileInfo::canonicalPath(baseURL.path()); + if (!path.isEmpty()) + baseURL.setPath(path); + } + int pos; + QString cutname = urlToConvert.path(); + QString cutdir = baseURL.path(1); + while ( (pos = cutname.find("../")) >=0 ) + { + cutname.remove( 0, pos+3 ); + cutdir.remove( cutdir.length()-1, 1 ); + cutdir.remove( cutdir.findRev('/')+1 , 1000); + } + resultURL.setPath(QDir::cleanDirPath(cutdir+cutname)); + } + + if (urlToConvert.path().endsWith("/")) resultURL.adjustPath(1); + return resultURL; +} + +/** All files in a dir. + The return will also contain the name of the subdirectories. + This is needed for empty directory adding/handling. (Andras) + Currently works only for local directories +*/ +KURL::List QExtFileInfo::allFiles( const KURL& path, const QString& mask, QWidget *window) +{ + QExtFileInfo internalFileInfo; + return internalFileInfo.allFilesInternal(path, mask, window); +} + +KURL::List QExtFileInfo::allFilesRelative( const KURL& path, const QString& mask, QWidget *window, bool resolveSymlinks) +{ + QExtFileInfo internalFileInfo; + KURL::List r = internalFileInfo.allFilesInternal(path, mask, window); + + KURL::List::Iterator it; + for ( it = r.begin(); it != r.end(); ++it ) + { + *it = QExtFileInfo::toRelative( *it, path, resolveSymlinks ); + } + + return r; +} + +QDict<KFileItem> QExtFileInfo::allFilesDetailed(const KURL& path, const QString& mask, QWidget *window) +{ + QExtFileInfo internalFileInfo; + return internalFileInfo.allFilesDetailedInternal(path, mask, window); +} + + +bool QExtFileInfo::createDir(const KURL& path, QWidget *window) +{ + int i = 0; + bool result; + KURL dir3; + KURL dir2; + KURL dir1 = path; + dir1.setPath("/"); + if (!exists(dir1, false, window) && path.protocol() != "webdav" ) + { + return false; //the root is not accessible, possible wrong username/password supplied + } + while (!exists(path, false, window) && dir2.path() != path.path()) + { + dir1 = path; + dir2 = path; + + dir1=cdUp(dir1); + while (!exists(dir1, false, window) && dir1.path() != "/") + { + dir1 = cdUp(dir1); + dir2 = cdUp(dir2); + // debug(d1); + } + dir3 = dir2; + dir3.adjustPath(-1); //some servers refuse to create directories ending with a slash + result = KIO::NetAccess::mkdir(dir3, window); + if (dir2.path() == "/" || !result) + break; + i++; + } + result = exists(path, false, window); + return result; +} + +KURL QExtFileInfo::cdUp(const KURL &url) +{ + KURL u = url; + QString dir = u.path(-1); + while ( !dir.isEmpty() && dir.right(1) != "/" ) + { + dir.remove( dir.length()-1,1); + } + u.setPath(dir); + return u; +} + +QString QExtFileInfo::shortName(const QString &fname) +{ + return fname.section("/", -1); +} + +KURL QExtFileInfo::path( const KURL &url ) +{ + KURL result = url; + result.setPath(result.directory(false,false)); + return result; +} + +KURL QExtFileInfo::home() +{ + KURL url; + url.setPath(QDir::currentDirPath()+"/"); + return url; +} + + +bool QExtFileInfo::exists(const KURL& a_url, bool readingOnly, QWidget *window) +{ +// Andras: Don't use it now, as it brings up an extra dialog and need manual +// intervention when usign fish +// return KIO::NetAccess::exists(a_url, false); + +// No dialog when stating. + if (a_url.isLocalFile()) + { + return QFile::exists(a_url.path()); + } else + { + QExtFileInfo internalFileInfo; + return internalFileInfo.internalExists(a_url, readingOnly, window); + } +} + +/* Synchronous copy, like NetAccess::file_copy in KDE 3.2 */ +bool QExtFileInfo::copy( const KURL& src, const KURL& target, int permissions, + bool overwrite, bool resume, QWidget* window ) +{ + QExtFileInfo internalFileInfo; + return internalFileInfo.internalCopy( src, target, permissions, overwrite, resume, window ); +} + +/** No descriptions */ +KURL::List QExtFileInfo::allFilesInternal(const KURL& startURL, const QString& mask, QWidget *window) +{ + if (startURL.isLocalFile()) + return allLocalFiles(startURL.path(-1), mask); + + dirListItems.clear(); + if (internalExists(startURL, true, window)) + { + lstFilters.setAutoDelete(true); + lstFilters.clear(); + // Split on white space + QStringList list = QStringList::split( ' ', mask ); + for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) + lstFilters.append( new QRegExp(*it, false, true ) ); + + bJobOK = true; + KIO::ListJob *job = KIO::listRecursive(startURL, false, true); + job->setWindow(window); + m_listJobCount = 1; + connect(job, SIGNAL(entries(KIO::Job *, const KIO::UDSEntryList&)), + this, SLOT(slotNewEntries(KIO::Job *, const KIO::UDSEntryList&))); + connect( job, SIGNAL( result (KIO::Job *) ), + this, SLOT( slotListResult (KIO::Job *) ) ); + m_listStartURL = startURL.url(); + + //kdDebug(24000) << "Now listing: " << startURL.url() << endl; + enter_loop(); + //kdDebug(24000) << "Listing done: " << startURL.url() << endl; + lstFilters.clear(); + if (!bJobOK) + { + // kdDebug(24000) << "Error while listing "<< startURL.url() << endl; + dirListItems.clear(); + } + } + return dirListItems; +} + +/** No descriptions */ +QDict<KFileItem> QExtFileInfo::allFilesDetailedInternal(const KURL& startURL, const QString& mask, QWidget *window) +{ + detailedDirListItems.setAutoDelete(true); + detailedDirListItems.clear(); + detailedDirListItems.setAutoDelete(false); + if (internalExists(startURL, true, window)) + { + lstFilters.setAutoDelete(true); + lstFilters.clear(); + // Split on white space + QStringList list = QStringList::split( ' ', mask ); + for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) + lstFilters.append( new QRegExp(*it, false, true ) ); + + bJobOK = true; + KIO::ListJob *job = KIO::listRecursive(startURL, false, true); + job->setWindow(window); + m_listJobCount = 1; + connect(job, SIGNAL(entries(KIO::Job *, const KIO::UDSEntryList&)), + this, SLOT(slotNewDetailedEntries(KIO::Job *, const KIO::UDSEntryList&))); + connect( job, SIGNAL( result (KIO::Job *) ), + this, SLOT( slotListResult (KIO::Job *) ) ); + m_listStartURL = startURL.url(); + //kdDebug(24000) << "Now listing: " << startURL.url() << endl; + enter_loop(); + //kdDebug(24000) << "Listing done: " << startURL.url() << endl; + lstFilters.clear(); + if (!bJobOK) + { + // kdDebug(24000) << "Error while listing "<< startURL.url() << endl; + detailedDirListItems.clear(); + } + } + return detailedDirListItems; +} + +KURL::List QExtFileInfo::allLocalFiles(const QString& startPath, const QString& mask) +{ + KURL::List list; + QDir d(startPath, mask); + QStringList l = d.entryList(); + QStringList::ConstIterator end = l.constEnd(); + QString path; + for (QStringList::ConstIterator it = l.constBegin(); it != end; ++it) + { + path = *it; + if (path != "." && path != "..") + { + path = startPath + "/" + path; + if (QFileInfo(path).isDir()) + path.append("/"); + list.append(KURL::fromPathOrURL(path)); + } + } + l = d.entryList("*", QDir::Dirs); + end = l.constEnd(); + for (QStringList::ConstIterator it = l.constBegin(); it != end; ++it) + { + if ((*it) != "." && (*it) != "..") + list += allLocalFiles(startPath + "/" + (*it), mask); + } + return list; +} + + +//Some hackery from KIO::NetAccess as they do not do exactly what we want +/* return true if the url exists*/ +bool QExtFileInfo::internalExists(const KURL& url, bool readingOnly, QWidget *window) +{ + bJobOK = true; + KURL url2 = url; + url2.adjustPath(-1); + // kdDebug(24000)<<"QExtFileInfo::internalExists"<<endl; + KIO::StatJob * job = KIO::stat(url2, false); + job->setWindow(window); + job->setDetails(0); + job->setSide(readingOnly); + connect( job, SIGNAL( result (KIO::Job *) ), + this, SLOT( slotResult (KIO::Job *) ) ); + + //To avoid lock-ups, start a timer. + QTimer::singleShot(60*1000, this,SLOT(slotTimeout())); + //kdDebug(24000)<<"QExtFileInfo::internalExists:before enter_loop"<<endl; + enter_loop(); + //kdDebug(24000)<<"QExtFileInfo::internalExists:after enter_loop"<<endl; + return bJobOK; +} + +bool QExtFileInfo::internalCopy(const KURL& src, const KURL& target, int permissions, + bool overwrite, bool resume, QWidget* window) +{ + bJobOK = true; // success unless further error occurs + + KIO::Scheduler::checkSlaveOnHold(true); + KIO::Job * job = KIO::file_copy( src, target, permissions, overwrite, resume, false ); +// KIO::Job * job2 = KIO::del(target, false ); + //job2->setWindow (window); + //connect( job2, SIGNAL( result (KIO::Job *) ), +// this, SLOT( slotResult (KIO::Job *) ) ); + + //enter_loop(); + //if (bJobOK) + { +// kdDebug(24000) << "Copying " << src << " to " << target << endl; + // KIO::Job *job = KIO::copy( src, target, false ); + job->setWindow (window); + connect( job, SIGNAL( result (KIO::Job *) ), + this, SLOT( slotResult (KIO::Job *) ) ); + enter_loop(); + } + return bJobOK; +} + + +void qt_enter_modal( QWidget *widget ); +void qt_leave_modal( QWidget *widget ); + +void QExtFileInfo::enter_loop() +{ + QWidget dummy(0,0,WType_Dialog | WShowModal); + dummy.setFocusPolicy( QWidget::NoFocus ); + qt_enter_modal(&dummy); + //kdDebug(24000)<<"QExtFileInfo::enter_loop:before qApp->enter_loop()"<< endl; + qApp->enter_loop(); +// kdDebug(24000)<<"QExtFileInfo::enter_loop:after qApp->enter_loop()"<<endl; + qt_leave_modal(&dummy); +} + +void QExtFileInfo::slotListResult(KIO::Job *job) +{ + m_listJobCount--; + if (m_listJobCount == 0) + slotResult(job); +} + +void QExtFileInfo::slotResult(KIO::Job *job) +{ + //kdDebug(24000)<<"QExtFileInfo::slotResult"<<endl; + bJobOK = !job->error(); + if ( !bJobOK ) + { + if ( !lastErrorMsg ) + lastErrorMsg = job->errorString(); + } + if ( job->isA("KIO::StatJob") ) + m_entry = static_cast<KIO::StatJob *>(job)->statResult(); + qApp->exit_loop(); +} + +void QExtFileInfo::slotNewEntries(KIO::Job *job, const KIO::UDSEntryList& udsList) +{ + KURL url = static_cast<KIO::ListJob *>(job)->url(); + url.adjustPath(-1); + // avoid creating these QStrings again and again + static const QString& dot = KGlobal::staticQString("."); + static const QString& dotdot = KGlobal::staticQString(".."); + + KIO::UDSEntryListConstIterator it = udsList.begin(); + KIO::UDSEntryListConstIterator end = udsList.end(); + KURL itemURL; + QPtrList<KFileItem> linkItems; + linkItems.setAutoDelete(true); + for ( ; it != end; ++it ) + { + QString name; + + // find out about the name + KIO::UDSEntry::ConstIterator entit = (*it).begin(); + for( ; entit != (*it).end(); ++entit ) + if ((*entit).m_uds == KIO::UDS_NAME) + { + name = (*entit).m_str; + break; + } + + if (!name.isEmpty() && name != dot && name != dotdot) + { + KFileItem* item = new KFileItem( *it, url, false, true ); + if (item->isDir() && item->isLink()) + { + KURL u = item->url(); + QString linkDest = item->linkDest(); + kdDebug(24000) << "Got link: " << name << " Points to:" << linkDest << endl; + if (linkDest.startsWith("./") || linkDest.startsWith("../") ) + { + u.setPath(u.directory(false, true) + linkDest); + u.cleanPath(); + } + else + u.setPath(linkDest); + u.adjustPath(+1); + if (!dirListItems.contains(u) && u.url() != m_listStartURL && !u.isParentOf(item->url())) + { + linkItems.append(new KFileItem(*item)); + } else + { + kdDebug(24000) << "Recursive link " << u.url() << endl; + continue; + } + } + itemURL = item->url(); + if (item->isDir()) + itemURL.adjustPath(1); + for (QPtrListIterator<QRegExp> filterIt(lstFilters); filterIt.current(); ++filterIt ) + { + if (filterIt.current()->exactMatch(item->text())) + dirListItems.append(itemURL); + } + delete item; + } + } + for (QPtrList<KFileItem>::ConstIterator it = linkItems.constBegin(); it != linkItems.constEnd(); ++it) + { + KIO::ListJob *ljob = KIO::listRecursive((*it)->url(), false, true); + m_listJobCount++; + //kdDebug(24000) << "Now listing: " << (*it)->url() << endl; + connect( ljob, SIGNAL(entries(KIO::Job *,const KIO::UDSEntryList &)), + this,SLOT (slotNewEntries(KIO::Job *,const KIO::UDSEntryList &))); + connect( ljob, SIGNAL(result(KIO::Job *)), + this,SLOT (slotListResult(KIO::Job *))); + } +} + +void QExtFileInfo::slotNewDetailedEntries(KIO::Job *job, const KIO::UDSEntryList& udsList) +{ + KURL url = static_cast<KIO::ListJob *>(job)->url(); + url.adjustPath(-1); + // avoid creating these QStrings again and again + static const QString& dot = KGlobal::staticQString("."); + static const QString& dotdot = KGlobal::staticQString(".."); + + KIO::UDSEntryListConstIterator it = udsList.begin(); + KIO::UDSEntryListConstIterator end = udsList.end(); + KURL itemURL; + QPtrList<KFileItem> linkItems; + linkItems.setAutoDelete(true); + for ( ; it != end; ++it ) + { + QString name; + + // find out about the name + KIO::UDSEntry::ConstIterator entit = (*it).begin(); + for( ; entit != (*it).end(); ++entit ) + if ((*entit).m_uds == KIO::UDS_NAME) + { + name = (*entit).m_str; + break; + } + + if (!name.isEmpty() && name != dot && name != dotdot) + { + KFileItem *item= new KFileItem(*it, url, false, true ); + if (item->isDir() && item->isLink()) + { + KURL u = item->url(); + u.setPath(item->linkDest()); + QString urlStr = u.url(); + if (detailedDirListItems.find(urlStr) == 0L && + (urlStr != m_listStartURL)) + { + linkItems.append(new KFileItem(*item)); + } else + { + kdDebug(24000) << "Recursive link" << item->url() << endl; + continue; + } + } + bool added = false; + for (QPtrListIterator<QRegExp> filterIt( lstFilters ); filterIt.current(); ++filterIt) + if (filterIt.current()->exactMatch(item->text())) + { + detailedDirListItems.insert(item->url().url(), item); + added = true; + } + if (!added) + delete item; + } + } + for (QPtrList<KFileItem>::ConstIterator it = linkItems.constBegin(); it != linkItems.constEnd(); ++it) + { + KIO::ListJob *ljob = KIO::listRecursive((*it)->url(), false, true); + m_listJobCount++; + // kdDebug(24000) << "Now listing: " << (*it)->url() << endl; + connect( ljob, SIGNAL(entries(KIO::Job *,const KIO::UDSEntryList &)), + this,SLOT (slotNewDetailedEntries(KIO::Job *,const KIO::UDSEntryList &))); + connect( ljob, SIGNAL(result(KIO::Job *)), + this,SLOT (slotListResult(KIO::Job *))); + } +} + +/** Timeout occurred while waiting for some network function to return. */ +void QExtFileInfo::slotTimeout() +{ + bJobOK = false; + qApp->exit_loop(); +} +#include "qextfileinfo.moc" diff --git a/lib/qextfileinfo.h b/lib/qextfileinfo.h new file mode 100644 index 00000000..dd05cb41 --- /dev/null +++ b/lib/qextfileinfo.h @@ -0,0 +1,119 @@ +/* + From WebMaker - KDE HTML Editor + Copyright (C) 1998, 1999 Alexei Dets <dets@services.ru> + Rewritten for Quanta Plus: (C) 2002 Andras Mantia <amantia@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. +*/ + +#ifndef _QEXTFILEINFO_H_ +#define _QEXTFILEINFO_H_ + +#include <kio/global.h> +#include <kio/job.h> +#include <kurl.h> +#include <kfileitem.h> + +#include <qobject.h> +#include <qptrlist.h> +#include <qdict.h> +#include <qregexp.h> + +class QExtFileInfo:public QObject +{ + Q_OBJECT +public: + QExtFileInfo() {}; + ~QExtFileInfo() {}; + + /** + * Works like QDir::canonicalPath, but it does not return an empty + * string if the path does not exists, but tries to find if there + * is a part of the path which exists and resolv the symlinks for + * that part. The ending slash is kept in the result. + * Example: + * /home/user/foo points to /mnt/foo + * /home/user/foo/foo2 does not exists + * QExtFileInfo::canonicalPath("/home/user/foo/foo2/") will return + * /mnt/foo/foo2/ . + * @param path the path to resolve + * @return the canonical path (symlinks resolved) + */ + static QString canonicalPath(const QString& path); + + /** + * Similar to QDir::homeDirPath(), but returns a resolved path. + * + */ + static QString homeDirPath(); + + /** Returns the relative url of urlToConvert to baseURL. */ + static KURL toRelative(const KURL& urlToConvert, const KURL& baseURL, bool resolveSymlinks = true); + /** Convert relative url to absolute, based on baseURL. */ + static KURL toAbsolute(const KURL& urlToConvert, const KURL& baseURL); + /** Returns a recursive list of files under path, matching the specified file mask. */ + static KURL::List allFiles( const KURL& path, const QString &mask, QWidget *window); + /** Returns a recursive list of files under path, matching the specified file mask. + The returned urls are relative to path. + */ + static KURL::List allFilesRelative( const KURL& path, const QString &mask, QWidget *window, bool resolveSymlinks = true); + /** Returns a recursive list of files under path, matching the specified file mask. + The returned list contains detailed information about each url. + The user should delete the KFileItems and clear the dict + after they are not needed. + */ + static QDict<KFileItem> allFilesDetailed(const KURL& path, const QString &mask, QWidget *window); + /** Creates a dir if don't exists. */ + static bool createDir(const KURL & path, QWidget *window); + /** Returns the parent directory of dir. */ + static KURL cdUp(const KURL &dir); + /** Returns the filename from a path string. */ + static QString shortName(const QString &fname ); + /** Returns the path to the url. */ + static KURL path(const KURL &); + /** Returns the user's home directory as an url. */ + static KURL home(); + /** A slightly better working alternative of KIO::NetAccess::exists(). + Checks for the existance of the url. readingOnly is true if we check if + the url is readable, and false if we check if it is writable.*/ + static bool exists(const KURL& url, bool readingOnly, QWidget *window); + /** Synchronous copy, like NetAccess::file_copy in KDE 3.2, just that it doesn't show a progress dialog */ + static bool copy( const KURL& src, const KURL& dest, int permissions=-1, + bool overwrite=false, bool resume=false, QWidget* window = 0L ); + /** Reenters the event loop. You must call qApp->exit_loop() to exit it. */ + void enter_loop(); + +private: + /** Internal methods called by the above ones. They start their own event loop and + exit when the even loop is exited */ + bool internalExists(const KURL& url, bool readingOnly, QWidget *window); + bool internalCopy(const KURL& src, const KURL& target, int permissions, + bool overwrite, bool resume, QWidget* window); + KURL::List allFilesInternal(const KURL& startURL, const QString& mask, QWidget *window); + QDict<KFileItem> allFilesDetailedInternal(const KURL& startURL, const QString& mask, QWidget *window); + KURL::List allLocalFiles(const QString& startPath, const QString& mask); + + bool bJobOK; + static QString lastErrorMsg; + KIO::UDSEntry m_entry; + KURL::List dirListItems; + QDict<KFileItem> detailedDirListItems; + QPtrList<QRegExp> lstFilters; + int m_listJobCount; + QString m_listStartURL; + +private slots: + void slotListResult(KIO::Job *job); + void slotResult(KIO::Job * job); + void slotNewEntries(KIO::Job *job, const KIO::UDSEntryList& udsList); + void slotNewDetailedEntries(KIO::Job *job, const KIO::UDSEntryList& udsList); +public slots: + /** Timeout occurred while waiting for some network function to return. */ + void slotTimeout(); +}; + + +#endif |