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