File indexing completed on 2024-04-14 05:39:37

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 //--------------------------------------------------------------------------------