File indexing completed on 2024-04-14 15:49:48
0001 // SPDX-License-Identifier: GPL-3.0-or-later 0002 /* 0003 Copyright 2017, 2018 Martin Koller, kollix@aon.at 0004 0005 This file is part of liquidshell. 0006 0007 liquidshell is free software: you can redistribute it and/or modify 0008 it under the terms of the GNU General Public License as published by 0009 the Free Software Foundation, either version 3 of the License, or 0010 (at your option) any later version. 0011 0012 liquidshell is distributed in the hope that it will be useful, 0013 but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0015 GNU General Public License for more details. 0016 0017 You should have received a copy of the GNU General Public License 0018 along with liquidshell. If not, see <http://www.gnu.org/licenses/>. 0019 */ 0020 0021 #include <PagerButton.hxx> 0022 #include <DesktopPanel.hxx> 0023 0024 #include <QPainter> 0025 #include <QStyle> 0026 #include <QStyleOptionButton> 0027 #include <QDragEnterEvent> 0028 #include <QDragLeaveEvent> 0029 #include <QDropEvent> 0030 #include <QMimeData> 0031 #include <QMenu> 0032 #include <QDebug> 0033 0034 #include <KWinCompat.hxx> 0035 #include <KIconLoader> 0036 #include <KIconEffect> 0037 0038 //-------------------------------------------------------------------------------- 0039 0040 PagerButton::PagerButton(int num, DesktopPanel *p, bool doShowIcon) 0041 : desktop(num), panel(p), showIcon(doShowIcon) 0042 { 0043 setText(KWinCompat::desktopName(desktop).isEmpty() ? 0044 QString::number(desktop) : KWinCompat::desktopName(desktop)); 0045 0046 setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); 0047 setAcceptDrops(true); 0048 dragDropTimer.setSingleShot(true); 0049 dragDropTimer.setInterval(1000); 0050 connect(&dragDropTimer, &QTimer::timeout, this, [this]() { emit clicked(true); }); 0051 0052 if ( showIcon ) 0053 { 0054 createPixmap(); 0055 0056 connect(KWinCompat::self(), &KWinCompat::windowAdded, 0057 this, &PagerButton::createPixmap); 0058 0059 connect(KWinCompat::self(), &KWinCompat::windowRemoved, 0060 this, &PagerButton::createPixmap); 0061 0062 connect(KWinCompat::self(), &KWinCompat::stackingOrderChanged, 0063 this, &PagerButton::createPixmap); 0064 0065 connect(KWinCompat::self(), SIGNAL(windowChanged(WId, NET::Properties, NET::Properties2)), 0066 this, SLOT(windowChanged(WId, NET::Properties, NET::Properties2))); 0067 0068 // when an application changes its icon very often very fast (windowChanged called) 0069 // (e.g. davmail when no network connection available) 0070 // let's avoid that liquidshell uses 100% CPU 0071 pixmapTimer.setSingleShot(true); 0072 pixmapTimer.setInterval(300); 0073 connect(&pixmapTimer, &QTimer::timeout, this, &PagerButton::createPixmap); 0074 0075 connect(KIconLoader::global(), &KIconLoader::iconLoaderSettingsChanged, this, [this]() { updateGeometry(); }); 0076 } 0077 0078 connect(KWinCompat::self(), &KWinCompat::desktopNamesChanged, this, 0079 [this]() 0080 { 0081 setText(KWinCompat::desktopName(desktop).isEmpty() ? 0082 QString::number(desktop) : KWinCompat::desktopName(desktop)); 0083 }); 0084 } 0085 0086 //-------------------------------------------------------------------------------- 0087 0088 QSize PagerButton::sizeHint() const 0089 { 0090 QSize s = fontMetrics().size(0, text()); 0091 s.setWidth(std::max(45, s.width() + 10)); 0092 s.setHeight(QPushButton::sizeHint().height() - 2); 0093 0094 if ( panel->getRows() == 1 ) 0095 s.setHeight(std::max(s.height(), KIconLoader::global()->currentSize(KIconLoader::Panel))); 0096 0097 return s; 0098 } 0099 0100 //-------------------------------------------------------------------------------- 0101 0102 void PagerButton::paintEvent(QPaintEvent *event) 0103 { 0104 Q_UNUSED(event); 0105 0106 QPainter painter(this); 0107 0108 QStyleOptionButton option; 0109 initStyleOption(&option); 0110 0111 style()->drawControl(QStyle::CE_PushButtonBevel, &option, &painter, this); 0112 0113 if ( !firstPixmap.isNull() ) 0114 painter.drawPixmap((width() - firstPixmap.width()) / 2, (height() - firstPixmap.height()) / 2, firstPixmap); 0115 0116 style()->drawControl(QStyle::CE_PushButtonLabel, &option, &painter, this); 0117 } 0118 0119 //-------------------------------------------------------------------------------- 0120 0121 void PagerButton::createPixmap() 0122 { 0123 firstPixmap = QPixmap(); 0124 QList<WId> windows = KWinCompat::stackingOrder(); 0125 0126 // from top to bottom 0127 for (int i = windows.count() - 1; i >= 0; i--) 0128 { 0129 WId wid = windows[i]; 0130 KWindowInfo win(wid, NET::WMDesktop | NET::WMWindowType | NET::WMState | NET::WMIcon); 0131 0132 if ( win.valid(true) && win.isOnDesktop(desktop) && 0133 (win.windowType(NET::DesktopMask) != NET::Desktop) && 0134 (win.windowType(NET::DockMask) != NET::Dock) && 0135 !(win.state() & NET::SkipTaskbar) ) 0136 { 0137 firstPixmap = KWinCompat::icon(wid, 22, 22, true); 0138 0139 KIconEffect effect; 0140 firstPixmap = effect.apply(firstPixmap, KIconEffect::DeSaturate, 0, QColor(), true); 0141 0142 break; 0143 } 0144 } 0145 0146 update(); 0147 } 0148 0149 //-------------------------------------------------------------------------------- 0150 0151 void PagerButton::windowChanged(WId id, NET::Properties props, NET::Properties2 props2) 0152 { 0153 Q_UNUSED(id) 0154 Q_UNUSED(props2) 0155 0156 if ( props & (NET::WMIcon | NET::WMDesktop) ) 0157 pixmapTimer.start(); 0158 } 0159 0160 //-------------------------------------------------------------------------------- 0161 0162 void PagerButton::dragEnterEvent(QDragEnterEvent *event) 0163 { 0164 event->accept(); 0165 dragDropTimer.start(); 0166 } 0167 0168 //-------------------------------------------------------------------------------- 0169 0170 void PagerButton::dragLeaveEvent(QDragLeaveEvent *event) 0171 { 0172 event->accept(); 0173 dragDropTimer.stop(); 0174 } 0175 0176 //-------------------------------------------------------------------------------- 0177 0178 void PagerButton::dropEvent(QDropEvent *event) 0179 { 0180 dragDropTimer.stop(); 0181 0182 if ( !event->mimeData()->hasFormat("application/x-winId") ) 0183 { 0184 event->ignore(); 0185 return; 0186 } 0187 0188 event->acceptProposedAction(); 0189 WId wid = static_cast<WId>(event->mimeData()->data("application/x-winId").toInt()); 0190 0191 KWinCompat::setOnDesktop(wid, desktop); 0192 } 0193 0194 //--------------------------------------------------------------------------------