|
| 1 | +// Copyright (C) 2023-2024 Stdware Collections (https://www.github.com/stdware) |
| 2 | +// Copyright (C) 2021-2023 wangwenx190 (Yuhang Zhao) |
| 3 | +// SPDX-License-Identifier: Apache-2.0 |
| 4 | + |
| 5 | +#include "windowbar.hpp" |
| 6 | +#include "windowbar_p.hpp" |
| 7 | + |
| 8 | +#include <QtCore/QDebug> |
| 9 | +#include <QtCore/QLocale> |
| 10 | +#include <QtGui/QtEvents> |
| 11 | + |
| 12 | +namespace QWK { |
| 13 | + |
| 14 | +WindowBarPrivate::WindowBarPrivate () { |
| 15 | + w = nullptr; |
| 16 | + autoTitle= true; |
| 17 | + autoIcon = false; |
| 18 | +} |
| 19 | + |
| 20 | +WindowBarPrivate::~WindowBarPrivate ()= default; |
| 21 | + |
| 22 | +void |
| 23 | +WindowBarPrivate::init () { |
| 24 | + Q_Q (WindowBar); |
| 25 | + layout= new QHBoxLayout (); |
| 26 | + if (QLocale::system ().textDirection () == Qt::RightToLeft) { |
| 27 | + layout->setDirection (QBoxLayout::RightToLeft); |
| 28 | + } |
| 29 | + |
| 30 | + layout->setContentsMargins (QMargins ()); |
| 31 | + layout->setSpacing (0); |
| 32 | + for (int i= IconButton; i <= CloseButton; ++i) { |
| 33 | + insertDefaultSpace (i); |
| 34 | + } |
| 35 | + q->setLayout (layout); |
| 36 | +} |
| 37 | + |
| 38 | +void |
| 39 | +WindowBarPrivate::setWidgetAt (int index, QWidget* widget) { |
| 40 | + auto item = layout->takeAt (index); |
| 41 | + auto orgWidget= item->widget (); |
| 42 | + if (orgWidget) { |
| 43 | + orgWidget->deleteLater (); |
| 44 | + } |
| 45 | + delete item; |
| 46 | + if (!widget) { |
| 47 | + insertDefaultSpace (index); |
| 48 | + } |
| 49 | + else { |
| 50 | + layout->insertWidget (index, widget); |
| 51 | + } |
| 52 | +} |
| 53 | + |
| 54 | +QWidget* |
| 55 | +WindowBarPrivate::takeWidgetAt (int index) { |
| 56 | + auto item = layout->itemAt (index); |
| 57 | + auto orgWidget= item->widget (); |
| 58 | + if (orgWidget) { |
| 59 | + item= layout->takeAt (index); |
| 60 | + delete item; |
| 61 | + insertDefaultSpace (index); |
| 62 | + } |
| 63 | + return orgWidget; |
| 64 | +} |
| 65 | + |
| 66 | +WindowBar::WindowBar (QWidget* parent) |
| 67 | + : WindowBar (*new WindowBarPrivate (), parent) {} |
| 68 | + |
| 69 | +WindowBar::~WindowBar ()= default; |
| 70 | + |
| 71 | +QMenuBar* |
| 72 | +WindowBar::menuBar () const { |
| 73 | + Q_D (const WindowBar); |
| 74 | + return static_cast<QMenuBar*> (d->widgetAt (WindowBarPrivate::MenuWidget)); |
| 75 | +} |
| 76 | + |
| 77 | +QLabel* |
| 78 | +WindowBar::titleLabel () const { |
| 79 | + Q_D (const WindowBar); |
| 80 | + return static_cast<QLabel*> (d->widgetAt (WindowBarPrivate::TitleLabel)); |
| 81 | +} |
| 82 | + |
| 83 | +QWidget* |
| 84 | +WindowBar::titleWidget () const { |
| 85 | + Q_D (const WindowBar); |
| 86 | + return d->widgetAt (WindowBarPrivate::TitleLabel); |
| 87 | +} |
| 88 | + |
| 89 | +QAbstractButton* |
| 90 | +WindowBar::iconButton () const { |
| 91 | + Q_D (const WindowBar); |
| 92 | + return static_cast<QAbstractButton*> ( |
| 93 | + d->widgetAt (WindowBarPrivate::IconButton)); |
| 94 | +} |
| 95 | + |
| 96 | +QAbstractButton* |
| 97 | +WindowBar::pinButton () const { |
| 98 | + Q_D (const WindowBar); |
| 99 | + return static_cast<QAbstractButton*> ( |
| 100 | + d->widgetAt (WindowBarPrivate::PinButton)); |
| 101 | +} |
| 102 | + |
| 103 | +QAbstractButton* |
| 104 | +WindowBar::minButton () const { |
| 105 | + Q_D (const WindowBar); |
| 106 | + return static_cast<QAbstractButton*> ( |
| 107 | + d->widgetAt (WindowBarPrivate::MinimizeButton)); |
| 108 | +} |
| 109 | + |
| 110 | +QAbstractButton* |
| 111 | +WindowBar::maxButton () const { |
| 112 | + Q_D (const WindowBar); |
| 113 | + return static_cast<QAbstractButton*> ( |
| 114 | + d->widgetAt (WindowBarPrivate::MaximizeButton)); |
| 115 | +} |
| 116 | + |
| 117 | +QAbstractButton* |
| 118 | +WindowBar::closeButton () const { |
| 119 | + Q_D (const WindowBar); |
| 120 | + return static_cast<QAbstractButton*> ( |
| 121 | + d->widgetAt (WindowBarPrivate::CloseButton)); |
| 122 | +} |
| 123 | + |
| 124 | +void |
| 125 | +WindowBar::setMenuBar (QMenuBar* menuBar) { |
| 126 | + Q_D (WindowBar); |
| 127 | + auto org= takeMenuBar (); |
| 128 | + if (org) org->deleteLater (); |
| 129 | + if (!menuBar) return; |
| 130 | + d->setWidgetAt (WindowBarPrivate::MenuWidget, menuBar); |
| 131 | + menuBar->setSizePolicy (QSizePolicy::Maximum, QSizePolicy::Minimum); |
| 132 | +} |
| 133 | + |
| 134 | +void |
| 135 | +WindowBar::setTitleLabel (QLabel* label) { |
| 136 | + // 使用setTitleWidget来保持一致性 |
| 137 | + setTitleWidget (label); |
| 138 | +} |
| 139 | + |
| 140 | +void |
| 141 | +WindowBar::setTitleWidget (QWidget* widget) { |
| 142 | + Q_D (WindowBar); |
| 143 | + auto org= takeTitleWidget (); |
| 144 | + if (org) org->deleteLater (); |
| 145 | + if (!widget) return; |
| 146 | + d->setWidgetAt (WindowBarPrivate::TitleLabel, widget); |
| 147 | + widget->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Minimum); |
| 148 | + |
| 149 | + // 如果设置的是QLabel,且开启了autoTitle,则设置文本 |
| 150 | + if (QLabel* label= qobject_cast<QLabel*> (widget)) { |
| 151 | + if (d->autoTitle && d->w) label->setText (d->w->windowTitle ()); |
| 152 | + } |
| 153 | +} |
| 154 | + |
| 155 | +void |
| 156 | +WindowBar::setIconButton (QAbstractButton* btn) { |
| 157 | + Q_D (WindowBar); |
| 158 | + auto org= takeIconButton (); |
| 159 | + if (org) org->deleteLater (); |
| 160 | + if (!btn) return; |
| 161 | + d->setWidgetAt (WindowBarPrivate::IconButton, btn); |
| 162 | + if (d->autoIcon && d->w) btn->setIcon (d->w->windowIcon ()); |
| 163 | + btn->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Preferred); |
| 164 | +} |
| 165 | + |
| 166 | +void |
| 167 | +WindowBar::setPinButton (QAbstractButton* btn) { |
| 168 | + Q_D (WindowBar); |
| 169 | + auto org= takePinButton (); |
| 170 | + if (org) org->deleteLater (); |
| 171 | + if (!btn) return; |
| 172 | + d->setWidgetAt (WindowBarPrivate::PinButton, btn); |
| 173 | + connect (btn, &QAbstractButton::clicked, this, &WindowBar::pinRequested); |
| 174 | +} |
| 175 | + |
| 176 | +void |
| 177 | +WindowBar::setMinButton (QAbstractButton* btn) { |
| 178 | + Q_D (WindowBar); |
| 179 | + auto org= takeMinButton (); |
| 180 | + if (org) org->deleteLater (); |
| 181 | + if (!btn) return; |
| 182 | + d->setWidgetAt (WindowBarPrivate::MinimizeButton, btn); |
| 183 | + connect (btn, &QAbstractButton::clicked, this, &WindowBar::minimizeRequested); |
| 184 | +} |
| 185 | + |
| 186 | +void |
| 187 | +WindowBar::setMaxButton (QAbstractButton* btn) { |
| 188 | + Q_D (WindowBar); |
| 189 | + auto org= takeMaxButton (); |
| 190 | + if (org) org->deleteLater (); |
| 191 | + if (!btn) return; |
| 192 | + d->setWidgetAt (WindowBarPrivate::MaximizeButton, btn); |
| 193 | + connect (btn, &QAbstractButton::clicked, this, &WindowBar::maximizeRequested); |
| 194 | +} |
| 195 | + |
| 196 | +void |
| 197 | +WindowBar::setCloseButton (QAbstractButton* btn) { |
| 198 | + Q_D (WindowBar); |
| 199 | + auto org= takeCloseButton (); |
| 200 | + if (org) org->deleteLater (); |
| 201 | + if (!btn) return; |
| 202 | + d->setWidgetAt (WindowBarPrivate::CloseButton, btn); |
| 203 | + connect (btn, &QAbstractButton::clicked, this, &WindowBar::closeRequested); |
| 204 | +} |
| 205 | + |
| 206 | +QMenuBar* |
| 207 | +WindowBar::takeMenuBar () { |
| 208 | + Q_D (WindowBar); |
| 209 | + return static_cast<QMenuBar*> ( |
| 210 | + d->takeWidgetAt (WindowBarPrivate::MenuWidget)); |
| 211 | +} |
| 212 | + |
| 213 | +QLabel* |
| 214 | +WindowBar::takeTitleLabel () { |
| 215 | + Q_D (WindowBar); |
| 216 | + return static_cast<QLabel*> (d->takeWidgetAt (WindowBarPrivate::TitleLabel)); |
| 217 | +} |
| 218 | + |
| 219 | +QWidget* |
| 220 | +WindowBar::takeTitleWidget () { |
| 221 | + Q_D (WindowBar); |
| 222 | + return d->takeWidgetAt (WindowBarPrivate::TitleLabel); |
| 223 | +} |
| 224 | + |
| 225 | +QAbstractButton* |
| 226 | +WindowBar::takeIconButton () { |
| 227 | + Q_D (WindowBar); |
| 228 | + return static_cast<QAbstractButton*> ( |
| 229 | + d->takeWidgetAt (WindowBarPrivate::IconButton)); |
| 230 | +} |
| 231 | + |
| 232 | +QAbstractButton* |
| 233 | +WindowBar::takePinButton () { |
| 234 | + Q_D (WindowBar); |
| 235 | + auto btn= static_cast<QAbstractButton*> ( |
| 236 | + d->takeWidgetAt (WindowBarPrivate::PinButton)); |
| 237 | + if (!btn) { |
| 238 | + return nullptr; |
| 239 | + } |
| 240 | + disconnect (btn, &QAbstractButton::clicked, this, &WindowBar::pinRequested); |
| 241 | + return btn; |
| 242 | +} |
| 243 | + |
| 244 | +QAbstractButton* |
| 245 | +WindowBar::takeMinButton () { |
| 246 | + Q_D (WindowBar); |
| 247 | + auto btn= static_cast<QAbstractButton*> ( |
| 248 | + d->takeWidgetAt (WindowBarPrivate::MinimizeButton)); |
| 249 | + if (!btn) { |
| 250 | + return nullptr; |
| 251 | + } |
| 252 | + disconnect (btn, &QAbstractButton::clicked, this, |
| 253 | + &WindowBar::minimizeRequested); |
| 254 | + return btn; |
| 255 | +} |
| 256 | + |
| 257 | +QAbstractButton* |
| 258 | +WindowBar::takeMaxButton () { |
| 259 | + Q_D (WindowBar); |
| 260 | + auto btn= static_cast<QAbstractButton*> ( |
| 261 | + d->takeWidgetAt (WindowBarPrivate::MaximizeButton)); |
| 262 | + if (!btn) { |
| 263 | + return nullptr; |
| 264 | + } |
| 265 | + disconnect (btn, &QAbstractButton::clicked, this, |
| 266 | + &WindowBar::maximizeRequested); |
| 267 | + return btn; |
| 268 | +} |
| 269 | + |
| 270 | +QAbstractButton* |
| 271 | +WindowBar::takeCloseButton () { |
| 272 | + Q_D (WindowBar); |
| 273 | + auto btn= static_cast<QAbstractButton*> ( |
| 274 | + d->takeWidgetAt (WindowBarPrivate::CloseButton)); |
| 275 | + if (!btn) { |
| 276 | + return nullptr; |
| 277 | + } |
| 278 | + disconnect (btn, &QAbstractButton::clicked, this, &WindowBar::closeRequested); |
| 279 | + return btn; |
| 280 | +} |
| 281 | + |
| 282 | +QWidget* |
| 283 | +WindowBar::hostWidget () const { |
| 284 | + Q_D (const WindowBar); |
| 285 | + return d->w; |
| 286 | +} |
| 287 | + |
| 288 | +void |
| 289 | +WindowBar::setHostWidget (QWidget* w) { |
| 290 | + Q_D (WindowBar); |
| 291 | + |
| 292 | + QWidget* org= d->w; |
| 293 | + if (org) { |
| 294 | + org->removeEventFilter (this); |
| 295 | + } |
| 296 | + d_ptr->w= w; |
| 297 | + if (w) { |
| 298 | + w->installEventFilter (this); |
| 299 | + } |
| 300 | +} |
| 301 | + |
| 302 | +bool |
| 303 | +WindowBar::titleFollowWindow () const { |
| 304 | + Q_D (const WindowBar); |
| 305 | + return d->autoTitle; |
| 306 | +} |
| 307 | + |
| 308 | +void |
| 309 | +WindowBar::setTitleFollowWindow (bool value) { |
| 310 | + Q_D (WindowBar); |
| 311 | + d->autoTitle= value; |
| 312 | +} |
| 313 | + |
| 314 | +bool |
| 315 | +WindowBar::iconFollowWindow () const { |
| 316 | + Q_D (const WindowBar); |
| 317 | + return d->autoIcon; |
| 318 | +} |
| 319 | + |
| 320 | +void |
| 321 | +WindowBar::setIconFollowWindow (bool value) { |
| 322 | + Q_D (WindowBar); |
| 323 | + d->autoIcon= value; |
| 324 | +} |
| 325 | + |
| 326 | +bool |
| 327 | +WindowBar::eventFilter (QObject* obj, QEvent* event) { |
| 328 | + Q_D (WindowBar); |
| 329 | + auto w= d->w; |
| 330 | + if (obj == w) { |
| 331 | + QAbstractButton* iconBtn = iconButton (); |
| 332 | + QWidget* titleWidget= this->titleWidget (); |
| 333 | + QLabel* label= qobject_cast<QLabel*> (titleWidget); // 检查是否为QLabel |
| 334 | + QAbstractButton* maxBtn= maxButton (); |
| 335 | + switch (event->type ()) { |
| 336 | + case QEvent::WindowIconChange: { |
| 337 | + if (d_ptr->autoIcon && iconBtn) { |
| 338 | + iconBtn->setIcon (w->windowIcon ()); |
| 339 | + iconChanged (w->windowIcon ()); |
| 340 | + } |
| 341 | + break; |
| 342 | + } |
| 343 | + case QEvent::WindowTitleChange: { |
| 344 | + if (d_ptr->autoTitle && label) { // 只对QLabel设置文本 |
| 345 | + label->setText (w->windowTitle ()); |
| 346 | + titleChanged (w->windowTitle ()); |
| 347 | + } |
| 348 | + break; |
| 349 | + } |
| 350 | + case QEvent::WindowStateChange: { |
| 351 | + if (maxBtn) { |
| 352 | + maxBtn->setChecked (w->isMaximized ()); |
| 353 | + } |
| 354 | + break; |
| 355 | + } |
| 356 | + default: |
| 357 | + break; |
| 358 | + } |
| 359 | + } |
| 360 | + return QWidget::eventFilter (obj, event); |
| 361 | +} |
| 362 | + |
| 363 | +void |
| 364 | +WindowBar::titleChanged (const QString& text) { |
| 365 | + Q_UNUSED (text) |
| 366 | +} |
| 367 | + |
| 368 | +void |
| 369 | +WindowBar::iconChanged (const QIcon& icon) { |
| 370 | + Q_UNUSED (icon) |
| 371 | +} |
| 372 | + |
| 373 | +WindowBar::WindowBar (WindowBarPrivate& d, QWidget* parent) |
| 374 | + : QFrame (parent), d_ptr (&d) { |
| 375 | + d.q_ptr= this; |
| 376 | + |
| 377 | + d.init (); |
| 378 | +} |
| 379 | + |
| 380 | +} // namespace QWK |
0 commit comments