1 /***************************************************************************
2  *   file klfsidewidget.cpp
3  *   This file is part of the KLatexFormula Project.
4  *   Copyright (C) 2011 by Philippe Faist
5  *   philippe.faist at bluewin.ch
6  *                                                                         *
7  *   This program is free software; you can redistribute it and/or modify  *
8  *   it under the terms of the GNU General Public License as published by  *
9  *   the Free Software Foundation; either version 2 of the License, or     *
10  *   (at your option) any later version.                                   *
11  *                                                                         *
12  *   This program is distributed in the hope that it will be useful,       *
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
15  *   GNU General Public License for more details.                          *
16  *                                                                         *
17  *   You should have received a copy of the GNU General Public License     *
18  *   along with this program; if not, write to the                         *
19  *   Free Software Foundation, Inc.,                                       *
20  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
21  ***************************************************************************/
22 /* $Id: klfsidewidget.cpp 983 2016-12-31 21:03:44Z phfaist $ */
23 
24 
25 #include <QApplication>
26 #include <QtGlobal>
27 #include <QLayout>
28 #include <QEvent>
29 #include <QResizeEvent>
30 #include <QStackedLayout>
31 #include <QPointer>
32 #include <QTime>
33 #include <QTimer>
34 
35 #include <klfdefs.h>
36 
37 #include "klfsidewidget.h"
38 
39 #include "klfsidewidget_p.h"
40 
41 
42 
43 struct KLFSideWidgetManagerBasePrivate
44 {
KLF_PRIVATE_HEADKLFSideWidgetManagerBasePrivate45   KLF_PRIVATE_HEAD(KLFSideWidgetManagerBase)
46   {
47     sideWidgetParentConsistency = false;
48   }
49 
50   QPointer<QWidget> pSideWidget;
51   QPointer<QWidget> pParentWidget;
52 
53   bool sideWidgetParentConsistency;
54 };
55 
56 
KLFSideWidgetManagerBase(QWidget * parentWidget,QWidget * sideWidget,bool consistency,QObject * parent)57 KLFSideWidgetManagerBase::KLFSideWidgetManagerBase(QWidget *parentWidget, QWidget *sideWidget,
58 						   bool consistency, QObject *parent)
59   : QObject(parent)
60 {
61   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
62 
63   KLF_INIT_PRIVATE(KLFSideWidgetManagerBase) ;
64 
65   d->sideWidgetParentConsistency = consistency;
66 
67   // IMPORTANT: see dox doc of this constructor.
68   d->pSideWidget = NULL;
69   d->pParentWidget = NULL;
70 
71   Q_UNUSED(parentWidget);
72   Q_UNUSED(sideWidget);
73 }
74 
~KLFSideWidgetManagerBase()75 KLFSideWidgetManagerBase::~KLFSideWidgetManagerBase()
76 {
77   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
78 
79   // with QPointer should be OK...  //  This has to be done manually by caller to avoid crashes at application/widget-destruction time
80   setSideWidget(NULL);
81 
82   KLF_DELETE_PRIVATE ;
83 }
84 
sideWidget() const85 QWidget * KLFSideWidgetManagerBase::sideWidget() const
86 {
87   return d->pSideWidget;
88 }
ourParentWidget() const89 QWidget * KLFSideWidgetManagerBase::ourParentWidget() const
90 {
91   return d->pParentWidget;
92 }
93 
setOurParentWidget(QWidget * p)94 void KLFSideWidgetManagerBase::setOurParentWidget(QWidget *p)
95 {
96   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
97 
98   if (d->pParentWidget == p) {
99     klfDbg("no-op.") ;
100     return;
101   }
102 
103   klfDbg("old="<<d->pParentWidget<<", new parentWidget="<<p) ;
104   QWidget *oldpw = d->pParentWidget;
105   d->pParentWidget = p;
106   if (d->pSideWidget != NULL && d->sideWidgetParentConsistency) {
107     d->pSideWidget->setParent(d->pParentWidget);
108   }
109   newParentWidgetSet(oldpw, d->pParentWidget);
110 }
111 
setSideWidget(QWidget * sideWidget)112 void KLFSideWidgetManagerBase::setSideWidget(QWidget *sideWidget)
113 {
114   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
115 
116   if (d->pSideWidget == sideWidget) {
117     klfDbg("no-op.") ;
118     return;
119   }
120 
121   klfDbg("old="<<(void*)d->pSideWidget<<", new sideWidget="<<(void*)sideWidget) ;
122   klfDbg("old="<<d->pSideWidget<<", new sideWidget="<<sideWidget) ;
123   QWidget *oldw = d->pSideWidget;
124 
125   d->pSideWidget = sideWidget;
126 
127   if (d->pSideWidget != NULL && d->sideWidgetParentConsistency) {
128     if (d->pSideWidget->parentWidget() != d->pParentWidget) {
129       klfDbg("Adjusting side widget's parent to satisfy parent consistency...") ;
130       d->pSideWidget->setParent(d->pParentWidget);
131       d->pSideWidget->show(); // subclasses may assume that this object is shown.
132     }
133   }
134 
135   klfDbg("about to call virtual method.") ;
136   newSideWidgetSet(oldw, d->pSideWidget);
137 }
138 
139 
waitForShowHideActionFinished(int timeout_ms)140 void KLFSideWidgetManagerBase::waitForShowHideActionFinished(int timeout_ms)
141 {
142   if (!showHideIsAnimating())
143     return; // we're not animated, we're immediately done.
144 
145   QTime tm;
146 
147   tm.start();
148 
149   //  connect(this, SIGNAL(sideWidgetShown(bool)), this, SLOT(slotSideWidgetShown(bool)));
150 
151   // Don't reinitialize to false here, since slotSideWidgetShownActionFinished() could have
152   // already been called.
153   //  d->actionFinishedSignalReceived = false;
154   while (showHideIsAnimating()) {
155     qApp->processEvents();
156     if (tm.elapsed() > timeout_ms) {
157       klfDbg("timeout while waiting for action-finished signal. timeout_ms="<<timeout_ms) ;
158       break;
159     }
160   }
161 
162   klfDbg("finished.");
163 }
164 
165 
166 
167 // ------------------
168 
169 
170 
171 
172 struct KLFShowHideSideWidgetManagerPrivate
173 {
KLF_PRIVATE_HEADKLFShowHideSideWidgetManagerPrivate174   KLF_PRIVATE_HEAD(KLFShowHideSideWidgetManager)
175   {
176     infunction = false;
177     oldParent = NULL;
178     msize = QSize(0, 0);
179     orientation = Qt::Horizontal;
180     calcSpacing = 6;
181   }
182 
183   bool infunction;
184   QWidget *oldParent;
185   // msie is only used when the side widget is visible
186   QSize msize;
187 
188   Qt::Orientation orientation;
189   int calcSpacing;
190 };
191 
192 
KLFShowHideSideWidgetManager(QWidget * parentWidget,QWidget * sideWidget,QObject * parent)193 KLFShowHideSideWidgetManager::KLFShowHideSideWidgetManager(QWidget *parentWidget, QWidget *sideWidget,
194 							   QObject *parent)
195   : KLFSideWidgetManagerBase(parentWidget, sideWidget, true, parent)
196 {
197   KLF_INIT_PRIVATE(KLFShowHideSideWidgetManager) ;
198 
199   setOurParentWidget(parentWidget);
200   setSideWidget(sideWidget);
201 }
202 
~KLFShowHideSideWidgetManager()203 KLFShowHideSideWidgetManager::~KLFShowHideSideWidgetManager()
204 {
205   KLF_DELETE_PRIVATE ;
206 }
207 
208 // protected
newSideWidgetSet(QWidget * oldw,QWidget * neww)209 void KLFShowHideSideWidgetManager::newSideWidgetSet(QWidget *oldw, QWidget *neww)
210 {
211   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
212 
213   //bool preserveshown = false;
214   //bool shown = false;
215 
216   if (oldw != NULL) {
217     klfDbg("old="<<oldw) ;
218     //preserveshown = true;
219     //shown = oldw->isVisible();
220     oldw->removeEventFilter(this);
221     oldw->hide();
222   }
223   if (neww != NULL) {
224     KLF_ASSERT_CONDITION(ourParentWidget() == neww->parentWidget(),
225 		       "Adding a widget that is not a child of our 'parent widget' ! Correcting parent.",
226 		       setOurParentWidget(neww->parentWidget()); ) ;
227     klfDbg("new="<<neww) ;
228     //     if (neww->isVisible()) {
229     //       d->msize = neww->parentWidget()->size();
230     //       klfDbg("parent size is "<<d->msize);
231     //       if (d->orientation & Qt::Horizontal)
232     // 	d->msize.setWidth(d->msize.width() - d->calcSpacing + neww->width());
233     //       if (d->orientation & Qt::Vertical)
234     // 	d->msize.setHeight(d->msize.height() - d->calcSpacing + neww->height());
235     //       klfDbg("initialized size to "<<d->msize) ;
236     //     } else {
237     //       // if widget is about to be shown in initialization process, we will recieve a resizeEvent.
238     //       // will calculate proper size there.
239     //       d->msize = QSize();
240     //     }
241     if (neww->parentWidget()->layout() != NULL) {
242       setCalcSpacing(neww->parentWidget()->layout()->spacing());
243     }
244     neww->hide(); //unconditionally hide!
245     //    showSideWidget(false);
246     //    if (preserveshown && shown)
247     //      showSideWidget(true);
248     neww->installEventFilter(this);
249     emit sideWidgetShown(false);
250   }
251   d->msize = QSize();
252 }
253 
254 
255 // protected
newParentWidgetSet(QWidget *,QWidget * pw)256 void KLFShowHideSideWidgetManager::newParentWidgetSet(QWidget */*oldParent*/, QWidget *pw)
257 {
258   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
259 
260   if (d->oldParent != NULL)
261     d->oldParent->removeEventFilter(this);
262   if (pw == NULL) {
263     d->msize = QSize(-1, -1);
264     return;
265   }
266   d->msize = pw->size();
267   pw->installEventFilter(this);
268 }
269 
sideWidgetVisible() const270 bool KLFShowHideSideWidgetManager::sideWidgetVisible() const
271 {
272   KLF_ASSERT_NOT_NULL(sideWidget(), "Side Widget is NULL!", return false; ) ;
273   return sideWidget()->isVisible();
274 }
275 
eventFilter(QObject * obj,QEvent * event)276 bool KLFShowHideSideWidgetManager::eventFilter(QObject *obj, QEvent *event)
277 {
278   if (sideWidget() != NULL) {
279     KLF_ASSERT_CONDITION(ourParentWidget() == sideWidget()->parentWidget(),
280 		     "We have a side widget that is not a child of our 'parent widget' ! Correcting parent.",
281 		     setOurParentWidget(sideWidget()->parentWidget()); ) ;
282     QWidget * pw = sideWidget()->parentWidget();
283     if (pw != NULL && obj == pw) {
284       if (event->type() == QEvent::Resize) {
285 	QResizeEvent *re = (QResizeEvent*) event;
286 	klfDbg("resize event, new size="<<re->size()<<", old size="<<re->oldSize()
287 	       <<"; sidewidget->isvisible="<<sideWidget()->isVisible()) ;
288 	if (sideWidget()->isVisible() && !d->infunction) {
289 	  // only relevant if we are visible and not ourselves resizing the widget
290 	  klfDbg("Readjusting inner widget size") ;
291 	  d->msize += re->size() - re->oldSize();
292 	}
293       }
294     }
295     if (obj == sideWidget()) {
296       if (event->type() == QEvent::ParentAboutToChange) {
297 	d->oldParent = sideWidget()->parentWidget();
298       } else if (event->type() == QEvent::ParentChange) {
299 	setOurParentWidget(pw);
300       }
301     }
302   }
303 
304   return KLFSideWidgetManagerBase::eventFilter(obj, event);
305 }
306 
event(QEvent * event)307 bool KLFShowHideSideWidgetManager::event(QEvent *event)
308 {
309   return KLFSideWidgetManagerBase::event(event);
310 }
311 
312 
showSideWidget(bool show)313 void KLFShowHideSideWidgetManager::showSideWidget(bool show)
314 {
315   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
316 
317   KLF_ASSERT_NOT_NULL(sideWidget(), "Side Widget is NULL!", return; ) ;
318 
319   klfDbg("show="<<show<<", sideWidgetVisible()="<<sideWidgetVisible()) ;
320 
321   if (show == sideWidgetVisible())
322     return;
323 
324   QWidget *pw = sideWidget()->parentWidget();
325 
326   KLF_ASSERT_NOT_NULL(pw, "Parent Widget of Side Widget is NULL!", return; ) ;
327   KLF_ASSERT_CONDITION(ourParentWidget() == sideWidget()->parentWidget(),
328 		   "We have a side widget that is not a child of our 'parent widget' ! Correcting parent.",
329 		   setOurParentWidget(sideWidget()->parentWidget()); ) ;
330 
331   QSize newSize;
332   if (show) {
333     d->msize = pw->size();
334     klfDbg("Store inner widget size as "<<d->msize) ;
335     newSize = d->msize;
336     if (d->orientation & Qt::Horizontal)
337       newSize += QSize(d->calcSpacing + sideWidget()->sizeHint().width(), 0);
338     if (d->orientation & Qt::Vertical)
339       newSize += QSize(0, d->calcSpacing + sideWidget()->sizeHint().height());
340   } else {
341     newSize = d->msize;
342   }
343 
344   klfDbg("sideWidget is "<<sideWidget()) ;
345   sideWidget()->setVisible(show);
346 
347   d->infunction = true;
348   klfDbg("newSize is "<<newSize<<"; d->msize is "<<d->msize) ;
349   if (newSize.isValid()) {
350     QMetaObject::invokeMethod(this, "resizeParentWidget", Qt::QueuedConnection, Q_ARG(QSize, newSize));
351   }
352   // will probably(?) emit sideWidgetShown _after_ we resized, which is possibly a more desirable behavior (?)
353   QMetaObject::invokeMethod(this, "sideWidgetShown", Qt::QueuedConnection, Q_ARG(bool, show));
354 }
355 
356 
resizeParentWidget(const QSize & size)357 void KLFShowHideSideWidgetManager::resizeParentWidget(const QSize& size)
358 {
359   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
360   klfDbg("size="<<size) ;
361   QWidget * sw = sideWidget();
362   KLF_ASSERT_NOT_NULL(sw, "Side Widget is NULL!", return; ) ;
363   KLF_ASSERT_NOT_NULL(sw->parentWidget(), "Side Widget is NULL!", return; ) ;
364 
365   QWidget *window = sw->window();
366   KLF_ASSERT_NOT_NULL(window, "hey, side-widget->window() is NULL!", return; ) ;
367   QSize diffsize = size - sw->parentWidget()->size();
368   QSize winsize = window->size() + diffsize;
369   klfDbg("resizing window to "<<winsize) ;
370   window->setFixedSize(winsize);
371   window->setFixedSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
372   d->infunction = false;
373 }
374 
375 
376 KLF_DEFINE_PROPERTY_GETSET(KLFShowHideSideWidgetManager, Qt::Orientation, orientation, Orientation) ;
377 
378 KLF_DEFINE_PROPERTY_GETSET(KLFShowHideSideWidgetManager, int, calcSpacing, CalcSpacing) ;
379 
380 
381 // ------------------
382 
383 
384 
385 
386 struct KLFContainerSideWidgetManagerPrivate
387 {
KLF_PRIVATE_HEADKLFContainerSideWidgetManagerPrivate388   KLF_PRIVATE_HEAD(KLFContainerSideWidgetManager)
389   {
390     isdestroying = false;
391     dwidget = NULL;
392     dlayout = NULL;
393     init_pw = init_sw = NULL;
394     saved_pw = NULL;
395     want_restore_saved = true;
396   }
397 
398   bool isdestroying;
399   QPointer<QWidget> dwidget;
400   QStackedLayout *dlayout;
401 
402   QWidget *init_pw;
403   QWidget *init_sw;
404 
405   QPointer<QWidget> saved_pw;
406   bool want_restore_saved;
407 
408 
restore_saved_parentKLFContainerSideWidgetManagerPrivate409   void restore_saved_parent(QWidget *oldw)
410   {
411     KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
412     KLF_ASSERT_NOT_NULL(oldw, "oldw is NULL!", return; ) ;
413     klfDbg("oldw="<<(void*)oldw<<"; saved_pw="<<(void*)saved_pw) ;
414     klfDbg("oldw="<<oldw<<"; saved_pw="<<saved_pw) ;
415 
416     oldw->setParent(saved_pw);
417 
418     klfDbg("set parent.") ;
419 
420     if (saved_pw != NULL && saved_pw->layout() != NULL) {
421       klfDbg("About to reinsert into layout "<<saved_pw->layout()) ;
422       saved_pw->layout()->addWidget(oldw);
423     }
424 
425   }
426 };
427 
428 
KLFContainerSideWidgetManager(QWidget * parentWidget,QWidget * sideWidget,QObject * parent)429 KLFContainerSideWidgetManager::KLFContainerSideWidgetManager(QWidget *parentWidget, QWidget *sideWidget,
430 							     QObject *parent)
431   : KLFSideWidgetManagerBase(parentWidget, sideWidget, false, parent)
432 {
433   KLF_INIT_PRIVATE(KLFContainerSideWidgetManager) ;
434 
435   klfDbg("parentWidget="<<parentWidget<<", sideWidget="<<sideWidget) ;
436   connect(parentWidget, SIGNAL(destroyed(QObject*)), this, SLOT(aWidgetDestroyed(QObject*)));
437   d->init_pw = parentWidget;
438   d->init_sw = sideWidget;
439 }
440 
init()441 void KLFContainerSideWidgetManager::init()
442 {
443   d->dwidget = createContainerWidget(d->init_pw);
444   connect(d->dwidget, SIGNAL(destroyed(QObject*)), this, SLOT(aWidgetDestroyed(QObject*)));
445 
446   d->dwidget->installEventFilter(this); // intercept close events
447 
448   KLF_ASSERT_NOT_NULL(d->dwidget, "Created Container Widget is NULL!", return; ) ;
449 
450   d->dlayout = new QStackedLayout(d->dwidget);
451   d->dlayout->setContentsMargins(0,0,0,0);
452   d->dlayout->setSpacing(0);
453 
454   d->dwidget->hide();
455 
456   setOurParentWidget(d->init_pw);
457   setSideWidget(d->init_sw);
458 }
459 
460 
containerWidget() const461 QWidget * KLFContainerSideWidgetManager::containerWidget() const
462 {
463   return d->dwidget;
464 }
465 
~KLFContainerSideWidgetManager()466 KLFContainerSideWidgetManager::~KLFContainerSideWidgetManager()
467 {
468   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
469 
470   d->isdestroying = true;
471 
472   if (d->dwidget != NULL) {
473     // make sure we do not destroy the sideWidget while destroying d->dwidget !
474     d->restore_saved_parent(sideWidget());
475   }
476 
477   klfDbg("d->dwidget="<<(void*)d->dwidget) ;
478   klfDbg("d->dwidget="<<d->dwidget) ;
479 
480 // d->dwidget should get deleted automatically when its parent widget dies.  Doing this
481 // explicitly on the other hand, and in the destructor, may cause a segfault
482 //
483 //  if (d->dwidget != NULL) {
484 //    klfDbg("deleting...") ;
485 //    delete d->dwidget;
486 //    klfDbg("...done") ;
487 //  }
488   KLF_DELETE_PRIVATE ;
489 }
490 
eventFilter(QObject * obj,QEvent * event)491 bool KLFContainerSideWidgetManager::eventFilter(QObject *obj, QEvent *event)
492 {
493   if (obj == d->dwidget) {
494     if (event->type() == QEvent::Close) {
495       klfDbg("intercepting close event.") ;
496       // close button clicked, eg. in floating window; make sure to hide the widget
497       // appropriately, emitting sideWidgetShown(bool) too, or saving its geometry etc.
498       showSideWidget(false);
499       return true;
500     }
501   }
502   return KLFSideWidgetManagerBase::eventFilter(obj, event);
503 }
504 
sideWidgetVisible() const505 bool KLFContainerSideWidgetManager::sideWidgetVisible() const
506 {
507   KLF_ASSERT_NOT_NULL(d->dwidget, "Container Widget is NULL! Did you forget to call init()?", return false; ) ;
508   return d->dwidget->isVisible();
509 }
510 
showSideWidget(bool show)511 void KLFContainerSideWidgetManager::showSideWidget(bool show)
512 {
513   KLF_ASSERT_NOT_NULL(d->dwidget, "Container Widget is NULL! Did you forget to call init()?", return; ) ;
514 
515   // and actually show/hide the container widget
516   d->dwidget->setVisible(show);
517   d->dwidget->setFocus();
518   emit sideWidgetShown(show);
519 }
520 
521 // protected
newSideWidgetSet(QWidget * oldw,QWidget * neww)522 void KLFContainerSideWidgetManager::newSideWidgetSet(QWidget *oldw, QWidget *neww)
523 {
524   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
525 
526   if (d->isdestroying)
527     return; // destructor has its own special treatment
528 
529   KLF_ASSERT_NOT_NULL(d->dwidget, "Container Widget is NULL! Did you forget to call init()?", return; ) ;
530 
531   klfDbg("new side widget: old="<<oldw<<", new="<<neww<<"; want restore saved="<<d->want_restore_saved) ;
532   if (oldw != NULL && d->want_restore_saved) {
533     d->dlayout->removeWidget(oldw);
534     //    oldw->hide(); // setParent() automatically hides the widget
535     d->restore_saved_parent(oldw);
536   }
537   if (d->saved_pw != NULL) {
538     klfDbg("Disconnecting the saved parent widget.") ;
539     disconnect(d->saved_pw, SIGNAL(destroyed()), this, 0);
540     d->saved_pw = NULL;
541   }
542   if (neww != NULL) {
543     d->saved_pw = neww->parentWidget(); // save its parent widget so that we can restore it
544     if (d->saved_pw != NULL) {
545       bool connected = connect(d->saved_pw, SIGNAL(destroyed(QObject*)), this, SLOT(aWidgetDestroyed(QObject*)));
546       Q_UNUSED(connected) ;
547       klfDbg("saving pw : "<<d->saved_pw<<" and connected to destroyed(QObject*) signal?="<<connected) ;
548     }
549     d->want_restore_saved = true;
550     neww->setParent(NULL) ;
551     neww->setParent(d->dwidget);
552     d->dlayout->addWidget(neww);
553     neww->show();
554     emit sideWidgetShown(d->dwidget->isVisible());
555   }
556 }
557 
558 // protected
newParentWidgetSet(QWidget *,QWidget * newWidget)559 void KLFContainerSideWidgetManager::newParentWidgetSet(QWidget *, QWidget *newWidget)
560 {
561   if (d->dwidget->parentWidget() != newWidget)
562     d->dwidget->setParent(newWidget);
563 }
564 
565 // private slot
aWidgetDestroyed(QObject * w)566 void KLFContainerSideWidgetManager::aWidgetDestroyed(QObject *w)
567 {
568   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
569   klfDbg("w="<<w) ;
570   if (w == d->saved_pw) {
571     klfDbg("saved parent "<<d->saved_pw<<" or our own parent = "<<parent()<<" was destroyed!") ;
572     d->want_restore_saved = false;
573     d->saved_pw = NULL;
574   }
575   // else if (w == d->dwidget) {
576   //    d->dwidget = NULL;
577   //  }
578 }
579 
580 
581 
582 
583 
584 
585 
586 
587 // ------------------
588 
589 
590 
591 struct KLFFloatSideWidgetManagerPrivate
592 {
KLF_PRIVATE_HEADKLFFloatSideWidgetManagerPrivate593   KLF_PRIVATE_HEAD(KLFFloatSideWidgetManager)
594   {
595     dwgeom = QRect();
596   }
597 
598   QRect dwgeom;
599 };
600 
601 
KLFFloatSideWidgetManager(QWidget * parentWidget,QWidget * sideWidget,QObject * parent)602 KLFFloatSideWidgetManager::KLFFloatSideWidgetManager(QWidget *parentWidget, QWidget *sideWidget, QObject *parent)
603   : KLFContainerSideWidgetManager(parentWidget, sideWidget, parent)
604 {
605   KLF_INIT_PRIVATE(KLFFloatSideWidgetManager) ;
606 
607   init();
608 }
609 
~KLFFloatSideWidgetManager()610 KLFFloatSideWidgetManager::~KLFFloatSideWidgetManager()
611 {
612   KLF_DELETE_PRIVATE ;
613 }
614 
wflags() const615 Qt::WindowFlags KLFFloatSideWidgetManager::wflags() const
616 {
617   return containerWidget()->windowFlags();
618 }
619 
sideWidgetVisible() const620 bool KLFFloatSideWidgetManager::sideWidgetVisible() const
621 {
622   return containerWidget()->isVisible();
623 }
624 
createContainerWidget(QWidget * pw)625 QWidget * KLFFloatSideWidgetManager::createContainerWidget(QWidget *pw)
626 {
627   return  new QWidget(pw, Qt::Tool|Qt::CustomizeWindowHint|Qt::WindowTitleHint
628 		      |Qt::WindowSystemMenuHint
629 #if QT_VERSION >= 0x040500
630 		      |Qt::WindowCloseButtonHint
631 #endif
632 		      );
633 }
634 
setWFlags(Qt::WindowFlags wf)635 void KLFFloatSideWidgetManager::setWFlags(Qt::WindowFlags wf)
636 {
637   KLF_ASSERT_NOT_NULL(sideWidget(), "side widget is NULL!", return; ) ;
638   wf |= Qt::Window; // make sure it is not a nested widget
639   containerWidget()->setWindowFlags(wf);
640 }
641 
showSideWidget(bool show)642 void KLFFloatSideWidgetManager::showSideWidget(bool show)
643 {
644   QWidget *w = containerWidget();
645   if (sideWidgetVisible()) {
646     // save position and size
647     d->dwgeom = w->geometry();
648   }
649   if (show && d->dwgeom.isValid()) {
650     // set saved position and size
651     w->setGeometry(d->dwgeom);
652   }
653   // this automatically emits sideWidgetShown
654   KLFContainerSideWidgetManager::showSideWidget(show);
655 }
656 
657 
658 // protected
newSideWidgetSet(QWidget * oldw,QWidget * neww)659 void KLFFloatSideWidgetManager::newSideWidgetSet(QWidget *oldw, QWidget *neww)
660 {
661   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
662   KLFContainerSideWidgetManager::newSideWidgetSet(oldw, neww);
663 }
664 
665 
666 
667 
668 
669 
670 // ---------------------------------------------
671 
672 // static
673 KLFFactoryManager KLFSideWidgetManagerFactory::pFactoryManager;
674 
675 
KLFSideWidgetManagerFactory()676 KLFSideWidgetManagerFactory::KLFSideWidgetManagerFactory()
677   : KLFFactoryBase(&pFactoryManager)
678 {
679 }
~KLFSideWidgetManagerFactory()680 KLFSideWidgetManagerFactory::~KLFSideWidgetManagerFactory()
681 {
682 }
683 
684 // static
allSupportedTypes()685 QStringList KLFSideWidgetManagerFactory::allSupportedTypes()
686 {
687   return pFactoryManager.allSupportedTypes();
688 }
689 
690 // static
findFactoryFor(const QString & managertype)691 KLFSideWidgetManagerFactory * KLFSideWidgetManagerFactory::findFactoryFor(const QString& managertype)
692 {
693   return dynamic_cast<KLFSideWidgetManagerFactory*>(pFactoryManager.findFactoryFor(managertype));
694 }
695 
696 // static
697 KLFSideWidgetManagerBase *
findCreateSideWidgetManager(const QString & type,QWidget * pw,QWidget * sw,QObject * parent)698 /* */ KLFSideWidgetManagerFactory::findCreateSideWidgetManager(const QString& type, QWidget *pw,
699 							       QWidget *sw, QObject *parent)
700 {
701   KLFSideWidgetManagerFactory * f = findFactoryFor(type);
702 
703   KLF_ASSERT_NOT_NULL(f, "Can't find factory for side widget manager type="<<type<<"!", return NULL; ) ;
704 
705   return f->createSideWidgetManager(type, pw, sw, parent);
706 }
707 
708 
supportedTypes() const709 QStringList KLFSideWidgetManagerFactory::supportedTypes() const
710 {
711   return QStringList()
712     << QLatin1String("ShowHide")
713     << QLatin1String("Float")
714 #ifdef KLF_WS_MAC
715     << QLatin1String("Drawer")
716 #endif
717     ;
718 }
719 
getTitleFor(const QString & type) const720 QString KLFSideWidgetManagerFactory::getTitleFor(const QString& type) const
721 {
722   if (type == QLatin1String("ShowHide"))
723     return QObject::tr("Expand/Shrink Window", "[[KLFSideWidgetManagerFactory]]");
724   if (type == QLatin1String("Float"))
725     return QObject::tr("Floating Tool Window", "[[KLFSideWidgetManagerFactory]]");
726   if (type == QLatin1String("Drawer"))
727     return QObject::tr("Side Drawer", "[[KLFSideWidgetManagerFactory]]");
728 
729   return QString();
730 }
731 
732 KLFSideWidgetManagerBase *
createSideWidgetManager(const QString & type,QWidget * parentWidget,QWidget * sideWidget,QObject * parent)733 /* */  KLFSideWidgetManagerFactory::createSideWidgetManager(const QString& type, QWidget *parentWidget,
734 							    QWidget *sideWidget, QObject *parent)
735 {
736   if (type == QLatin1String("ShowHide")) {
737     return new KLFShowHideSideWidgetManager(parentWidget, sideWidget, parent);
738   }
739   if (type == QLatin1String("Float")) {
740     return new KLFFloatSideWidgetManager(parentWidget, sideWidget, parent);
741   }
742 #ifdef KLF_WS_MAC
743   if (type == QLatin1String("Drawer")) {
744     return new KLFDrawerSideWidgetManager(parentWidget, sideWidget, parent);
745   }
746 #endif
747 
748   qWarning()<<KLF_FUNC_NAME<<": Unknown side-widget-manager type "<<type;
749 
750   return NULL;
751 }
752 
753 
754 // an instance of the factory
755 KLFSideWidgetManagerFactory __klf_side_widget_manager_factory;
756 
757 
758 // ---------
759 
760 struct KLFSideWidgetPrivate
761 {
KLF_PRIVATE_HEADKLFSideWidgetPrivate762   KLF_PRIVATE_HEAD(KLFSideWidget) {
763     manager = NULL;
764     swmtype = QString();
765   }
766 
767   KLFSideWidgetManagerBase * manager;
768   QString swmtype;
769 };
770 
771 
772 /*KLFSideWidget::KLFSideWidget(SideWidgetManager mtype, QWidget *parent)
773   : QWidget(parent)
774 {
775   KLF_INIT_PRIVATE(KLFSideWidget) ;
776   setSideWidgetManager(mtype);
777 }
778 KLFSideWidget::KLFSideWidget(const QString& mtype, QWidget *parent)
779 {
780   KLF_INIT_PRIVATE(KLFSideWidget) ;
781   setSideWidgetManager(mtype);
782   }*/
783 
KLFSideWidget(QWidget * parent)784 KLFSideWidget::KLFSideWidget(QWidget *parent)
785   : QWidget(parent)
786 {
787   KLF_INIT_PRIVATE(KLFSideWidget) ;
788 
789   _inqtdesigner = false;
790 
791 }
~KLFSideWidget()792 KLFSideWidget::~KLFSideWidget()
793 {
794   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
795 
796   delete d->manager;
797 
798   KLF_DELETE_PRIVATE ;
799 }
800 
sideWidgetManager()801 KLFSideWidgetManagerBase * KLFSideWidget::sideWidgetManager()
802 {
803   return d->manager;
804 }
805 
sideWidgetVisible() const806 bool KLFSideWidget::sideWidgetVisible() const
807 {
808   KLF_ASSERT_NOT_NULL(d->manager, "Manager is NULL!", return false) ;
809   return d->manager->sideWidgetVisible();
810 }
811 
sideWidgetManagerType() const812 QString KLFSideWidget::sideWidgetManagerType() const
813 {
814   return d->swmtype;
815 }
816 
817 
setSideWidgetManager(SideWidgetManager mtype)818 void KLFSideWidget::setSideWidgetManager(SideWidgetManager mtype)
819 {
820   QString s;
821   switch (mtype) {
822   case ShowHide: s = QLatin1String("ShowHide"); break;
823   case Float: s = QLatin1String("Float"); break;
824   case Drawer: s = QLatin1String("Drawer"); break;
825   default: break;
826   }
827 
828   KLF_ASSERT_CONDITION(!s.isEmpty(), "Invalid mtype: "<<mtype<<"!", return; ) ;
829   setSideWidgetManager(s);
830 }
setSideWidgetManager(const QString & mtype)831 void KLFSideWidget::setSideWidgetManager(const QString& mtype)
832 {
833   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
834 
835   if (_inqtdesigner) {
836     klfDbg("We're in Qt Designer. DUMMY ACTION.") ;
837     d->swmtype = mtype;
838     return;
839   }
840 
841   if (d->swmtype == mtype) {
842     klfDbg("no-op");
843     return;
844   }
845 
846   if (d->manager != NULL) {
847     d->manager->hideSideWidget();
848     klfDbg("deleting current manager") ;
849     //    d->manager->setSideWidget(NULL) ; // re-take the side widget
850     delete d->manager;
851     d->manager = NULL;
852     d->swmtype = QString();
853   }
854 
855   d->swmtype = mtype;
856   d->manager = KLFSideWidgetManagerFactory::findCreateSideWidgetManager(mtype, parentWidget(), this, this);
857   KLF_ASSERT_NOT_NULL(d->manager, "Factory returned NULL manager for type "<<mtype<<"!", return; ) ;
858 
859   connect(d->manager, SIGNAL(sideWidgetShown(bool)), this, SIGNAL(sideWidgetShown(bool)));
860 
861   emit sideWidgetManagerTypeChanged(mtype);
862   emit sideWidgetShown(d->manager->sideWidgetVisible());
863 }
864 
showSideWidget(bool show)865 void KLFSideWidget::showSideWidget(bool show)
866 {
867   if (_inqtdesigner)
868     return;
869 
870   KLF_ASSERT_NOT_NULL(d->manager, "Manager is NULL! For debugging purposes, I'm creating a 'float' manager !",
871 		      setSideWidgetManager(Float); ) ;
872   KLF_ASSERT_NOT_NULL(d->manager, "Manager is NULL!", return; ) ;
873   d->manager->showSideWidget(show);
874 }
875 
debug_unlock_qtdesigner()876 void KLFSideWidget::debug_unlock_qtdesigner()
877 {
878   if (_inqtdesigner) {
879     _inqtdesigner = false;
880     setSideWidgetManager(sideWidgetManagerType());
881   }
882 }
883