File indexing completed on 2024-04-21 16:30:31

0001 // SPDX-License-Identifier: GPL-3.0-or-later
0002 /*
0003   Copyright 2017 - 2020 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 <AppMenu.hxx>
0022 #include <IconButton.hxx>
0023 #include <DesktopWidget.hxx>
0024 
0025 #include <QGridLayout>
0026 #include <QToolButton>
0027 #include <QStandardPaths>
0028 #include <QDir>
0029 #include <QMimeDatabase>
0030 #include <QApplication>
0031 #include <QScreen>
0032 
0033 #include <KFileItem>
0034 #include <KDesktopFile>
0035 #include <KIOWidgets/KRun>
0036 #include <KIconLoader>
0037 
0038 //--------------------------------------------------------------------------------
0039 
0040 AppMenu::AppMenu(DesktopPanel *parent)
0041   : Launcher(parent, "AppMenu")
0042 {
0043   button = new QToolButton;  // QToolButton is smaller than QPushButton
0044   adjustIconSize();
0045   button->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
0046 
0047   connect(button, &QToolButton::pressed, this, &AppMenu::showMenu);
0048 
0049   layout()->addWidget(button);
0050   loadConfig(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation));
0051 
0052   connect(parent, &DesktopPanel::rowsChanged, this, &AppMenu::adjustIconSize);
0053   connect(KIconLoader::global(), &KIconLoader::iconLoaderSettingsChanged, this, &AppMenu::adjustIconSize);
0054   connect(KIconLoader::global(), &KIconLoader::iconLoaderSettingsChanged, this, &AppMenu::fill);
0055 }
0056 
0057 //--------------------------------------------------------------------------------
0058 
0059 void AppMenu::adjustIconSize()
0060 {
0061   const int MAX_ROWS = qobject_cast<DesktopPanel *>(parentWidget())->getRows();
0062 
0063   if ( MAX_ROWS > 1 )
0064     button->setIconSize(QSize(48, 48));
0065   else
0066   {
0067     int size = KIconLoader::global()->currentSize(KIconLoader::Panel);
0068     button->setIconSize(QSize(size, size));
0069   }
0070 }
0071 
0072 //--------------------------------------------------------------------------------
0073 
0074 void AppMenu::fill()
0075 {
0076   KDesktopFile desktopFile(dirPath + "/.directory");
0077 
0078   if ( !desktopFile.readIcon().isEmpty() )
0079     button->setIcon(QIcon::fromTheme(desktopFile.readIcon()));
0080   else if ( dirPath == QStandardPaths::writableLocation(QStandardPaths::DesktopLocation) )
0081     button->setIcon(QIcon::fromTheme("user-desktop"));
0082   else // fallback
0083     button->setIcon(QIcon::fromTheme("folder"));
0084 }
0085 
0086 //--------------------------------------------------------------------------------
0087 
0088 void AppMenu::showMenu()
0089 {
0090   Menu *popup = new Menu(button);
0091 
0092   QDir dir(dirPath);
0093   QFileInfoList entries = dir.entryInfoList(QDir::AllEntries | QDir::NoDotDot);
0094 
0095   int row = 0, col = 0, h = 0;
0096   const int maxHeight = DesktopWidget::availableSize().height();
0097 
0098   for (const QFileInfo &info : entries)
0099   {
0100     QUrl url(QUrl::fromLocalFile(info.absoluteFilePath()));
0101     QString name;
0102     QIcon icon;
0103 
0104     KFileItem item(url);
0105 
0106     if ( item.isDesktopFile() )
0107     {
0108       KDesktopFile desktopFile(info.absoluteFilePath());
0109       if ( desktopFile.noDisplay() )
0110         continue;
0111 
0112       name = desktopFile.readName();
0113       if ( name.isEmpty() )
0114         name = desktopFile.readGenericName();
0115 
0116       QString iconName = desktopFile.readIcon();
0117       icon = QIcon::fromTheme(iconName.isEmpty() ? name : iconName);
0118     }
0119     else if ( info.isDir() )
0120     {
0121       if ( info.fileName() == "." )
0122       {
0123         name = info.dir().dirName();
0124         icon = button->icon();
0125       }
0126       else
0127         icon = QIcon::fromTheme("folder");
0128     }
0129     else
0130     {
0131       QMimeDatabase db;
0132       icon = QIcon::fromTheme(db.mimeTypeForFile(info.absoluteFilePath()).iconName());
0133     }
0134 
0135     if ( name.isEmpty() )
0136       name = info.fileName();
0137 
0138     IconButton *entryButton = new IconButton(this, icon, 32, name);
0139     connect(entryButton, &IconButton::clicked, [this, url, popup]() { popup->close(); new KRun(url, nullptr); });
0140 
0141     h += entryButton->sizeHint().height();
0142 
0143     if ( h >= maxHeight )
0144     {
0145       h = entryButton->sizeHint().height();
0146       col++;
0147       row = 0;
0148     }
0149 
0150     static_cast<QGridLayout *>(popup->layout())->addWidget(entryButton, row++, col);
0151   }
0152 
0153   popup->exec();
0154   button->setDown(false);
0155   delete popup;
0156 }
0157 
0158 //--------------------------------------------------------------------------------
0159 //--------------------------------------------------------------------------------
0160 //--------------------------------------------------------------------------------
0161 
0162 Menu::Menu(QWidget *parent)
0163   : QMenu(parent)
0164 {
0165   QGridLayout *grid = new QGridLayout(this);
0166   grid->setContentsMargins(QMargins());
0167   grid->setSpacing(0);
0168 }
0169 
0170 //--------------------------------------------------------------------------------
0171 
0172 void Menu::hideEvent(QHideEvent *event)
0173 {
0174   Q_UNUSED(event);
0175   eventLoop.exit();
0176 }
0177 
0178 //--------------------------------------------------------------------------------
0179 
0180 void Menu::exec()
0181 {
0182   adjustSize();
0183   QPoint p = parentWidget()->mapToGlobal(QPoint(0, 0));
0184   move(p.x(), p.y() - height());
0185   show();
0186   eventLoop.exec();
0187 }
0188 
0189 //--------------------------------------------------------------------------------