1 /*
2 SPDX-FileCopyrightText: 2008-2014 Eike Hein <hein@kde.org>
3 SPDX-FileCopyrightText: 2020 Ryan McCoskrie <work@ryanmccoskrie.me>
4
5 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
6 */
7
8 #include "titlebar.h"
9 #include "mainwindow.h"
10 #include "skin.h"
11
12 #include <KLocalizedString>
13 #include <QFontDatabase>
14 #include <QMenu>
15 #include <QPushButton>
16
17 #include <QApplication>
18 #include <QBitmap>
19 #include <QPainter>
20
TitleBar(MainWindow * mainWindow)21 TitleBar::TitleBar(MainWindow *mainWindow)
22 : QWidget(mainWindow)
23 {
24 setWhatsThis(xi18nc("@info:whatsthis",
25 "<title>Title Bar</title>"
26 "<para>The title bar displays the session title if available.</para>"));
27
28 setAttribute(Qt::WA_OpaquePaintEvent);
29
30 m_mainWindow = mainWindow;
31 m_skin = mainWindow->skin();
32
33 setCursor(Qt::SizeVerCursor);
34
35 m_focusButton = new QPushButton(this);
36 m_focusButton->setFocusPolicy(Qt::NoFocus);
37 m_focusButton->setCheckable(true);
38 m_focusButton->setToolTip(xi18nc("@info:tooltip", "Keep window open when it loses focus"));
39 m_focusButton->setWhatsThis(xi18nc("@info:whatsthis", "If this is checked, the window will stay open when it loses focus."));
40 m_focusButton->setCursor(Qt::ArrowCursor);
41 connect(m_focusButton, SIGNAL(toggled(bool)), mainWindow, SLOT(setKeepOpen(bool)));
42
43 m_menuButton = new QPushButton(this);
44 m_menuButton->setFocusPolicy(Qt::NoFocus);
45 m_menuButton->setMenu(mainWindow->menu());
46 m_menuButton->setToolTip(xi18nc("@info:tooltip", "Open Menu"));
47 m_menuButton->setWhatsThis(xi18nc("@info:whatsthis", "Opens the main menu."));
48 m_menuButton->setCursor(Qt::ArrowCursor);
49
50 m_quitButton = new QPushButton(this);
51 m_quitButton->setFocusPolicy(Qt::NoFocus);
52 m_quitButton->setToolTip(xi18nc("@info:tooltip Quits the application", "Quit"));
53 m_quitButton->setWhatsThis(xi18nc("@info:whatsthis", "Quits the application."));
54 m_quitButton->setCursor(Qt::ArrowCursor);
55 connect(m_quitButton, SIGNAL(clicked()), mainWindow, SLOT(close()));
56 }
57
~TitleBar()58 TitleBar::~TitleBar()
59 {
60 }
61
setVisible(bool visible)62 void TitleBar::setVisible(bool visible)
63 {
64 m_visible = visible;
65 if (m_visible) {
66 resize(width(), m_skin->titleBarBackgroundImage().height());
67 } else {
68 resize(width(), 0);
69 }
70
71 QWidget::setVisible(m_visible);
72 }
73
applySkin()74 void TitleBar::applySkin()
75 {
76 resize(width(), m_visible ? m_skin->titleBarBackgroundImage().height() : 0);
77
78 m_focusButton->setStyleSheet(m_skin->titleBarFocusButtonStyleSheet());
79 m_menuButton->setStyleSheet(m_skin->titleBarMenuButtonStyleSheet());
80 m_quitButton->setStyleSheet(m_skin->titleBarQuitButtonStyleSheet());
81
82 moveButtons();
83
84 repaint();
85
86 updateMask();
87 }
88
moveButtons()89 void TitleBar::moveButtons()
90 {
91 if (m_skin->titleBarFocusButtonAnchor() == Qt::AnchorLeft)
92 m_focusButton->move(m_skin->titleBarFocusButtonPosition().x(), m_skin->titleBarFocusButtonPosition().y());
93 else if (m_skin->titleBarFocusButtonAnchor() == Qt::AnchorRight)
94 m_focusButton->move(width() - m_skin->titleBarFocusButtonPosition().x(), m_skin->titleBarFocusButtonPosition().y());
95
96 if (m_skin->titleBarMenuButtonAnchor() == Qt::AnchorLeft)
97 m_menuButton->move(m_skin->titleBarMenuButtonPosition().x(), m_skin->titleBarMenuButtonPosition().y());
98 else if (m_skin->titleBarMenuButtonAnchor() == Qt::AnchorRight)
99 m_menuButton->move(width() - m_skin->titleBarMenuButtonPosition().x(), m_skin->titleBarMenuButtonPosition().y());
100
101 if (m_skin->titleBarQuitButtonAnchor() == Qt::AnchorLeft)
102 m_quitButton->move(m_skin->titleBarQuitButtonPosition().x(), m_skin->titleBarQuitButtonPosition().y());
103 else if (m_skin->titleBarQuitButtonAnchor() == Qt::AnchorRight)
104 m_quitButton->move(width() - m_skin->titleBarQuitButtonPosition().x(), m_skin->titleBarQuitButtonPosition().y());
105 }
106
resizeEvent(QResizeEvent * event)107 void TitleBar::resizeEvent(QResizeEvent *event)
108 {
109 moveButtons();
110
111 updateMask();
112
113 QWidget::resizeEvent(event);
114 }
115
paintEvent(QPaintEvent *)116 void TitleBar::paintEvent(QPaintEvent *)
117 {
118 QPainter painter(this);
119 painter.setPen(m_skin->titleBarTextColor());
120
121 const QPixmap &backgroundImage = m_skin->titleBarBackgroundImage();
122 const QPixmap &leftCornerImage = m_skin->titleBarLeftCornerImage();
123 const QPixmap &rightCornerImage = m_skin->titleBarRightCornerImage();
124
125 painter.drawTiledPixmap(leftCornerImage.width(), 0, width() - leftCornerImage.width() - rightCornerImage.width(), height(), backgroundImage);
126
127 painter.drawPixmap(0, 0, leftCornerImage);
128 painter.drawPixmap(width() - rightCornerImage.width(), 0, rightCornerImage);
129
130 QFont font = QFontDatabase::systemFont(QFontDatabase::TitleFont);
131 font.setBold(m_skin->titleBarTextBold());
132 painter.setFont(font);
133
134 const QString title = this->title();
135 if (m_skin->titleBarTextCentered()
136 && width() > m_skin->titleBarTextPosition().x() + painter.fontMetrics().horizontalAdvance(title) + m_focusButton->width() + m_quitButton->width()
137 + m_menuButton->width())
138 painter.drawText(0, 0, width(), height(), Qt::AlignCenter, title);
139 else
140 painter.drawText(m_skin->titleBarTextPosition(), title);
141
142 painter.end();
143 }
144
mouseMoveEvent(QMouseEvent * event)145 void TitleBar::mouseMoveEvent(QMouseEvent *event)
146 {
147 if (event->buttons() == Qt::LeftButton) {
148 // Dynamic cast needed to use getDesktopGeometry()
149 MainWindow *window = dynamic_cast<MainWindow *>(parent());
150
151 int maxHeight = window->getDesktopGeometry().height();
152 int newHeight = event->globalY() / (maxHeight / 100);
153
154 // Correct newHeight if mouse is dragged too far
155 if (newHeight > 100) {
156 newHeight = 100;
157 } else if (newHeight < 10) {
158 newHeight = 10;
159 }
160
161 window->setWindowHeight(newHeight);
162 } else {
163 QWidget::mouseMoveEvent(event);
164 }
165 }
166
updateMask()167 void TitleBar::updateMask()
168 {
169 const QPixmap &leftCornerImage = m_skin->titleBarLeftCornerImage();
170 const QPixmap &rightCornerImage = m_skin->titleBarRightCornerImage();
171
172 QRegion leftCornerRegion = leftCornerImage.hasAlpha() ? QRegion(leftCornerImage.mask()) : QRegion(leftCornerImage.rect());
173 QRegion rightCornerRegion = rightCornerImage.hasAlpha() ? QRegion(rightCornerImage.mask()) : QRegion(rightCornerImage.rect());
174
175 QRegion mask = leftCornerRegion;
176
177 mask += QRegion(QRect(0, 0, width() - leftCornerImage.width() - rightCornerImage.width(), height())).translated(leftCornerImage.width(), 0);
178
179 mask += rightCornerRegion.translated(width() - rightCornerImage.width(), 0);
180
181 setMask(mask);
182 }
183
updateMenu()184 void TitleBar::updateMenu()
185 {
186 m_menuButton->setMenu(m_mainWindow->menu());
187 }
188
setFocusButtonState(bool checked)189 void TitleBar::setFocusButtonState(bool checked)
190 {
191 m_focusButton->setChecked(checked);
192 }
193
title()194 QString TitleBar::title()
195 {
196 if (!m_skin->titleBarText().isEmpty() && !m_title.isEmpty())
197 return m_title + QStringLiteral(" - ") + m_skin->titleBarText();
198 else if (!m_skin->titleBarText().isEmpty() && m_title.isEmpty())
199 return m_skin->titleBarText();
200 else
201 return m_title;
202 }
203
setTitle(const QString & title)204 void TitleBar::setTitle(const QString &title)
205 {
206 m_title = title;
207
208 repaint();
209 }
210