/**************************************************************************** ** ** Implementation of the TQWorkspace class ** ** Created : 931107 ** ** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. ** ** This file is part of the workspace module of the TQt GUI Toolkit. ** ** This file may be used under the terms of the GNU General ** Public License versions 2.0 or 3.0 as published by the Free ** Software Foundation and appearing in the files LICENSE.GPL2 ** and LICENSE.GPL3 included in the packaging of this file. ** Alternatively you may (at your option) use any later version ** of the GNU General Public License if such license has been ** publicly approved by Trolltech ASA (or its successors, if any) ** and the KDE Free TQt Foundation. ** ** Please review the following information to ensure GNU General ** Public Licensing requirements will be met: ** http://trolltech.com/products/qt/licenses/licensing/opensource/. ** If you are unsure which license is appropriate for your use, please ** review the following information: ** http://trolltech.com/products/qt/licenses/licensing/licensingoverview ** or contact the sales department at sales@trolltech.com. ** ** This file may be used under the terms of the Q Public License as ** defined by Trolltech ASA and appearing in the file LICENSE.TQPL ** included in the packaging of this file. Licensees holding valid TQt ** Commercial licenses may use this file in accordance with the TQt ** Commercial License Agreement provided with the Software. ** ** This file is provided "AS IS" with NO WARRANTY OF ANY KIND, ** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted ** herein. ** **********************************************************************/ #include "ntqworkspace.h" #ifndef TQT_NO_WORKSPACE #include "ntqapplication.h" #include "../widgets/qtitlebar_p.h" #include "ntqobjectlist.h" #include "ntqlayout.h" #include "ntqtoolbutton.h" #include "ntqlabel.h" #include "ntqvbox.h" #include "ntqaccel.h" #include "ntqcursor.h" #include "ntqpopupmenu.h" #include "ntqmenubar.h" #include "ntqguardedptr.h" #include "ntqiconset.h" #include "../widgets/qwidgetresizehandler_p.h" #include "ntqfocusdata.h" #include "ntqdatetime.h" #include "ntqtooltip.h" #include "ntqwmatrix.h" #include "ntqimage.h" #include "ntqscrollbar.h" #include "ntqstyle.h" #include "ntqbitmap.h" // magic non-mdi things #include "ntqtimer.h" #include "ntqdockarea.h" #include "ntqstatusbar.h" #include "ntqmainwindow.h" #include "ntqdockwindow.h" #include "ntqtoolbar.h" #define BUTTON_WIDTH 16 #define BUTTON_HEIGHT 14 /*! \class TQWorkspace ntqworkspace.h \brief The TQWorkspace widget provides a workspace window that can contain decorated windows, e.g. for MDI. \module workspace \ingroup application \ingroup organizers \mainclass MDI (multiple document interface) applications typically have one main window with a menu bar and toolbar, and a central widget that is a TQWorkspace. The workspace itself contains zero, one or more document windows, each of which is a widget. The workspace itself is an ordinary TQt widget. It has a standard constructor that takes a parent widget and an object name. The parent window is usually a TQMainWindow, but it need not be. Document windows (i.e. MDI windows) are also ordinary TQt widgets which have the workspace as their parent widget. When you call show(), hide(), showMaximized(), setCaption(), etc. on a document window, it is shown, hidden, etc. with a frame, caption, icon and icon text, just as you'd expect. You can provide widget flags which will be used for the layout of the decoration or the behaviour of the widget itself. To change or retrieve the geometry of MDI windows you must operate on the MDI widget's parentWidget(). (The parentWidget() provides access to the decorated window in which the MDI window's widget is shown.) A document window becomes active when it gets the keyboard focus. You can also activate a window in code using setFocus(). The user can activate a window by moving focus in the usual ways, for example by clicking a window or by pressing Tab. The workspace emits a signal windowActivated() when it detects the activation change, and the function activeWindow() always returns a pointer to the active document window. The convenience function windowList() returns a list of all document windows. This is useful to create a popup menu "Windows" on the fly, for example. TQWorkspace provides two built-in layout strategies for child windows: cascade() and tile(). Both are slots so you can easily connect menu entries to them. If you want your users to be able to work with document windows larger than the actual workspace, set the scrollBarsEnabled property to TRUE. If the top-level window contains a menu bar and a document window is maximised, TQWorkspace moves the document window's minimize, restore and close buttons from the document window's frame to the workspace window's menu bar. It then inserts a window operations menu at the far left of the menu bar. */ static bool inCaptionChange = FALSE; class TQWorkspaceChild : public TQFrame { TQ_OBJECT friend class TQWorkspace; friend class TQTitleBar; public: TQWorkspaceChild( TQWidget* window, TQWorkspace* parent=0, const char* name=0 ); ~TQWorkspaceChild(); void setActive( bool ); bool isActive() const; void adjustToFullscreen(); void setStatusBar(TQStatusBar *); TQWidget* windowWidget() const; TQWidget* iconWidget() const; void doResize(); void doMove(); TQSize sizeHint() const; TQSize minimumSizeHint() const; TQSize baseSize() const; signals: void showOperationMenu(); void popupOperationMenu( const TQPoint& ); public slots: void activate(); void showMinimized(); void showMaximized(); void showNormal(); void showShaded(); void setCaption( const TQString& ); void internalRaise(); void titleBarDoubleClicked(); void move( int x, int y ); protected: bool event(TQEvent * ); void enterEvent( TQEvent * ); void leaveEvent( TQEvent * ); void childEvent( TQChildEvent* ); void resizeEvent( TQResizeEvent * ); void moveEvent( TQMoveEvent * ); bool eventFilter( TQObject *, TQEvent * ); bool focusNextPrevChild( bool ); void drawFrame( TQPainter * ); void styleChange( TQStyle & ); private: TQWidget* childWidget; TQGuardedPtr lastfocusw; TQWidgetResizeHandler *widgetResizeHandler; TQTitleBar* titlebar; TQGuardedPtr statusbar; TQGuardedPtr iconw; TQSize windowSize; TQSize shadeRestore; TQSize shadeRestoreMin; bool act :1; bool shademode :1; bool snappedRight :1; bool snappedDown :1; #if defined(TQ_DISABLE_COPY) // Disabled copy constructor and operator= TQWorkspaceChild( const TQWorkspaceChild & ); TQWorkspaceChild &operator=( const TQWorkspaceChild & ); #endif }; class TQMainWindow; class TQWorkspacePrivate { public: TQWorkspaceChild* active; TQPtrList windows; TQPtrList focus; TQPtrList icons; TQWorkspaceChild* maxWindow; TQRect maxRestore; TQGuardedPtr maxcontrols; TQGuardedPtr maxmenubar; int px; int py; TQWidget *becomeActive; TQGuardedPtr maxtools; TQPopupMenu* popup; TQPopupMenu* toolPopup; int menuId; int controlId; TQString topCaption; TQScrollBar *vbar, *hbar; TQWidget *corner; int yoffset, xoffset; // toplevel mdi fu TQWorkspace::WindowMode wmode; TQGuardedPtr mainwindow; TQPtrList dockwindows, newdocks; }; static bool isChildOf( TQWidget * child, TQWidget * parent ) { if ( !parent || !child ) return FALSE; TQWidget * w = child; while( w && w != parent ) w = w->parentWidget(); return w != 0; } /*! Constructs a workspace with a \a parent and a \a name. */ TQWorkspace::TQWorkspace( TQWidget *parent, const char *name ) : TQWidget( parent, name ) { init(); } #ifdef QT_WORKSPACE_WINDOWMODE /*! Constructs a workspace with a \a parent and a \a name. This constructor will also set the WindowMode to \a mode. \sa windowMode() */ TQWorkspace::TQWorkspace( TQWorkspace::WindowMode mode, TQWidget *parent, const char *name ) : TQWidget( parent, name ) { init(); d->wmode = mode; } #endif /*! \internal */ void TQWorkspace::init() { d = new TQWorkspacePrivate; d->maxcontrols = 0; d->active = 0; d->maxWindow = 0; d->maxtools = 0; d->px = 0; d->py = 0; d->becomeActive = 0; #if defined( QT_WORKSPACE_WINDOWMODE ) && defined( TQ_WS_MAC ) d->wmode = AutoDetect; #else d->wmode = MDI; #endif d->mainwindow = 0; #if defined(TQ_WS_WIN) d->popup = new TQPopupMenu( this, "qt_internal_mdi_popup" ); d->toolPopup = new TQPopupMenu( this, "qt_internal_mdi_popup" ); #else d->popup = new TQPopupMenu( parentWidget(), "qt_internal_mdi_popup" ); d->toolPopup = new TQPopupMenu( parentWidget(), "qt_internal_mdi_popup" ); #endif d->menuId = -1; d->controlId = -1; connect( d->popup, TQ_SIGNAL( aboutToShow() ), this, TQ_SLOT(operationMenuAboutToShow() )); connect( d->popup, TQ_SIGNAL( activated(int) ), this, TQ_SLOT( operationMenuActivated(int) ) ); d->popup->insertItem(TQIconSet(style().stylePixmap(TQStyle::SP_TitleBarNormalButton)), tr("&Restore"), 1); d->popup->insertItem(tr("&Move"), 2); d->popup->insertItem(tr("&Size"), 3); d->popup->insertItem(TQIconSet(style().stylePixmap(TQStyle::SP_TitleBarMinButton)), tr("Mi&nimize"), 4); d->popup->insertItem(TQIconSet(style().stylePixmap(TQStyle::SP_TitleBarMaxButton)), tr("Ma&ximize"), 5); d->popup->insertSeparator(); d->popup->insertItem(TQIconSet(style().stylePixmap(TQStyle::SP_TitleBarCloseButton)), tr("&Close") #ifndef TQT_NO_ACCEL +"\t"+TQAccel::keyToString(CTRL+Key_F4) #endif , this, TQ_SLOT( closeActiveWindow() ) ); connect( d->toolPopup, TQ_SIGNAL( aboutToShow() ), this, TQ_SLOT(toolMenuAboutToShow() )); connect( d->toolPopup, TQ_SIGNAL( activated(int) ), this, TQ_SLOT( operationMenuActivated(int) ) ); d->toolPopup->insertItem(tr("&Move"), 2); d->toolPopup->insertItem(tr("&Size"), 3); d->toolPopup->insertItem(tr("Stay on &Top"), 7); d->toolPopup->setItemChecked( 7, TRUE ); d->toolPopup->setCheckable( TRUE ); d->toolPopup->insertSeparator(); d->toolPopup->insertItem(TQIconSet(style().stylePixmap(TQStyle::SP_TitleBarShadeButton)), tr("Sh&ade"), 6); d->toolPopup->insertItem(TQIconSet(style().stylePixmap(TQStyle::SP_TitleBarCloseButton)), tr("&Close") #ifndef TQT_NO_ACCEL +"\t"+TQAccel::keyToString( CTRL+Key_F4) #endif , this, TQ_SLOT( closeActiveWindow() ) ); #ifndef TQT_NO_ACCEL TQAccel* a = new TQAccel( this ); a->connectItem( a->insertItem( ALT + Key_Minus), this, TQ_SLOT( showOperationMenu() ) ); a->connectItem( a->insertItem( CTRL + Key_F6), this, TQ_SLOT( activateNextWindow() ) ); a->connectItem( a->insertItem( CTRL + Key_Tab), this, TQ_SLOT( activateNextWindow() ) ); a->connectItem( a->insertItem( Key_Forward ), this, TQ_SLOT( activateNextWindow() ) ); a->connectItem( a->insertItem( CTRL + SHIFT + Key_F6), this, TQ_SLOT( activatePreviousWindow() ) ); a->connectItem( a->insertItem( CTRL + SHIFT + Key_Tab), this, TQ_SLOT( activatePreviousWindow() ) ); a->connectItem( a->insertItem( Key_Back ), this, TQ_SLOT( activatePreviousWindow() ) ); a->connectItem( a->insertItem( CTRL + Key_F4 ), this, TQ_SLOT( closeActiveWindow() ) ); #endif setBackgroundMode( PaletteDark ); setSizePolicy( TQSizePolicy( TQSizePolicy::Expanding, TQSizePolicy::Expanding ) ); #ifndef TQT_NO_WIDGET_TOPEXTRA d->topCaption = topLevelWidget()->caption(); #endif d->hbar = d->vbar = 0; d->corner = 0; d->xoffset = d->yoffset = 0; updateWorkspace(); topLevelWidget()->installEventFilter( this ); } /*! Destroys the workspace and frees any allocated resources. */ TQWorkspace::~TQWorkspace() { delete d; d = 0; } /*!\reimp */ TQSize TQWorkspace::sizeHint() const { TQSize s( TQApplication::desktop()->size() ); return TQSize( s.width()*2/3, s.height()*2/3); } /*! \reimp */ void TQWorkspace::setPaletteBackgroundColor( const TQColor & c ) { setEraseColor( c ); } /*! \reimp */ void TQWorkspace::setPaletteBackgroundPixmap( const TQPixmap & pm ) { setErasePixmap( pm ); } /*! \reimp */ void TQWorkspace::childEvent( TQChildEvent * e) { if (e->inserted() && e->child()->isWidgetType()) { TQWidget* w = (TQWidget*) e->child(); if ( !w || !w->testWFlags( WStyle_Title | WStyle_NormalBorder | WStyle_DialogBorder) || w->testWFlags(WType_Dialog) || d->icons.contains( w ) || w == d->vbar || w == d->hbar || w == d->corner ) return; // nothing to do bool wasMaximized = w->isMaximized(); bool wasMinimized = w->isMinimized(); bool hasBeenHidden = w->isHidden(); bool hasSize = w->testWState( WState_Resized ); int x = w->x(); int y = w->y(); bool hasPos = x != 0 || y != 0; TQSize s = w->size().expandedTo( w->minimumSizeHint() ); if ( !hasSize && w->sizeHint().isValid() ) w->adjustSize(); TQWorkspaceChild* child = new TQWorkspaceChild( w, this, "qt_workspacechild" ); child->installEventFilter( this ); connect( child, TQ_SIGNAL( popupOperationMenu(const TQPoint&) ), this, TQ_SLOT( popupOperationMenu(const TQPoint&) ) ); connect( child, TQ_SIGNAL( showOperationMenu() ), this, TQ_SLOT( showOperationMenu() ) ); d->windows.append( child ); if ( child->isVisibleTo( this ) ) d->focus.append( child ); child->internalRaise(); if ( !hasPos ) place( child ); if ( hasSize ) child->resize( s + child->baseSize() ); else child->adjustSize(); if ( hasPos ) child->move( x, y ); if ( hasBeenHidden ) w->hide(); else if ( !isVisible() ) // that's a case were we don't receive a showEvent in time. Tricky. child->show(); if ( wasMaximized ) w->showMaximized(); else if ( wasMinimized ) w->showMinimized(); else if (!hasBeenHidden) activateWindow( w ); updateWorkspace(); } else if (e->removed() ) { if ( d->windows.contains( (TQWorkspaceChild*)e->child() ) ) { d->windows.removeRef( (TQWorkspaceChild*)e->child() ); d->focus.removeRef( (TQWorkspaceChild*)e->child() ); if (d->maxWindow == e->child()) d->maxWindow = 0; updateWorkspace(); } } } /*! \reimp */ #ifndef TQT_NO_WHEELEVENT void TQWorkspace::wheelEvent( TQWheelEvent *e ) { if ( !scrollBarsEnabled() ) return; if ( d->vbar && d->vbar->isVisible() && !( e->state() & AltButton ) ) TQApplication::sendEvent( d->vbar, e ); else if ( d->hbar && d->hbar->isVisible() ) TQApplication::sendEvent( d->hbar, e ); } #endif void TQWorkspace::activateWindow( TQWidget* w, bool change_focus ) { if ( !w ) { d->active = 0; emit windowActivated( 0 ); return; } if ( d->wmode == MDI && !isVisibleTo( 0 ) ) { d->becomeActive = w; return; } if ( d->active && d->active->windowWidget() == w ) { if ( !isChildOf( focusWidget(), w ) ) // child window does not have focus d->active->setActive( TRUE ); return; } d->active = 0; // First deactivate all other workspace clients TQPtrListIterator it( d->windows ); while ( it.current () ) { TQWorkspaceChild* c = it.current(); ++it; if(windowMode() == TQWorkspace::TopLevel && c->isTopLevel() && c->windowWidget() == w && !c->isActive()) c->setActiveWindow(); if (c->windowWidget() == w) d->active = c; else c->setActive( FALSE ); } if (!d->active) return; // Then activate the new one, so the focus is stored correctly d->active->setActive( TRUE ); if (!d->active) return; if ( d->maxWindow && d->maxWindow != d->active && d->active->windowWidget() && d->active->windowWidget()->testWFlags( WStyle_MinMax ) && !d->active->windowWidget()->testWFlags( WStyle_Tool ) ) { d->active->showMaximized(); if ( d->maxtools ) { #ifndef TQT_NO_WIDGET_TOPEXTRA if ( w->icon() ) { TQPixmap pm(*w->icon()); int iconSize = d->maxtools->size().height(); if(pm.width() > iconSize || pm.height() > iconSize) { TQImage im; im = pm; pm = im.smoothScale( TQMIN(iconSize, pm.width()), TQMIN(iconSize, pm.height()) ); } d->maxtools->setPixmap( pm ); } else #endif { TQPixmap pm(14,14); pm.fill( color1 ); pm.setMask(pm.createHeuristicMask()); d->maxtools->setPixmap( pm ); } } } else { // done implicitly in maximizeWindow otherwise d->active->internalRaise(); } if ( change_focus ) { if ( d->focus.find( d->active ) >=0 ) { d->focus.removeRef( d->active ); d->focus.append( d->active ); } } updateWorkspace(); emit windowActivated( w ); } /*! Returns the active window, or 0 if no window is active. */ TQWidget* TQWorkspace::activeWindow() const { return d->active?d->active->windowWidget():0; } void TQWorkspace::place( TQWidget* w) { TQPtrList widgets; for(TQPtrListIterator it( d->windows ); it.current(); ++it) if ((*it) != w) widgets.append((*it)); if(d->wmode == TopLevel) { for(TQPtrListIterator it( d->dockwindows ); it.current(); ++it) if ((*it) != w) widgets.append((*it)); } int overlap, minOverlap = 0; int possible; TQRect r1(0, 0, 0, 0); TQRect r2(0, 0, 0, 0); TQRect maxRect = rect(); if(d->wmode == TopLevel) { const TQDesktopWidget *dw = tqApp->desktop(); maxRect = dw->availableGeometry(dw->screenNumber(topLevelWidget())); } int x = maxRect.left(), y = maxRect.top(); TQPoint wpos(maxRect.left(), maxRect.top()); bool firstPass = TRUE; do { if ( y + w->height() > maxRect.bottom() ) { overlap = -1; } else if( x + w->width() > maxRect.right() ) { overlap = -2; } else { overlap = 0; r1.setRect(x, y, w->width(), w->height()); TQWidget *l; TQPtrListIterator it( widgets ); while ( it.current () ) { l = it.current(); ++it; if ( d->maxWindow == l ) r2 = d->maxRestore; else r2.setRect(l->x(), l->y(), l->width(), l->height()); if (r2.intersects(r1)) { r2.setCoords(TQMAX(r1.left(), r2.left()), TQMAX(r1.top(), r2.top()), TQMIN(r1.right(), r2.right()), TQMIN(r1.bottom(), r2.bottom()) ); overlap += (r2.right() - r2.left()) * (r2.bottom() - r2.top()); } } } if (overlap == 0) { wpos = TQPoint(x, y); break; } if (firstPass) { firstPass = FALSE; minOverlap = overlap; } else if ( overlap >= 0 && overlap < minOverlap) { minOverlap = overlap; wpos = TQPoint(x, y); } if ( overlap > 0 ) { possible = maxRect.right(); if ( possible - w->width() > x) possible -= w->width(); TQWidget *l; TQPtrListIterator it( widgets ); while ( it.current () ) { l = it.current(); ++it; if ( d->maxWindow == l ) r2 = d->maxRestore; else r2.setRect(l->x(), l->y(), l->width(), l->height()); if( ( y < r2.bottom() ) && ( r2.top() < w->height() + y ) ) { if( r2.right() > x ) possible = possible < r2.right() ? possible : r2.right(); if( r2.left() - w->width() > x ) possible = possible < r2.left() - w->width() ? possible : r2.left() - w->width(); } } x = possible; } else if ( overlap == -2 ) { x = maxRect.left(); possible = maxRect.bottom(); if ( possible - w->height() > y ) possible -= w->height(); TQWidget *l; TQPtrListIterator it( widgets ); while ( it.current () ) { l = it.current(); ++it; if ( d->maxWindow == l ) r2 = d->maxRestore; else r2.setRect(l->x(), l->y(), l->width(), l->height()); if( r2.bottom() > y) possible = possible < r2.bottom() ? possible : r2.bottom(); if( r2.top() - w->height() > y ) possible = possible < r2.top() - w->height() ? possible : r2.top() - w->height(); } y = possible; } } while( overlap != 0 && overlap != -1 ); #if 0 if(windowMode() == TQWorkspace::TopLevel && wpos.y()) { TQPoint fr = w->topLevelWidget()->frameGeometry().topLeft(), r = w->topLevelWidget()->geometry().topLeft(); wpos += TQPoint(r.x() - fr.x(), r.y() - fr.y()); } #endif w->move(wpos); updateWorkspace(); } void TQWorkspace::insertIcon( TQWidget* w ) { if ( !w || d->icons.contains( w ) ) return; d->icons.append( w ); if (w->parentWidget() != this ) w->reparent( this, 0, TQPoint(0,0), FALSE); TQRect cr = updateWorkspace(); int x = 0; int y = cr.height() - w->height(); TQPtrListIterator it( d->icons ); while ( it.current () ) { TQWidget* i = it.current(); ++it; if ( x > 0 && x + i->width() > cr.width() ){ x = 0; y -= i->height(); } if ( i != w && i->geometry().intersects( TQRect( x, y, w->width(), w->height() ) ) ) x += i->width(); } w->move( x, y ); if ( isVisibleTo( parentWidget() ) ) { w->show(); w->lower(); } updateWorkspace(); } void TQWorkspace::removeIcon( TQWidget* w) { if ( !d->icons.contains( w ) ) return; d->icons.remove( w ); w->hide(); } /*! \reimp */ void TQWorkspace::resizeEvent( TQResizeEvent * ) { if ( d->maxWindow ) { d->maxWindow->adjustToFullscreen(); if (d->maxWindow->windowWidget()) ((TQWorkspace*)d->maxWindow->windowWidget())->setWState( WState_Maximized ); } TQRect cr = updateWorkspace(); TQPtrListIterator it( d->windows ); while ( it.current () ) { TQWorkspaceChild* c = it.current(); ++it; if ( c->windowWidget() && !c->windowWidget()->testWFlags( WStyle_Tool ) ) continue; int x = c->x(); int y = c->y(); if ( c->snappedDown ) y = cr.height() - c->height(); if ( c->snappedRight ) x = cr.width() - c->width(); if ( x != c->x() || y != c->y() ) c->move( x, y ); } } void TQWorkspace::handleUndock(TQDockWindow *w) { const TQDesktopWidget *dw = tqApp->desktop(); TQRect maxRect = dw->availableGeometry(dw->screenNumber(d->mainwindow)); TQPoint wpos(maxRect.left(), maxRect.top()); int possible = 0; if(!::tqt_cast(w)) { struct place_score { int o, x, y; } score = {0, 0, 0}; int left = 1, x = wpos.x(), y = wpos.y(); TQPtrListIterator it( d->dockwindows ); while(1) { if(y + w->height() > maxRect.bottom()) { if(left) { x = maxRect.right() - w->width(); y = maxRect.top(); left = 0; } else { break; } } TQDockWindow *l, *nearest = NULL, *furthest; for ( it.toFirst(); it.current(); ++it ) { l = it.current(); if ( l != w && y == l->y() ) { if(!nearest) { nearest = l; } else if(l->x() == x) { nearest = l; break; } else if(left && (l->x() - x) < (nearest->x() - x)) { nearest = l; } else if(!left && (x - l->x()) < (x - nearest->x())) { nearest = l; } } } TQRect r2(x, y, w->width(), w->height()); if(!nearest || !nearest->geometry().intersects(r2)) { wpos = TQPoint(x, y); //best possible outcome possible = 2; break; } TQDockWindow *o = NULL; int overlap = 0; for( it.toFirst(); it.current(); ++it ) { l = it.current(); if ( l != w && l->geometry().intersects(TQRect(TQPoint(x, y), w->size()))) { overlap++; o = l; } } if(o && overlap == 1 && w->isVisible() && !o->isVisible()) { wpos = TQPoint(x, y); possible = 2; while(d->dockwindows.remove(o)); d->newdocks.append(o); if(d->newdocks.count() == 1) TQTimer::singleShot(0, this, TQ_SLOT(dockWindowsShow())); break; } for ( furthest = nearest, it.toFirst(); it.current(); ++it ) { l = it.current(); if ( l != w && l->y() == nearest->y() && ((left && (l->x() == nearest->x() + nearest->width())) || (!left && (l->x() + l->width() == nearest->x()) ))) furthest = l; } if(left) x = furthest->x() + furthest->width(); else x = furthest->x() - w->width(); TQPoint sc_pt(x, y); place_score sc; if(left) sc.x = (x + w->width()) * 2; else sc.x = ((maxRect.width() - x) * 2) + 1; sc.y = sc_pt.y(); for( sc.o = 0, it.toFirst(); it.current(); ++it ) { l = it.current(); if ( l != w && l->geometry().intersects(TQRect(sc_pt, w->size()))) sc.o++; } if(maxRect.contains(TQRect(sc_pt, w->size())) && (!possible || (sc.o < score.o) || ((score.o || sc.o == score.o) && score.x < sc.x))) { wpos = sc_pt; score = sc; possible = 1; } y += nearest->height(); if(left) x = maxRect.x(); else x = maxRect.right() - w->width(); } if(!possible || (possible == 1 && score.o)) { //fallback to less knowledgeable function place(w); wpos = w->pos(); } } bool ishidden = w->isHidden(); TQSize olds(w->size()); if(w->place() == TQDockWindow::InDock) w->undock(); w->move(wpos); w->resize(olds); if(!ishidden) w->show(); else w->hide(); } void TQWorkspace::dockWindowsShow() { TQPtrList lst = d->newdocks; d->newdocks.clear(); for(TQPtrListIterator dw_it(lst); (*dw_it); ++dw_it) { if(d->dockwindows.find((*dw_it)) != -1) continue; handleUndock((*dw_it)); d->dockwindows.append((*dw_it)); } } /*! \reimp */ void TQWorkspace::showEvent( TQShowEvent *e ) { /* This is all magic, be carefull when playing with this code - this tries to allow people to use TQWorkspace as a high level abstraction for window management, but removes enforcement that TQWorkspace be used as an MDI. */ if(d->wmode == AutoDetect) { d->wmode = MDI; TQWidget *o = topLevelWidget(); if(::tqt_cast(o)) { d->wmode = TopLevel; const TQObjectList *c = o->children(); for(TQObjectListIt it(*c); it; ++it) { if((*it)->isWidgetType() && !((TQWidget *)(*it))->isTopLevel() && !::tqt_cast(*it) && !::tqt_cast(*it) && !::tqt_cast(*it) && !(*it)->inherits("TQHideDock") && !::tqt_cast(*it) && !::tqt_cast(*it) && !::tqt_cast(*it) && !::tqt_cast(*it)) { d->wmode = MDI; break; } } } } if(d->wmode == TopLevel) { TQWidget *o = topLevelWidget(); d->mainwindow = ::tqt_cast(o); const TQObjectList children = *o->children(); for(TQObjectListIt it(children); it; ++it) { if(!(*it)->isWidgetType()) continue; TQWidget *w = (TQWidget *)(*it); if(w->isTopLevel()) continue; if(::tqt_cast(w)) { const TQObjectList *dock_c = w->children(); if(dock_c) { TQPtrList tb_list; for(TQObjectListIt dock_it(*dock_c); dock_it; ++dock_it) { if(!(*dock_it)->isWidgetType()) continue; if(::tqt_cast(*dock_it)) { tb_list.append((TQToolBar *)(*dock_it)); } else if (::tqt_cast(*dock_it)) { TQDockWindow *dw = (TQDockWindow*)(*dock_it); dw->move(dw->mapToGlobal(TQPoint(0, 0))); d->newdocks.append(dw); } else { tqDebug("not sure what to do with %s %s", (*dock_it)->className(), (*dock_it)->name()); } } if(tb_list.count() == 1) { TQToolBar *tb = tb_list.first(); tb->move(0, 0); d->newdocks.prepend(tb); } else if(tb_list.count()) { TQDockWindow *dw = new TQDockWindow(TQDockWindow::OutsideDock, w->parentWidget(), TQString("TQMagicDock_") + w->name()); dw->installEventFilter(this); dw->setResizeEnabled(TRUE); dw->setCloseMode( TQDockWindow::Always ); dw->setResizeEnabled(FALSE); #ifndef TQT_NO_WIDGET_TOPEXTRA dw->setCaption(o->caption()); #endif TQSize os(w->size()); if(w->layout() && w->layout()->hasHeightForWidth()) { w->layout()->invalidate(); os.setHeight(w->layout()->heightForWidth(os.width())); } if(!w->isHidden()) dw->show(); w->reparent(dw, TQPoint(0, 0)); dw->setWidget(w); dw->setSizePolicy(TQSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Minimum)); dw->setGeometry(0, 0, os.width(), os.height() + dw->sizeHint().height()); d->newdocks.prepend(dw); ((TQDockArea*)w)->setAcceptDockWindow(dw, FALSE); w->show(); } } w->installEventFilter(this); } else if(::tqt_cast(w)) { if(activeWindow()) { TQWorkspaceChild *c; if ( ( c = findChild(activeWindow()) ) ) c->setStatusBar((TQStatusBar*)w); } } else if(::tqt_cast(w)) { w->reparent(this, w->testWFlags(~(0)) | WType_TopLevel, w->pos()); } } dockWindowsShow(); //now place and undock windows discovered TQWidget *w = new TQWidget(NULL, "TQDoesNotExist", WType_Dialog | WStyle_Customize | WStyle_NoBorder); // if(tqApp->mainWidget() == o) // TQObject::connect(tqApp, TQ_SIGNAL(lastWindowClosed()), tqApp, TQ_SLOT(quit())); TQDesktopWidget *dw = TQApplication::desktop(); w->setGeometry(dw->availableGeometry(dw->screenNumber(o))); o->reparent(w, TQPoint(0, 0), TRUE); { TQMenuBar *mb = 0; if(::tqt_cast(o)) mb = ((TQMainWindow *)o)->menuBar(); if(!mb) mb = (TQMenuBar*)o->child(NULL, "TQMenuBar"); if(mb) mb->reparent(w, TQPoint(0, 0)); } reparent(w, TQPoint(0,0)); setGeometry(0, 0, w->width(), w->height()); #if 0 /* Hide really isn't acceptable because I need to make the rest of TQt think it is visible, so instead I set it to an empty mask. I'm not sure what problems this is going to create, hopefully everything will be happy (or not even notice since this is mostly intended for TQt/Mac) */ // w->setMask(TQRegion()); // w->show(); #else w->hide(); #endif } //done with that nastiness, on with your regularly schedueled programming.. if ( d->maxWindow && !style().styleHint(TQStyle::SH_Workspace_FillSpaceOnMaximize, this)) showMaximizeControls(); TQWidget::showEvent( e ); if ( d->becomeActive ) { activateWindow( d->becomeActive ); d->becomeActive = 0; } else if ( d->windows.count() > 0 && !d->active ) { activateWindow( d->windows.first()->windowWidget() ); } // force a frame repaint - this is a workaround for what seems to be a bug // introduced when changing the TQWidget::show() implementation. Might be // a windows bug as well though. for (TQPtrListIterator it( d->windows ); it.current(); ++it ) { TQWorkspaceChild* c = it.current(); TQApplication::postEvent(c, new TQPaintEvent(c->rect(), TRUE)); } updateWorkspace(); } /*! \reimp */ void TQWorkspace::hideEvent( TQHideEvent * ) { if ( !isVisibleTo(0) && !style().styleHint(TQStyle::SH_Workspace_FillSpaceOnMaximize, this)) hideMaximizeControls(); } void TQWorkspace::minimizeWindow( TQWidget* w) { TQWorkspaceChild* c = findChild( w ); if ( !w || ( ( w && (!w->testWFlags( WStyle_Minimize ) ) ) || w->testWFlags( WStyle_Tool) ) ) return; if ( c ) { TQWorkspace *fake = (TQWorkspace*)w; setUpdatesEnabled( FALSE ); bool wasMax = FALSE; if ( c == d->maxWindow ) { wasMax = TRUE; d->maxWindow = 0; inCaptionChange = TRUE; #ifndef TQT_NO_WIDGET_TOPEXTRA if ( !!d->topCaption ) topLevelWidget()->setCaption( d->topCaption ); #endif inCaptionChange = FALSE; if ( !style().styleHint(TQStyle::SH_Workspace_FillSpaceOnMaximize, this) ) hideMaximizeControls(); for (TQPtrListIterator it( d->windows ); it.current(); ++it ) { TQWorkspaceChild* c = it.current(); if ( c->titlebar ) c->titlebar->setMovable( TRUE ); c->widgetResizeHandler->setActive( TRUE ); } } insertIcon( c->iconWidget() ); c->hide(); if ( wasMax ) c->setGeometry( d->maxRestore ); d->focus.append( c ); activateWindow(w); setUpdatesEnabled( TRUE ); updateWorkspace(); fake->clearWState( WState_Maximized ); fake->setWState( WState_Minimized ); c->clearWState( WState_Maximized ); c->setWState( WState_Minimized ); } } void TQWorkspace::normalizeWindow( TQWidget* w) { TQWorkspaceChild* c = findChild( w ); if ( !w ) return; if ( c ) { TQWorkspace *fake = (TQWorkspace*)w; fake->clearWState( WState_Minimized | WState_Maximized ); if ( !style().styleHint(TQStyle::SH_Workspace_FillSpaceOnMaximize, this) && d->maxWindow ) { hideMaximizeControls(); } else { if ( w->minimumSize() != w->maximumSize() ) c->widgetResizeHandler->setActive( TRUE ); if ( c->titlebar ) c->titlebar->setMovable(TRUE); } fake->clearWState( WState_Minimized | WState_Maximized ); c->clearWState( WState_Minimized | WState_Maximized ); if ( c == d->maxWindow ) { c->setGeometry( d->maxRestore ); d->maxWindow = 0; #ifndef TQT_NO_WIDGET_TOPEXTRA inCaptionChange = TRUE; if ( !!d->topCaption ) topLevelWidget()->setCaption( d->topCaption ); inCaptionChange = FALSE; #endif } else { if ( c->iconw ) removeIcon( c->iconw->parentWidget() ); c->show(); } if ( !style().styleHint(TQStyle::SH_Workspace_FillSpaceOnMaximize, this)) hideMaximizeControls(); for (TQPtrListIterator it( d->windows ); it.current(); ++it ) { TQWorkspaceChild* c = it.current(); if ( c->titlebar ) c->titlebar->setMovable( TRUE ); if ( c->childWidget && c->childWidget->minimumSize() != c->childWidget->maximumSize() ) c->widgetResizeHandler->setActive( TRUE ); } activateWindow( w, TRUE ); updateWorkspace(); } } void TQWorkspace::maximizeWindow( TQWidget* w) { TQWorkspaceChild* c = findChild( w ); if ( !w || ( ( w && (!w->testWFlags( WStyle_Maximize ) ) ) || w->testWFlags( WStyle_Tool) ) ) return; if ( c ) { setUpdatesEnabled( FALSE ); if (c->iconw && d->icons.contains( c->iconw->parentWidget() ) ) normalizeWindow( w ); TQWorkspace *fake = (TQWorkspace*)w; TQRect r( c->geometry() ); c->adjustToFullscreen(); c->show(); c->internalRaise(); tqApp->sendPostedEvents( c, TQEvent::Resize ); tqApp->sendPostedEvents( c, TQEvent::Move ); tqApp->sendPostedEvents( c, TQEvent::ShowWindowRequest ); if ( d->maxWindow != c ) { if ( d->maxWindow ) d->maxWindow->setGeometry( d->maxRestore ); d->maxWindow = c; d->maxRestore = r; } activateWindow( w ); if(!style().styleHint(TQStyle::SH_Workspace_FillSpaceOnMaximize, this)) { showMaximizeControls(); } else { c->widgetResizeHandler->setActive( FALSE ); if ( c->titlebar ) c->titlebar->setMovable( FALSE ); } #ifndef TQT_NO_WIDGET_TOPEXTRA inCaptionChange = TRUE; if ( !!d->topCaption ) topLevelWidget()->setCaption( tr("%1 - [%2]") .arg(d->topCaption).arg(c->caption()) ); inCaptionChange = FALSE; #endif setUpdatesEnabled( TRUE ); updateWorkspace(); fake->clearWState( WState_Minimized ); fake->setWState( WState_Maximized ); c->clearWState( WState_Minimized ); c->setWState( WState_Maximized ); } } void TQWorkspace::showWindow( TQWidget* w) { if ( d->maxWindow && w->testWFlags( WStyle_Maximize ) && !w->testWFlags( WStyle_Tool) ) maximizeWindow(w); else if (w->isMinimized() && !w->testWFlags(WStyle_Tool)) minimizeWindow(w); else if ( !w->testWFlags( WStyle_Tool ) ) normalizeWindow(w); else w->parentWidget()->show(); if ( d->maxWindow ) d->maxWindow->internalRaise(); updateWorkspace(); } TQWorkspaceChild* TQWorkspace::findChild( TQWidget* w) { TQPtrListIterator it( d->windows ); while ( it.current () ) { TQWorkspaceChild* c = it.current(); ++it; if (c->windowWidget() == w) return c; } return 0; } /*! \obsolete \overload */ TQWidgetList TQWorkspace::windowList() const { return windowList( CreationOrder ); } /*! Returns a list of all windows. If \a order is CreationOrder (the default) the windows are listed in the order in which they had been inserted into the workspace. If \a order is StackingOrder the windows are listed in their stacking order, with the topmost window being the last window in the list. TQWidgetList is the same as TQPtrList. \sa TQPtrList */ TQWidgetList TQWorkspace::windowList( WindowOrder order ) const { TQWidgetList windows; if ( order == StackingOrder ) { const TQObjectList *cl = children(); if ( cl ) { TQObjectListIt it( *cl ); while (it.current()) { TQObject *o = it.current(); ++it; TQWorkspaceChild *c = ::tqt_cast(o); if (c && c->windowWidget()) windows.append(c->windowWidget()); } } } else { TQPtrListIterator it( d->windows ); while (it.current()) { TQWorkspaceChild* c = it.current(); ++it; if ( c->windowWidget() ) windows.append( c->windowWidget() ); } } return windows; } /*!\reimp*/ bool TQWorkspace::eventFilter( TQObject *o, TQEvent * e) { if(d->wmode == TopLevel && d->mainwindow && o->parent() == d->mainwindow) { if((e->type() == TQEvent::ChildInserted || e->type() == TQEvent::Reparent) && ::tqt_cast(o) && !((TQWidget*)o)->isVisible()) { TQChildEvent *ce = (TQChildEvent*)e; if(!::tqt_cast(ce->child())) { tqDebug("No idea what to do.."); return FALSE; } TQDockWindow *w = (TQDockWindow*)ce->child(); if(d->newdocks.find(w) == -1 && d->dockwindows.find(w) == -1) { if(::tqt_cast(w)) d->newdocks.prepend(w); else d->newdocks.append(w); if(d->newdocks.count() == 1) TQTimer::singleShot(0, this, TQ_SLOT(dockWindowsShow())); } } else if(e->type() == TQEvent::Hide && !e->spontaneous() && !tqstrncmp(o->name(), "TQMagicDock_", 11)) { // d->mainwindow->close(); } return TQWidget::eventFilter(o, e); } static TQTime* t = 0; static TQWorkspace* tc = 0; #ifndef TQT_NO_MENUBAR if ( o == d->maxtools && d->menuId != -1 ) { switch ( e->type() ) { case TQEvent::MouseButtonPress: { TQMenuBar* b = (TQMenuBar*)o->parent(); if ( !t ) t = new TQTime; if ( tc != this || t->elapsed() > TQApplication::doubleClickInterval() ) { if ( TQApplication::reverseLayout() ) { TQPoint p = b->mapToGlobal( TQPoint( b->x() + b->width(), b->y() + b->height() ) ); p.rx() -= d->popup->sizeHint().width(); popupOperationMenu( p ); } else { popupOperationMenu( b->mapToGlobal( TQPoint( b->x(), b->y() + b->height() ) ) ); } t->start(); tc = this; } else { tc = 0; closeActiveWindow(); } return TRUE; } default: break; } return TQWidget::eventFilter( o, e ); } #endif switch ( e->type() ) { case TQEvent::Hide: case TQEvent::HideToParent: if ( !o->isA( "TQWorkspaceChild" ) || !isVisible() || e->spontaneous() ) break; if ( d->active == o ) { int a = d->focus.find( d->active ); for ( ;; ) { if ( --a < 0 ) a = d->focus.count()-1; TQWorkspaceChild* c = d->focus.at( a ); if ( !c || c == o ) { if ( c && c->iconw && d->icons.contains( c->iconw->parentWidget() ) ) break; activateWindow( 0 ); break; } if ( c->isShown() ) { activateWindow( c->windowWidget(), FALSE ); break; } } } d->focus.removeRef( (TQWorkspaceChild*)o ); if ( d->maxWindow == o && d->maxWindow->isHidden() ) { d->maxWindow->setGeometry( d->maxRestore ); d->maxWindow = 0; if ( d->active ) maximizeWindow( d->active ); if ( !d->maxWindow ) { if ( style().styleHint(TQStyle::SH_Workspace_FillSpaceOnMaximize, this)) { TQWorkspaceChild *wc = (TQWorkspaceChild *)o; wc->widgetResizeHandler->setActive( TRUE ); if ( wc->titlebar ) wc->titlebar->setMovable( TRUE ); } else { hideMaximizeControls(); } #ifndef TQT_NO_WIDGET_TOPEXTRA inCaptionChange = TRUE; if ( !!d->topCaption ) topLevelWidget()->setCaption( d->topCaption ); inCaptionChange = FALSE; #endif } } updateWorkspace(); break; case TQEvent::Show: if ( o->isA("TQWorkspaceChild") && !d->focus.containsRef( (TQWorkspaceChild*)o ) ) d->focus.append( (TQWorkspaceChild*)o ); updateWorkspace(); break; case TQEvent::CaptionChange: if ( inCaptionChange ) break; #ifndef TQT_NO_WIDGET_TOPEXTRA inCaptionChange = TRUE; if ( o == topLevelWidget() ) { TQWidget *tlw = (TQWidget*)o; if ( !d->maxWindow || tlw->caption() != tr("%1 - [%2]").arg(d->topCaption).arg(d->maxWindow->caption()) ) d->topCaption = tlw->caption(); } if ( d->maxWindow && !!d->topCaption ) topLevelWidget()->setCaption( tr("%1 - [%2]") .arg(d->topCaption).arg(d->maxWindow->caption())); inCaptionChange = FALSE; #endif break; case TQEvent::Close: if ( o == topLevelWidget() ) { TQPtrListIterator it( d->windows ); while ( it.current () ) { TQWorkspaceChild* c = it.current(); ++it; if ( c->shademode ) c->showShaded(); } } else if ( ::tqt_cast(o) ) { d->popup->hide(); } updateWorkspace(); break; default: break; } return TQWidget::eventFilter( o, e); } void TQWorkspace::showMaximizeControls() { #ifndef TQT_NO_MENUBAR Q_ASSERT(d->maxWindow); TQMenuBar* b = 0; // Do a breadth-first search first on every parent, TQWidget* w = parentWidget(); TQObjectList * l = 0; while ( !l && w ) { l = w->queryList( "TQMenuBar", 0, FALSE, FALSE ); w = w->parentWidget(); if ( l && !l->count() ) { delete l; l = 0; } } // and query recursively if nothing is found. if ( !l || !l->count() ) { if ( l ) delete l; l = topLevelWidget()->queryList( "TQMenuBar", 0, 0, TRUE ); } if ( l && l->count() ) b = (TQMenuBar *)l->first(); delete l; if ( !b ) return; if ( !d->maxcontrols ) { d->maxmenubar = b; d->maxcontrols = new TQFrame( topLevelWidget(), "qt_maxcontrols" ); TQHBoxLayout* l = new TQHBoxLayout( d->maxcontrols, d->maxcontrols->frameWidth(), 0 ); if ( d->maxWindow->windowWidget() && d->maxWindow->windowWidget()->testWFlags(WStyle_Minimize) ) { TQToolButton* iconB = new TQToolButton( d->maxcontrols, "iconify" ); #ifndef TQT_NO_TOOLTIP TQToolTip::add( iconB, tr( "Minimize" ) ); #endif l->addWidget( iconB ); iconB->setFocusPolicy( NoFocus ); iconB->setIconSet(style().stylePixmap(TQStyle::SP_TitleBarMinButton)); iconB->setFixedSize(BUTTON_WIDTH, BUTTON_HEIGHT); connect( iconB, TQ_SIGNAL( clicked() ), this, TQ_SLOT( minimizeActiveWindow() ) ); } TQToolButton* restoreB = new TQToolButton( d->maxcontrols, "restore" ); #ifndef TQT_NO_TOOLTIP TQToolTip::add( restoreB, tr( "Restore Down" ) ); #endif l->addWidget( restoreB ); restoreB->setFocusPolicy( NoFocus ); restoreB->setIconSet( style().stylePixmap(TQStyle::SP_TitleBarNormalButton)); restoreB->setFixedSize(BUTTON_WIDTH, BUTTON_HEIGHT); connect( restoreB, TQ_SIGNAL( clicked() ), this, TQ_SLOT( normalizeActiveWindow() ) ); l->addSpacing( 2 ); TQToolButton* closeB = new TQToolButton( d->maxcontrols, "close" ); #ifndef TQT_NO_TOOLTIP TQToolTip::add( closeB, tr( "Close" ) ); #endif l->addWidget( closeB ); closeB->setFocusPolicy( NoFocus ); closeB->setIconSet( style().stylePixmap(TQStyle::SP_TitleBarCloseButton) ); closeB->setFixedSize(BUTTON_WIDTH, BUTTON_HEIGHT); connect( closeB, TQ_SIGNAL( clicked() ), this, TQ_SLOT( closeActiveWindow() ) ); d->maxcontrols->setFixedSize( d->maxcontrols->minimumSizeHint() ); } if ( d->controlId == -1 || b->indexOf( d->controlId ) == -1 ) { TQFrame* dmaxcontrols = d->maxcontrols; d->controlId = b->insertItem( dmaxcontrols, -1, b->count() ); } if ( !d->active && d->becomeActive ) { d->active = (TQWorkspaceChild*)d->becomeActive->parentWidget(); d->active->setActive( TRUE ); d->becomeActive = 0; emit windowActivated( d->active->windowWidget() ); } if ( d->active && ( d->menuId == -1 || b->indexOf( d->menuId ) == -1 ) ) { if ( !d->maxtools ) { d->maxtools = new TQLabel( topLevelWidget(), "qt_maxtools" ); d->maxtools->installEventFilter( this ); } #ifndef TQT_NO_WIDGET_TOPEXTRA if ( d->active->windowWidget() && d->active->windowWidget()->icon() ) { TQPixmap pm(*d->active->windowWidget()->icon()); int iconSize = d->maxcontrols->size().height(); if(pm.width() > iconSize || pm.height() > iconSize) { TQImage im; im = pm; pm = im.smoothScale( TQMIN(iconSize, pm.width()), TQMIN(iconSize, pm.height()) ); } d->maxtools->setPixmap( pm ); } else #endif { TQPixmap pm(14,14); pm.fill( color1 ); pm.setMask(pm.createHeuristicMask()); d->maxtools->setPixmap( pm ); } d->menuId = b->insertItem( d->maxtools, -1, 0 ); } #endif } void TQWorkspace::hideMaximizeControls() { #ifndef TQT_NO_MENUBAR if ( d->maxmenubar ) { int mi = d->menuId; if ( mi != -1 ) { if ( d->maxmenubar->indexOf( mi ) != -1 ) d->maxmenubar->removeItem( mi ); d->maxtools = 0; } int ci = d->controlId; if ( ci != -1 && d->maxmenubar->indexOf( ci ) != -1 ) d->maxmenubar->removeItem( ci ); } d->maxcontrols = 0; d->menuId = -1; d->controlId = -1; #endif } /*! Closes the child window that is currently active. \sa closeAllWindows() */ void TQWorkspace::closeActiveWindow() { setUpdatesEnabled( FALSE ); if ( d->maxWindow && d->maxWindow->windowWidget() ) d->maxWindow->windowWidget()->close(); else if ( d->active && d->active->windowWidget() ) d->active->windowWidget()->close(); setUpdatesEnabled( TRUE ); updateWorkspace(); } /*! Closes all child windows. The windows are closed in random order. The operation stops if a window does not accept the close event. \sa closeActiveWindow() */ void TQWorkspace::closeAllWindows() { bool did_close = TRUE; TQPtrListIterator it( d->windows ); TQWorkspaceChild *c = 0; while ( ( c = it.current() ) && did_close ) { ++it; if ( c->windowWidget() ) did_close = c->windowWidget()->close(); } } void TQWorkspace::normalizeActiveWindow() { if ( d->maxWindow ) d->maxWindow->showNormal(); else if ( d->active ) d->active->showNormal(); } void TQWorkspace::minimizeActiveWindow() { if ( d->maxWindow ) d->maxWindow->showMinimized(); else if ( d->active ) d->active->showMinimized(); } void TQWorkspace::showOperationMenu() { if ( !d->active || !d->active->windowWidget() ) return; Q_ASSERT( d->active->windowWidget()->testWFlags( WStyle_SysMenu ) ); TQPoint p; TQPopupMenu *popup = d->active->windowWidget()->testWFlags( WStyle_Tool ) ? d->toolPopup : d->popup; if ( TQApplication::reverseLayout() ) { p = TQPoint( d->active->windowWidget()->mapToGlobal( TQPoint(d->active->windowWidget()->width(),0) ) ); p.rx() -= popup->sizeHint().width(); } else { p = TQPoint( d->active->windowWidget()->mapToGlobal( TQPoint(0,0) ) ); } if ( !d->active->isVisible() ) { p = d->active->iconWidget()->mapToGlobal( TQPoint(0,0) ); p.ry() -= popup->sizeHint().height(); } popupOperationMenu( p ); } void TQWorkspace::popupOperationMenu( const TQPoint& p) { if ( !d->active || !d->active->windowWidget() || !d->active->windowWidget()->testWFlags( WStyle_SysMenu ) ) return; if ( d->active->windowWidget()->testWFlags( WStyle_Tool )) d->toolPopup->popup( p ); else d->popup->popup( p ); } void TQWorkspace::operationMenuAboutToShow() { for ( int i = 1; i < 6; i++ ) { bool enable = d->active != 0; d->popup->setItemEnabled( i, enable ); } if ( !d->active || !d->active->windowWidget() ) return; TQWidget *windowWidget = d->active->windowWidget(); bool canResize = windowWidget->maximumSize() != windowWidget->minimumSize(); d->popup->setItemEnabled( 3, canResize ); d->popup->setItemEnabled( 4, windowWidget->testWFlags( WStyle_Minimize ) ); d->popup->setItemEnabled( 5, windowWidget->testWFlags( WStyle_Maximize ) && canResize ); if ( d->active == d->maxWindow ) { d->popup->setItemEnabled( 2, FALSE ); d->popup->setItemEnabled( 3, FALSE ); d->popup->setItemEnabled( 5, FALSE ); } else if ( d->active->isVisible() ){ d->popup->setItemEnabled( 1, FALSE ); } else { d->popup->setItemEnabled( 2, FALSE ); d->popup->setItemEnabled( 3, FALSE ); d->popup->setItemEnabled( 4, FALSE ); } } void TQWorkspace::toolMenuAboutToShow() { if ( !d->active || !d->active->windowWidget() ) return; TQWidget *windowWidget = d->active->windowWidget(); bool canResize = windowWidget->maximumSize() != windowWidget->minimumSize(); d->toolPopup->setItemEnabled( 3, !d->active->shademode && canResize ); if ( d->active->shademode ) d->toolPopup->changeItem( 6, TQIconSet(style().stylePixmap(TQStyle::SP_TitleBarUnshadeButton)), tr("&Unshade") ); else d->toolPopup->changeItem( 6, TQIconSet(style().stylePixmap(TQStyle::SP_TitleBarShadeButton)), tr("Sh&ade") ); d->toolPopup->setItemEnabled( 6, d->active->windowWidget()->testWFlags( WStyle_MinMax ) ); d->toolPopup->setItemChecked( 7, d->active->windowWidget()->testWFlags( WStyle_StaysOnTop ) ); } void TQWorkspace::operationMenuActivated( int a ) { if ( !d->active ) return; switch ( a ) { case 1: d->active->showNormal(); break; case 2: d->active->doMove(); break; case 3: if ( d->active->shademode ) d->active->showShaded(); d->active->doResize(); break; case 4: d->active->showMinimized(); break; case 5: d->active->showMaximized(); break; case 6: d->active->showShaded(); break; case 7: { TQWorkspace* w = (TQWorkspace*)d->active->windowWidget(); if ( !w ) break; if ( w->testWFlags( WStyle_StaysOnTop ) ) { w->clearWFlags( WStyle_StaysOnTop ); } else { w->setWFlags( WStyle_StaysOnTop ); w->parentWidget()->raise(); } } break; default: break; } } /*! Activates the next window in the child window chain. \sa activatePrevWindow() */ void TQWorkspace::activateNextWindow() { if ( d->focus.isEmpty() ) return; if ( !d->active ) { if ( d->focus.first() ) activateWindow( d->focus.first()->windowWidget(), FALSE ); return; } int a = d->focus.find( d->active ) + 1; a = a % d->focus.count(); if ( d->focus.at( a ) ) activateWindow( d->focus.at( a )->windowWidget(), FALSE ); else activateWindow(0); } void TQWorkspace::activatePreviousWindow() { activatePrevWindow(); } /*! Activates the previous window in the child window chain. \sa activateNextWindow() */ void TQWorkspace::activatePrevWindow() { if ( d->focus.isEmpty() ) return; if ( !d->active ) { if ( d->focus.last() ) activateWindow( d->focus.first()->windowWidget(), FALSE ); else activateWindow( 0 ); return; } int a = d->focus.find( d->active ) - 1; if ( a < 0 ) a = d->focus.count()-1; if ( d->focus.at( a ) ) activateWindow( d->focus.at( a )->windowWidget(), FALSE ); else activateWindow( 0 ); } /*! \fn void TQWorkspace::windowActivated( TQWidget* w ) This signal is emitted when the window widget \a w becomes active. Note that \a w can be null, and that more than one signal may be emitted for a single activation event. \sa activeWindow(), windowList() */ /*! Arranges all the child windows in a cascade pattern. \sa tile() */ void TQWorkspace::cascade() { blockSignals(TRUE); if ( d->maxWindow ) d->maxWindow->showNormal(); if ( d->vbar ) { d->vbar->blockSignals( TRUE ); d->vbar->setValue( 0 ); d->vbar->blockSignals( FALSE ); d->hbar->blockSignals( TRUE ); d->hbar->setValue( 0 ); d->hbar->blockSignals( FALSE ); scrollBarChanged(); } const int xoffset = 13; const int yoffset = 20; // make a list of all relevant mdi clients TQPtrList widgets; TQWorkspaceChild* wc = 0; for ( wc = d->focus.first(); wc; wc = d->focus.next() ) if ( wc->windowWidget()->isVisibleTo( this ) && !wc->windowWidget()->testWFlags( WStyle_Tool ) && !wc->iconw ) widgets.append( wc ); int x = 0; int y = 0; setUpdatesEnabled( FALSE ); TQPtrListIterator it( widgets ); while ( it.current () ) { TQWorkspaceChild *child = it.current(); ++it; child->setUpdatesEnabled( FALSE ); TQSize prefSize = child->windowWidget()->sizeHint().expandedTo( child->windowWidget()->minimumSizeHint() ); if ( !prefSize.isValid() ) prefSize = child->windowWidget()->size(); prefSize = prefSize.expandedTo( child->windowWidget()->minimumSize() ).boundedTo( child->windowWidget()->maximumSize() ); if (prefSize.isValid()) prefSize += TQSize( child->baseSize().width(), child->baseSize().height() ); int w = prefSize.width(); int h = prefSize.height(); child->showNormal(); tqApp->sendPostedEvents( 0, TQEvent::ShowNormal ); if ( y + h > height() ) y = 0; if ( x + w > width() ) x = 0; child->setGeometry( x, y, w, h ); x += xoffset; y += yoffset; child->internalRaise(); child->setUpdatesEnabled( TRUE ); } setUpdatesEnabled( TRUE ); updateWorkspace(); blockSignals(FALSE); } /*! Arranges all child windows in a tile pattern. \sa cascade() */ void TQWorkspace::tile() { blockSignals(TRUE); TQWidget *oldActive = d->active ? d->active->windowWidget() : 0; if ( d->maxWindow ) d->maxWindow->showNormal(); if ( d->vbar ) { d->vbar->blockSignals( TRUE ); d->vbar->setValue( 0 ); d->vbar->blockSignals( FALSE ); d->hbar->blockSignals( TRUE ); d->hbar->setValue( 0 ); d->hbar->blockSignals( FALSE ); scrollBarChanged(); } int rows = 1; int cols = 1; int n = 0; TQWorkspaceChild* c; TQPtrListIterator it( d->windows ); while ( it.current () ) { c = it.current(); ++it; if ( !c->windowWidget()->isHidden() && !c->windowWidget()->testWFlags( WStyle_StaysOnTop ) && !c->windowWidget()->testWFlags( WStyle_Tool ) && !c->iconw ) n++; } while ( rows * cols < n ) { if ( cols <= rows ) cols++; else rows++; } int add = cols * rows - n; bool* used = new bool[ cols*rows ]; for ( int i = 0; i < rows*cols; i++ ) used[i] = FALSE; int row = 0; int col = 0; int w = width() / cols; int h = height() / rows; it.toFirst(); while ( it.current () ) { c = it.current(); ++it; if ( c->iconw || c->windowWidget()->isHidden() || c->windowWidget()->testWFlags( WStyle_Tool ) ) continue; if (!row && !col) { w -= c->baseSize().width(); h -= c->baseSize().height(); } if ( c->windowWidget()->testWFlags( WStyle_StaysOnTop ) ) { TQPoint p = c->pos(); if ( p.x()+c->width() < 0 ) p.setX( 0 ); if ( p.x() > width() ) p.setX( width() - c->width() ); if ( p.y() + 10 < 0 ) p.setY( 0 ); if ( p.y() > height() ) p.setY( height() - c->height() ); if ( p != c->pos() ) c->TQFrame::move( p ); } else { c->showNormal(); tqApp->sendPostedEvents( 0, TQEvent::ShowNormal ); used[row*cols+col] = TRUE; TQSize sz(w, h); TQSize bsize(c->baseSize()); sz = sz.expandedTo(c->windowWidget()->minimumSize()).boundedTo(c->windowWidget()->maximumSize()); sz += bsize; if ( add ) { if (sz.height() == h + bsize.height()) // no relevant constrains sz.rheight() *= 2; c->setGeometry(col*w + col*bsize.width(), row*h + row*bsize.height(), sz.width(), sz.height()); used[(row+1)*cols+col] = TRUE; add--; } else { c->setGeometry(col*w + col*bsize.width(), row*h + row*bsize.height(), sz.width(), sz.height()); } while( row < rows && col < cols && used[row*cols+col] ) { col++; if ( col == cols ) { col = 0; row++; } } } } delete [] used; activateWindow( oldActive ); updateWorkspace(); blockSignals(FALSE); } TQWorkspaceChild::TQWorkspaceChild( TQWidget* window, TQWorkspace *parent, const char *name ) : TQFrame( parent, name, (parent->windowMode() == TQWorkspace::TopLevel ? (WStyle_MinMax | WStyle_SysMenu | WType_TopLevel) : WStyle_NoBorder ) | WStyle_Customize | WDestructiveClose | WNoMousePropagation | WSubWindow ) { statusbar = 0; setMouseTracking( TRUE ); act = FALSE; iconw = 0; lastfocusw = 0; shademode = FALSE; titlebar = 0; snappedRight = FALSE; snappedDown = FALSE; if (window) { switch (window->focusPolicy()) { case TQWidget::NoFocus: window->setFocusPolicy(TQWidget::ClickFocus); break; case TQWidget::TabFocus: window->setFocusPolicy(TQWidget::StrongFocus); break; default: break; } } if ( window && window->testWFlags( WStyle_Title ) && parent->windowMode() != TQWorkspace::TopLevel ) { titlebar = new TQTitleBar( window, this, "qt_ws_titlebar" ); connect( titlebar, TQ_SIGNAL( doActivate() ), this, TQ_SLOT( activate() ) ); connect( titlebar, TQ_SIGNAL( doClose() ), window, TQ_SLOT( close() ) ); connect( titlebar, TQ_SIGNAL( doMinimize() ), this, TQ_SLOT( showMinimized() ) ); connect( titlebar, TQ_SIGNAL( doNormal() ), this, TQ_SLOT( showNormal() ) ); connect( titlebar, TQ_SIGNAL( doMaximize() ), this, TQ_SLOT( showMaximized() ) ); connect( titlebar, TQ_SIGNAL( popupOperationMenu(const TQPoint&) ), this, TQ_SIGNAL( popupOperationMenu(const TQPoint&) ) ); connect( titlebar, TQ_SIGNAL( showOperationMenu() ), this, TQ_SIGNAL( showOperationMenu() ) ); connect( titlebar, TQ_SIGNAL( doShade() ), this, TQ_SLOT( showShaded() ) ); connect( titlebar, TQ_SIGNAL( doubleClicked() ), this, TQ_SLOT( titleBarDoubleClicked() ) ); } setFrameStyle( TQFrame::StyledPanel | TQFrame::Raised ); setLineWidth( style().pixelMetric(TQStyle::PM_MDIFrameWidth, this) ); setMinimumSize( 128, 0 ); childWidget = window; if (!childWidget) return; #ifndef TQT_NO_WIDGET_TOPEXTRA setCaption( childWidget->caption() ); #endif TQPoint p; TQSize s; TQSize cs; bool hasBeenResized = childWidget->testWState( WState_Resized ); if ( !hasBeenResized ) cs = childWidget->sizeHint().expandedTo( childWidget->minimumSizeHint() ); else cs = childWidget->size(); int th = titlebar ? titlebar->sizeHint().height() : 0; if ( titlebar ) { #ifndef TQT_NO_WIDGET_TOPEXTRA int iconSize = th; if( childWidget->icon() ) { TQPixmap pm(*childWidget->icon()); if(pm.width() > iconSize || pm.height() > iconSize) { TQImage im; im = pm; pm = im.smoothScale( TQMIN(iconSize, pm.width()), TQMIN(iconSize, pm.height()) ); } titlebar->setIcon( pm ); } #endif if ( !style().styleHint( TQStyle::SH_TitleBar_NoBorder, titlebar ) ) th += frameWidth(); else th -= contentsRect().y(); p = TQPoint( contentsRect().x(), th + contentsRect().y() ); s = TQSize( cs.width() + 2*frameWidth(), cs.height() + 2*frameWidth() + th ); } else { p = TQPoint( contentsRect().x(), contentsRect().y() ); s = TQSize( cs.width() + 2*frameWidth(), cs.height() + 2*frameWidth() ); } childWidget->reparent( this, p); resize( s ); childWidget->installEventFilter( this ); widgetResizeHandler = new TQWidgetResizeHandler( this, window ); widgetResizeHandler->setSizeProtection( !parent->scrollBarsEnabled() ); connect( widgetResizeHandler, TQ_SIGNAL( activate() ), this, TQ_SLOT( activate() ) ); if ( !style().styleHint( TQStyle::SH_TitleBar_NoBorder, titlebar ) ) widgetResizeHandler->setExtraHeight( th + contentsRect().y() - 2*frameWidth() ); else widgetResizeHandler->setExtraHeight( th + contentsRect().y() - frameWidth() ); if(parent->windowMode() == TQWorkspace::TopLevel && isTopLevel()) { move(0, 0); widgetResizeHandler->setActive( FALSE ); } if ( childWidget->minimumSize() == childWidget->maximumSize() ) widgetResizeHandler->setActive( TQWidgetResizeHandler::Resize, FALSE ); setBaseSize( baseSize() ); } TQWorkspaceChild::~TQWorkspaceChild() { if ( iconw ) delete iconw->parentWidget(); TQWorkspace *workspace = ::tqt_cast(parentWidget()); if ( workspace ) { workspace->d->focus.removeRef(this); if ( workspace->d->active == this ) { workspace->activatePrevWindow(); if (workspace->d->active == this) { workspace->activateWindow(0); } } if ( workspace->d->maxWindow == this ) { workspace->hideMaximizeControls(); workspace->d->maxWindow = 0; } } } bool TQWorkspaceChild::event( TQEvent *e ) { if(((TQWorkspace*)parentWidget())->windowMode() == TQWorkspace::TopLevel) { switch(e->type()) { case TQEvent::Close: if(windowWidget()) { if(!windowWidget()->close()) { if(((TQWorkspace*) parentWidget() )->d->active == this) ((TQWorkspace*) parentWidget() )->activatePrevWindow(); return TRUE; } } break; #if 0 case TQEvent::WindowDeactivate: if(statusbar) { TQSize newsize(width(), height() - statusbar->height()); if(statusbar->parentWidget() == this) statusbar->hide(); statusbar = 0; resize(newsize); } break; #endif case TQEvent::WindowActivate: if(((TQWorkspace*)parentWidget())->activeWindow() == windowWidget()) activate(); if(statusbar) statusbar->show(); else if(((TQWorkspace*) parentWidget() )->d->mainwindow) setStatusBar(((TQWorkspace*) parentWidget() )->d->mainwindow->statusBar()); break; default: break; } } return TQWidget::event(e); } void TQWorkspaceChild::setStatusBar( TQStatusBar *sb ) { if(((TQWorkspace*) parentWidget() )->windowMode() == TQWorkspace::TopLevel) { TQSize newsize; if(sb) { sb->show(); if(sb != statusbar) { sb->reparent(this, TQPoint(0, height()), TRUE); newsize = TQSize(width(), height() + sb->height()); } } statusbar = sb; if(!newsize.isNull()) resize(newsize); } } void TQWorkspaceChild::moveEvent( TQMoveEvent *e ) { if(((TQWorkspace*) parentWidget() )->windowMode() == TQWorkspace::TopLevel && !e->spontaneous()) { TQPoint p = parentWidget()->topLevelWidget()->pos(); if(x() < p.x() || y() < p.y()) move(TQMAX(x(), p.x()), TQMAX(y(), p.y())); } ((TQWorkspace*) parentWidget() )->updateWorkspace(); } void TQWorkspaceChild::resizeEvent( TQResizeEvent * ) { TQRect r = contentsRect(); TQRect cr; if ( titlebar ) { int th = titlebar->sizeHint().height(); TQRect tbrect( 0, 0, width(), th ); if ( !style().styleHint( TQStyle::SH_TitleBar_NoBorder ) ) tbrect = TQRect( r.x(), r.y(), r.width(), th ); titlebar->setGeometry( tbrect ); if ( style().styleHint( TQStyle::SH_TitleBar_NoBorder, titlebar ) ) th -= frameWidth(); cr = TQRect( r.x(), r.y() + th + (shademode ? (frameWidth() * 3) : 0), r.width(), r.height() - th ); } else { cr = r; } if(statusbar && statusbar->isVisible()) { int sh = statusbar->height(); statusbar->setGeometry(r.x(), r.bottom() - sh, r.width(), sh); cr.setBottom(cr.bottom() - sh); } if (!childWidget) return; windowSize = cr.size(); childWidget->setGeometry( cr ); ((TQWorkspace*) parentWidget() )->updateWorkspace(); } TQSize TQWorkspaceChild::baseSize() const { int th = titlebar ? titlebar->sizeHint().height() : 0; if ( style().styleHint( TQStyle::SH_TitleBar_NoBorder, titlebar ) ) th -= frameWidth(); return TQSize( 2*frameWidth(), 2*frameWidth() + th ); } TQSize TQWorkspaceChild::sizeHint() const { if ( !childWidget ) return TQFrame::sizeHint() + baseSize(); TQSize prefSize = windowWidget()->sizeHint().expandedTo( windowWidget()->minimumSizeHint() ); prefSize = prefSize.expandedTo( windowWidget()->minimumSize() ).boundedTo( windowWidget()->maximumSize() ); prefSize += baseSize(); return prefSize; } TQSize TQWorkspaceChild::minimumSizeHint() const { if ( !childWidget ) return TQFrame::minimumSizeHint() + baseSize(); TQSize s = childWidget->minimumSize(); if ( s.isEmpty() ) s = childWidget->minimumSizeHint(); return s + baseSize(); } void TQWorkspaceChild::activate() { ((TQWorkspace*)parentWidget())->activateWindow( windowWidget() ); } bool TQWorkspaceChild::eventFilter( TQObject * o, TQEvent * e) { if ( !isActive() && ( e->type() == TQEvent::MouseButtonPress || e->type() == TQEvent::FocusIn ) ) { if ( iconw ) { ((TQWorkspace*)parentWidget())->normalizeWindow( windowWidget() ); if ( iconw ) { ((TQWorkspace*)parentWidget())->removeIcon( iconw->parentWidget() ); delete iconw->parentWidget(); iconw = 0; } } activate(); } // for all widgets except the window, that's the only thing we // process, and if we have no childWidget we skip totally if ( o != childWidget || childWidget == 0 ) return FALSE; switch ( e->type() ) { case TQEvent::Show: if ( ((TQWorkspace*)parentWidget())->d->focus.find( this ) < 0 ) ((TQWorkspace*)parentWidget())->d->focus.append( this ); if ( isVisibleTo( parentWidget() ) ) break; if (( (TQShowEvent*)e)->spontaneous() ) break; // fall through case TQEvent::ShowToParent: if ( windowWidget() && windowWidget()->testWFlags( WStyle_StaysOnTop ) ) { internalRaise(); show(); } ((TQWorkspace*)parentWidget())->showWindow( windowWidget() ); break; case TQEvent::ShowMaximized: if ( windowWidget()->maximumSize().isValid() && ( windowWidget()->maximumWidth() < parentWidget()->width() || windowWidget()->maximumHeight() < parentWidget()->height() ) ) { windowWidget()->resize( windowWidget()->maximumSize() ); ((TQWorkspace*)windowWidget())->clearWState(WState_Maximized); if (titlebar) titlebar->repaint(FALSE); break; } if ( windowWidget()->testWFlags( WStyle_Maximize ) && !windowWidget()->testWFlags( WStyle_Tool ) ) ((TQWorkspace*)parentWidget())->maximizeWindow( windowWidget() ); else ((TQWorkspace*)parentWidget())->normalizeWindow( windowWidget() ); break; case TQEvent::ShowMinimized: ((TQWorkspace*)parentWidget())->minimizeWindow( windowWidget() ); break; case TQEvent::ShowNormal: ((TQWorkspace*)parentWidget())->normalizeWindow( windowWidget() ); if (iconw) { ((TQWorkspace*)parentWidget())->removeIcon( iconw->parentWidget() ); delete iconw->parentWidget(); } break; case TQEvent::Hide: case TQEvent::HideToParent: if ( !childWidget->isVisibleTo( this ) ) { TQWidget * w = iconw; if ( w && ( w = w->parentWidget() ) ) { ((TQWorkspace*)parentWidget())->removeIcon( w ); delete w; } hide(); } break; case TQEvent::CaptionChange: #ifndef TQT_NO_WIDGET_TOPEXTRA setCaption( childWidget->caption() ); if ( iconw ) iconw->setCaption( childWidget->caption() ); #endif break; case TQEvent::IconChange: { TQWorkspace* ws = (TQWorkspace*)parentWidget(); if ( !titlebar ) break; TQPixmap pm; int iconSize = titlebar->size().height(); #ifndef TQT_NO_WIDGET_TOPEXTRA if ( childWidget->icon() ) { pm = *childWidget->icon(); if(pm.width() > iconSize || pm.height() > iconSize) { TQImage im; im = pm; pm = im.smoothScale( TQMIN(iconSize, pm.width()), TQMIN(iconSize, pm.height()) ); } } else #endif { pm.resize( iconSize, iconSize ); pm.fill( color1 ); pm.setMask(pm.createHeuristicMask()); } titlebar->setIcon( pm ); if ( iconw ) iconw->setIcon( pm ); if ( ws->d->maxWindow != this ) break; if ( ws->d->maxtools ) ws->d->maxtools->setPixmap( pm ); } break; case TQEvent::Resize: { TQResizeEvent* re = (TQResizeEvent*)e; if ( re->size() != windowSize && !shademode ) resize( re->size() + baseSize() ); } break; case TQEvent::WindowDeactivate: if ( titlebar ) titlebar->setActive( FALSE ); repaint( FALSE ); break; case TQEvent::WindowActivate: if ( titlebar ) titlebar->setActive( act ); repaint( FALSE ); break; default: break; } return TQFrame::eventFilter(o, e); } bool TQWorkspaceChild::focusNextPrevChild( bool next ) { TQFocusData *f = focusData(); TQWidget *startingPoint = f->home(); TQWidget *candidate = 0; TQWidget *w = next ? f->next() : f->prev(); while( !candidate && w != startingPoint ) { if ( w != startingPoint && (w->focusPolicy() & TabFocus) == TabFocus && w->isEnabled() &&!w->focusProxy() && w->isVisible() ) candidate = w; w = next ? f->next() : f->prev(); } if ( candidate ) { TQObjectList *ol = queryList(); bool ischild = ol->findRef( candidate ) != -1; delete ol; if ( !ischild ) { startingPoint = f->home(); TQWidget *nw = next ? f->prev() : f->next(); TQObjectList *ol2 = queryList(); TQWidget *lastValid = 0; candidate = startingPoint; while ( nw != startingPoint ) { if ( ( candidate->focusPolicy() & TabFocus ) == TabFocus && candidate->isEnabled() &&!candidate->focusProxy() && candidate->isVisible() ) lastValid = candidate; if ( ol2->findRef( nw ) == -1 ) { candidate = lastValid; break; } candidate = nw; nw = next ? f->prev() : f->next(); } delete ol2; } } if ( !candidate ) return FALSE; candidate->setFocus(); return TRUE; } void TQWorkspaceChild::childEvent( TQChildEvent* e) { if ( e->type() == TQEvent::ChildRemoved && e->child() == childWidget ) { childWidget = 0; if ( iconw ) { ((TQWorkspace*)parentWidget())->removeIcon( iconw->parentWidget() ); delete iconw->parentWidget(); } close(); } } void TQWorkspaceChild::doResize() { widgetResizeHandler->doResize(); } void TQWorkspaceChild::doMove() { widgetResizeHandler->doMove(); } void TQWorkspaceChild::enterEvent( TQEvent * ) { } void TQWorkspaceChild::leaveEvent( TQEvent * ) { #ifndef TQT_NO_CURSOR if ( !widgetResizeHandler->isButtonDown() ) setCursor( arrowCursor ); #endif } void TQWorkspaceChild::drawFrame( TQPainter *p ) { TQStyle::SFlags flags = TQStyle::Style_Default; TQStyleOption opt(lineWidth(),midLineWidth()); if ( titlebar && titlebar->isActive() ) flags |= TQStyle::Style_Active; style().drawPrimitive( TQStyle::PE_WindowFrame, p, rect(), colorGroup(), flags, opt ); } void TQWorkspaceChild::styleChange( TQStyle & ) { resizeEvent( 0 ); if ( iconw ) { TQVBox *vbox = (TQVBox*)iconw->parentWidget()->tqt_cast( "TQVBox" ); Q_ASSERT(vbox); if ( !style().styleHint( TQStyle::SH_TitleBar_NoBorder ) ) { vbox->setFrameStyle( TQFrame::WinPanel | TQFrame::Raised ); vbox->resize( 196+2*vbox->frameWidth(), 20 + 2*vbox->frameWidth() ); } else { vbox->resize( 196, 20 ); } } } void TQWorkspaceChild::setActive( bool b ) { if ( !childWidget ) return; bool hasFocus = isChildOf( focusWidget(), childWidget ); if ( act == b && hasFocus ) return; act = b; if ( titlebar ) titlebar->setActive( act ); if ( iconw ) iconw->setActive( act ); repaint( FALSE ); TQObjectList* ol = childWidget->queryList( "TQWidget" ); if ( act ) { TQObject *o; for ( o = ol->first(); o; o = ol->next() ) o->removeEventFilter( this ); if ( !hasFocus ) { if ( lastfocusw && ol->contains( lastfocusw ) && lastfocusw->focusPolicy() != NoFocus ) { // this is a bug if lastfocusw has been deleted, a new // widget has been created, and the new one is a child // of the same window as the old one. but even though // it's a bug the behaviour is reasonable lastfocusw->setFocus(); } else if ( childWidget->focusPolicy() != NoFocus ) { childWidget->setFocus(); } else { // find something, anything, that accepts focus, and use that. o = ol->first(); while( o && ((TQWidget*)o)->focusPolicy() == NoFocus ) o = ol->next(); if ( o ) ((TQWidget*)o)->setFocus(); } } } else { if ( isChildOf( focusWidget(), childWidget ) ) lastfocusw = focusWidget(); TQObject * o; for ( o = ol->first(); o; o = ol->next() ) { o->removeEventFilter( this ); o->installEventFilter( this ); } } delete ol; } bool TQWorkspaceChild::isActive() const { return act; } TQWidget* TQWorkspaceChild::windowWidget() const { return childWidget; } TQWidget* TQWorkspaceChild::iconWidget() const { if ( !iconw ) { TQWorkspaceChild* that = (TQWorkspaceChild*) this; // ### why do we even need the vbox? -Brad TQVBox* vbox = new TQVBox(that, "qt_vbox", WType_TopLevel ); TQTitleBar *tb = new TQTitleBar( windowWidget(), vbox, "_workspacechild_icon_"); int th = style().pixelMetric( TQStyle::PM_TitleBarHeight, tb ); int iconSize = style().pixelMetric( TQStyle::PM_MDIMinimizedWidth, this ); if ( !style().styleHint( TQStyle::SH_TitleBar_NoBorder ) ) { vbox->setFrameStyle( TQFrame::WinPanel | TQFrame::Raised ); vbox->resize( iconSize+2*vbox->frameWidth(), th+2*vbox->frameWidth() ); } else { vbox->resize( iconSize, th ); } that->iconw = tb; iconw->setActive( isActive() ); connect( iconw, TQ_SIGNAL( doActivate() ), this, TQ_SLOT( activate() ) ); connect( iconw, TQ_SIGNAL( doClose() ), windowWidget(), TQ_SLOT( close() ) ); connect( iconw, TQ_SIGNAL( doNormal() ), this, TQ_SLOT( showNormal() ) ); connect( iconw, TQ_SIGNAL( doMaximize() ), this, TQ_SLOT( showMaximized() ) ); connect( iconw, TQ_SIGNAL( popupOperationMenu(const TQPoint&) ), this, TQ_SIGNAL( popupOperationMenu(const TQPoint&) ) ); connect( iconw, TQ_SIGNAL( showOperationMenu() ), this, TQ_SIGNAL( showOperationMenu() ) ); connect( iconw, TQ_SIGNAL( doubleClicked() ), this, TQ_SLOT( titleBarDoubleClicked() ) ); } #ifndef TQT_NO_WIDGET_TOPEXTRA if ( windowWidget() ) { iconw->setCaption( windowWidget()->caption() ); if ( windowWidget()->icon() ) { int iconSize = iconw->sizeHint().height(); TQPixmap pm(*childWidget->icon()); if(pm.width() > iconSize || pm.height() > iconSize) { TQImage im; im = pm; pm = im.smoothScale( TQMIN(iconSize, pm.width()), TQMIN(iconSize, pm.height()) ); } iconw->setIcon( pm ); } } #endif return iconw->parentWidget(); } void TQWorkspaceChild::showMinimized() { windowWidget()->setWindowState(WindowMinimized | windowWidget()->windowState()); } void TQWorkspaceChild::showMaximized() { windowWidget()->setWindowState(WindowMaximized | (windowWidget()->windowState() & ~WindowMinimized)); } void TQWorkspaceChild::showNormal() { windowWidget()->setWindowState(windowWidget()->windowState() & ~(WindowMinimized|WindowMaximized)); } void TQWorkspaceChild::showShaded() { if ( !titlebar) return; Q_ASSERT( windowWidget()->testWFlags( WStyle_MinMax ) && windowWidget()->testWFlags( WStyle_Tool ) ); ((TQWorkspace*)parentWidget())->activateWindow( windowWidget() ); if ( shademode ) { TQWorkspaceChild* fake = (TQWorkspaceChild*)windowWidget(); fake->clearWState( WState_Minimized ); clearWState( WState_Minimized ); shademode = FALSE; resize( shadeRestore ); setMinimumSize( shadeRestoreMin ); style().polish(this); } else { shadeRestore = size(); shadeRestoreMin = minimumSize(); setMinimumHeight(0); shademode = TRUE; TQWorkspaceChild* fake = (TQWorkspaceChild*)windowWidget(); fake->setWState( WState_Minimized ); setWState( WState_Minimized ); if ( style().styleHint( TQStyle::SH_TitleBar_NoBorder ) ) resize( width(), titlebar->height() ); else resize( width(), titlebar->height() + 2*lineWidth() + 1 ); style().polish(this); } titlebar->update(); } void TQWorkspaceChild::titleBarDoubleClicked() { if ( !windowWidget() ) return; if ( windowWidget()->testWFlags( WStyle_MinMax ) ) { if ( windowWidget()->testWFlags( WStyle_Tool ) ) showShaded(); else if ( iconw ) showNormal(); else if ( windowWidget()->testWFlags( WStyle_Maximize ) ) showMaximized(); } } void TQWorkspaceChild::adjustToFullscreen() { if ( !childWidget ) return; tqApp->sendPostedEvents( this, TQEvent::Resize ); tqApp->sendPostedEvents( childWidget, TQEvent::Resize ); tqApp->sendPostedEvents( childWidget, TQEvent::Move ); if( style().styleHint(TQStyle::SH_Workspace_FillSpaceOnMaximize, this) ) { setGeometry( 0, 0, parentWidget()->width(), parentWidget()->height()); } else { int w = parentWidget()->width() + width() - childWidget->width(); int h = parentWidget()->height() + height() - childWidget->height(); w = TQMAX( w, childWidget->minimumWidth() ); h = TQMAX( h, childWidget->minimumHeight() ); setGeometry( -childWidget->x(), -childWidget->y(), w, h ); } setWState( WState_Maximized ); ((TQWorkspaceChild*)childWidget)->setWState( WState_Maximized ); } void TQWorkspaceChild::setCaption( const TQString& cap ) { if ( titlebar ) titlebar->setCaption( cap ); #ifndef TQT_NO_WIDGET_TOPEXTRA TQWidget::setCaption( cap ); #endif } void TQWorkspaceChild::internalRaise() { setUpdatesEnabled( FALSE ); if ( iconw ) iconw->parentWidget()->raise(); raise(); if ( !windowWidget() || windowWidget()->testWFlags( WStyle_StaysOnTop ) ) { setUpdatesEnabled( TRUE ); return; } TQPtrListIterator it( ((TQWorkspace*)parent())->d->windows ); while ( it.current () ) { TQWorkspaceChild* c = it.current(); ++it; if ( c->windowWidget() && !c->windowWidget()->isHidden() && c->windowWidget()->testWFlags( WStyle_StaysOnTop ) ) c->raise(); } setUpdatesEnabled( TRUE ); } void TQWorkspaceChild::move( int x, int y ) { int nx = x; int ny = y; if ( windowWidget() && windowWidget()->testWFlags( WStyle_Tool ) ) { int dx = 10; int dy = 10; if ( TQABS( x ) < dx ) nx = 0; if ( TQABS( y ) < dy ) ny = 0; if ( TQABS( x + width() - parentWidget()->width() ) < dx ) { nx = parentWidget()->width() - width(); snappedRight = TRUE; } else snappedRight = FALSE; if ( TQABS( y + height() - parentWidget()->height() ) < dy ) { ny = parentWidget()->height() - height(); snappedDown = TRUE; } else snappedDown = FALSE; } TQFrame::move( nx, ny ); } bool TQWorkspace::scrollBarsEnabled() const { return d->vbar != 0; } /*! \property TQWorkspace::scrollBarsEnabled \brief whether the workspace provides scrollbars If this property is set to TRUE, it is possible to resize child windows over the right or the bottom edge out of the visible area of the workspace. The workspace shows scrollbars to make it possible for the user to access those windows. If this property is set to FALSE (the default), resizing windows out of the visible area of the workspace is not permitted. */ void TQWorkspace::setScrollBarsEnabled( bool enable ) { if ( (d->vbar != 0) == enable ) return; d->xoffset = d->yoffset = 0; if ( enable ) { d->vbar = new TQScrollBar( Vertical, this, "vertical scrollbar" ); connect( d->vbar, TQ_SIGNAL( valueChanged(int) ), this, TQ_SLOT( scrollBarChanged() ) ); d->hbar = new TQScrollBar( Horizontal, this, "horizontal scrollbar" ); connect( d->hbar, TQ_SIGNAL( valueChanged(int) ), this, TQ_SLOT( scrollBarChanged() ) ); d->corner = new TQWidget( this, "qt_corner" ); updateWorkspace(); } else { delete d->vbar; delete d->hbar; delete d->corner; d->vbar = d->hbar = 0; d->corner = 0; } TQPtrListIterator it( d->windows ); while ( it.current () ) { TQWorkspaceChild *child = it.current(); ++it; child->widgetResizeHandler->setSizeProtection( !enable ); } } TQRect TQWorkspace::updateWorkspace() { if ( !isUpdatesEnabled() ) return rect(); TQRect cr( rect() ); if ( scrollBarsEnabled() && !d->maxWindow ) { d->corner->raise(); d->vbar->raise(); d->hbar->raise(); if ( d->maxWindow ) d->maxWindow->internalRaise(); TQRect r( 0, 0, 0, 0 ); TQPtrListIterator it( d->windows ); while ( it.current () ) { TQWorkspaceChild *child = it.current(); ++it; if ( !child->isHidden() ) r = r.unite( child->geometry() ); } d->vbar->blockSignals( TRUE ); d->hbar->blockSignals( TRUE ); int hsbExt = d->hbar->sizeHint().height(); int vsbExt = d->vbar->sizeHint().width(); bool showv = d->yoffset || d->yoffset + r.bottom() - height() + 1 > 0 || d->yoffset + r.top() < 0; bool showh = d->xoffset || d->xoffset + r.right() - width() + 1 > 0 || d->xoffset + r.left() < 0; if ( showh && !showv) showv = d->yoffset + r.bottom() - height() + hsbExt + 1 > 0; if ( showv && !showh ) showh = d->xoffset + r.right() - width() + vsbExt + 1 > 0; if ( !showh ) hsbExt = 0; if ( !showv ) vsbExt = 0; if ( showv ) { d->vbar->setSteps( TQMAX( height() / 12, 30 ), height() - hsbExt ); d->vbar->setRange( TQMIN( 0, d->yoffset + TQMIN( 0, r.top() ) ), TQMAX( 0, d->yoffset + TQMAX( 0, r.bottom() - height() + hsbExt + 1) ) ); d->vbar->setGeometry( width() - vsbExt, 0, vsbExt, height() - hsbExt ); d->vbar->setValue( d->yoffset ); d->vbar->show(); } else { d->vbar->hide(); } if ( showh ) { d->hbar->setSteps( TQMAX( width() / 12, 30 ), width() - vsbExt ); d->hbar->setRange( TQMIN( 0, d->xoffset + TQMIN( 0, r.left() ) ), TQMAX( 0, d->xoffset + TQMAX( 0, r.right() - width() + vsbExt + 1) ) ); d->hbar->setGeometry( 0, height() - hsbExt, width() - vsbExt, hsbExt ); d->hbar->setValue( d->xoffset ); d->hbar->show(); } else { d->hbar->hide(); } if ( showh && showv ) { d->corner->setGeometry( width() - vsbExt, height() - hsbExt, vsbExt, hsbExt ); d->corner->show(); } else { d->corner->hide(); } d->vbar->blockSignals( FALSE ); d->hbar->blockSignals( FALSE ); cr.setRect( 0, 0, width() - vsbExt, height() - hsbExt ); } TQPtrListIterator ii( d->icons ); while ( ii.current() ) { TQWorkspaceChild* w = (TQWorkspaceChild*)ii.current(); ++ii; int x = w->x(); int y = w->y(); bool m = FALSE; if ( x+w->width() > cr.width() ) { m = TRUE; x = cr.width() - w->width(); } if ( y+w->height() > cr.height() ) { y = cr.height() - w->height(); m = TRUE; } if ( m ) w->move( x, y ); } return cr; } void TQWorkspace::scrollBarChanged() { int ver = d->yoffset - d->vbar->value(); int hor = d->xoffset - d->hbar->value(); d->yoffset = d->vbar->value(); d->xoffset = d->hbar->value(); TQPtrListIterator it( d->windows ); while ( it.current () ) { TQWorkspaceChild *child = it.current(); ++it; // we do not use move() due to the reimplementation in TQWorkspaceChild child->setGeometry( child->x() + hor, child->y() + ver, child->width(), child->height() ); } updateWorkspace(); } /*! \enum TQWorkspace::WindowOrder Specifies the order in which windows are returned from windowList(). \value CreationOrder The windows are returned in the order of their creation \value StackingOrder The windows are returned in the order of their stacking */ #ifdef QT_WORKSPACE_WINDOWMODE /*! \enum TQWorkspace::WindowMode Determines the Windowing Model TQWorkspace will use for sub-windows. \value TopLevel Subwindows are treated as toplevel windows \value MDI Subwindows are organized in an MDI interface \value AutoDetect TQWorkspace will detect whether TopLevel or MDI is appropriate */ /*! The windowing model influences how the subwindows are actually created. For most platforms the default behavior of a workspace is to operate in MDI mode, with TQt/Mac the default mode is AutoDetect. */ #else /*! \internal */ #endif TQWorkspace::WindowMode TQWorkspace::windowMode() const { return d->wmode; } #ifndef TQT_NO_STYLE /*!\reimp */ void TQWorkspace::styleChange( TQStyle &olds ) { int fs = style().styleHint(TQStyle::SH_Workspace_FillSpaceOnMaximize, this); if ( isVisibleTo(0) && d->maxWindow && fs != olds.styleHint(TQStyle::SH_Workspace_FillSpaceOnMaximize, this)) { if( fs ) hideMaximizeControls(); else showMaximizeControls(); } TQWidget::styleChange(olds); } #endif #include "qworkspace.moc" #endif // TQT_NO_WORKSPACE