1 2#include <QtCore> 3#include <QtGui> 4#include <QtWidgets> 5#include <QMacNativeWidget> 6 7#include <Cocoa/Cocoa.h> 8#include <objc/runtime.h> 9#include <CoreServices/CoreServices.h> 10 11#include <klfdefs.h> 12 13#include <klfsidewidget.h> 14#include "klfsidewidget_p.h" 15 16 17 18inline NSRectEdge nsEdgeForQtEdge(Qt::DockWidgetArea edge) 19{ 20 switch (edge) { 21 case Qt::LeftDockWidgetArea: return NSMinXEdge; 22 case Qt::RightDockWidgetArea: return NSMaxXEdge; 23 case Qt::TopDockWidgetArea: return NSMinYEdge; 24 case Qt::BottomDockWidgetArea: return NSMaxYEdge; 25 default: 26 qWarning()<<KLF_FUNC_NAME<<": Invalid Qt::DockWidgetArea edge: " << edge << "\n"; 27 } 28 return NSMaxXEdge; // by default 29} 30 31inline NSSize nsSizeForQSize(QSize sz) 32{ 33 NSSize nsz; 34 nsz.width = sz.width(); 35 nsz.height = sz.height(); 36 return nsz; 37} 38 39 40 41struct KLFDrawerSideWidgetManagerPrivate 42{ 43 KLF_PRIVATE_HEAD(KLFDrawerSideWidgetManager) 44 { 45 nsdrawer = NULL; 46 sideWidget = NULL; 47 nativeWidget = NULL; 48 layout = NULL; 49 openEdge = Qt::RightDockWidgetArea; 50 } 51 52 NSDrawer * nsdrawer; 53 QWidget * sideWidget; 54 QMacNativeWidget * nativeWidget; 55 QLayout * layout; 56 57 Qt::DockWidgetArea openEdge; 58}; 59 60KLFDrawerSideWidgetManager::KLFDrawerSideWidgetManager(QWidget *parentWidget, QWidget *sideWidget, QObject *parent) 61 : KLFSideWidgetManagerBase(parentWidget, sideWidget, false, parent) 62{ 63 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ; 64 klfDbg("parentW=" << parentWidget << ", sidewidget=" << sideWidget << ", parent=" << parent) ; 65 66 KLF_INIT_PRIVATE(KLFDrawerSideWidgetManager) ; 67 68 NSView * nswinview = reinterpret_cast<NSView*>(parentWidget->window()->winId()); 69 70 NSSize csz = nsSizeForQSize(sideWidget->sizeHint()); 71 d->nsdrawer = [[NSDrawer alloc] initWithContentSize:csz preferredEdge:NSMaxXEdge]; 72 [d->nsdrawer setParentWindow:[nswinview window]]; 73 NSView *contentView = [d->nsdrawer contentView]; 74 75 d->nsdrawer.minContentSize = nsSizeForQSize(sideWidget->minimumSizeHint()); 76 d->nsdrawer.maxContentSize = nsSizeForQSize(QSize(32767,32767)); 77 78 // inspired by http://doc.qt.io/qt-5/qmacnativewidget.html 79 80 d->nativeWidget = new QMacNativeWidget(contentView); 81 d->nativeWidget->move(0, 0); 82 //d->nativeWidget->setPalette(QPalette(Qt::red)); 83 d->nativeWidget->setAutoFillBackground(true); 84 //d->nativeWidget->setMinimumSize(sideWidget->minimumSizeHint()); 85 d->layout = new QVBoxLayout(); 86 d->layout->setMargin(0); 87 d->sideWidget = sideWidget; 88 d->sideWidget->setParent(d->nativeWidget); 89 d->sideWidget->setAttribute(Qt::WA_LayoutUsesWidgetRect); 90 d->layout->addWidget(sideWidget); 91 d->nativeWidget->setLayout(d->layout); 92 93 NSView *nativeWidgetView = d->nativeWidget->nativeView(); 94 [contentView setAutoresizesSubviews:YES]; 95 [nativeWidgetView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; 96 [nativeWidgetView setAutoresizesSubviews:YES]; 97 NSView *sideWidgetView = reinterpret_cast<NSView *>(d->sideWidget->winId()); 98 [sideWidgetView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; 99 100 // Add the nativeWidget to the window. 101 [contentView addSubview:nativeWidgetView positioned:NSWindowAbove relativeTo:nil]; 102 d->nativeWidget->show(); 103 104 d->sideWidget->show(); 105 106 NSRect frame = [contentView frame]; 107 d->nativeWidget->resize(QSize(frame.size.width, frame.size.height)); 108 109 setOurParentWidget(parentWidget); 110 setSideWidget(sideWidget); 111} 112 113KLFDrawerSideWidgetManager::~KLFDrawerSideWidgetManager() 114{ 115 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ; 116 117 KLF_DELETE_PRIVATE ; 118} 119 120// protected 121void KLFDrawerSideWidgetManager::newSideWidgetSet(QWidget *oldw, QWidget *neww) 122{ 123 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ; 124 125 if (oldw != NULL) { 126 d->layout->removeWidget(oldw); 127 } 128 if (neww != NULL) { 129 d->sideWidget = neww; 130 d->sideWidget->setParent(d->nativeWidget); 131 d->sideWidget->setAttribute(Qt::WA_LayoutUsesWidgetRect); 132 d->layout->addWidget(neww); 133 NSView *sideWidgetView = reinterpret_cast<NSView *>(d->sideWidget->winId()); 134 [sideWidgetView setAutoresizingMask:NSViewWidthSizable]; 135 d->sideWidget->show(); 136 NSRect frame = [[d->nsdrawer contentView] frame]; 137 d->nativeWidget->resize(QSize(frame.size.width, frame.size.height)); 138 } 139} 140 141// protected 142void KLFDrawerSideWidgetManager::newParentWidgetSet(QWidget */*oldp*/, QWidget *newWidget) 143{ 144 if (d->sideWidget->parentWidget() != newWidget) { 145 d->sideWidget->setParent(newWidget); 146 } 147} 148 149bool KLFDrawerSideWidgetManager::sideWidgetVisible() const 150{ 151 NSInteger s = [d->nsdrawer state]; 152 return (s == NSDrawerOpenState || s == NSDrawerOpeningState); 153} 154 155void KLFDrawerSideWidgetManager::showSideWidget(bool show) 156{ 157 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ; 158 159 if (show == sideWidgetVisible()) { 160 klfDbg("show == sideWidgetVisible() == " << show); 161 return; 162 } 163 164 klfDbg("show=" << show << "; sideWidgetVisible()=" << sideWidgetVisible()); 165 166 if (show) { 167 [d->nsdrawer openOnEdge:nsEdgeForQtEdge(d->openEdge)]; 168 } else { 169 [d->nsdrawer close]; 170 } 171 172 emit sideWidgetShown(show); 173} 174 175bool KLFDrawerSideWidgetManager::showHideIsAnimating() 176{ 177 NSInteger s = [d->nsdrawer state]; 178 return (s == NSDrawerOpeningState || s == NSDrawerClosingState); 179} 180 181 182KLF_DEFINE_PROPERTY_GET(KLFDrawerSideWidgetManager, Qt::DockWidgetArea, openEdge) ; 183 184void KLFDrawerSideWidgetManager::setOpenEdge(Qt::DockWidgetArea edge) 185{ 186 d->openEdge = edge; 187} 188 189 190 191