diff --git a/AppMenu.cxx b/AppMenu.cxx
index 9e50994..f9e2c34 100644
--- a/AppMenu.cxx
+++ b/AppMenu.cxx
@@ -1,224 +1,194 @@
/*
Copyright 2017 Martin Koller, kollix@aon.at
This file is part of liquidshell.
liquidshell is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
liquidshell is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with liquidshell. If not, see .
*/
#include
+#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//--------------------------------------------------------------------------------
AppMenu::AppMenu(DesktopPanel *parent)
: Launcher(parent, "AppMenu")
{
button = new QToolButton; // QToolButton is smaller than QPushButton
adjustIconSize();
button->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
popup = new Menu(button);
connect(button, &QToolButton::pressed, this, &AppMenu::showMenu);
layout()->addWidget(button);
loadConfig(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation));
connect(parent, &DesktopPanel::rowsChanged, this, &AppMenu::adjustIconSize);
connect(KIconLoader::global(), &KIconLoader::iconLoaderSettingsChanged, this, &AppMenu::adjustIconSize);
connect(KIconLoader::global(), &KIconLoader::iconLoaderSettingsChanged, this, &AppMenu::fill);
connect(QApplication::desktop(), &QDesktopWidget::resized, this, &AppMenu::fill);
}
//--------------------------------------------------------------------------------
void AppMenu::adjustIconSize()
{
const int MAX_ROWS = qobject_cast(parentWidget())->getRows();
if ( MAX_ROWS > 1 )
button->setIconSize(QSize(48, 48));
else
{
int size = KIconLoader::global()->currentSize(KIconLoader::Panel);
button->setIconSize(QSize(size, size));
}
}
//--------------------------------------------------------------------------------
void AppMenu::fill()
{
KDesktopFile desktopFile(dirPath + "/.directory");
if ( !desktopFile.readIcon().isEmpty() )
button->setIcon(QIcon::fromTheme(desktopFile.readIcon()));
else if ( dirPath == QStandardPaths::writableLocation(QStandardPaths::DesktopLocation) )
button->setIcon(QIcon::fromTheme("user-desktop"));
else // fallback
button->setIcon(QIcon::fromTheme("folder"));
QLayoutItem *child;
while ( (child = popup->layout()->takeAt(0)) )
{
delete child->widget();
delete child;
}
QDir dir(dirPath);
QFileInfoList entries = dir.entryInfoList(QDir::AllEntries | QDir::NoDotDot);
int row = 0, col = 0, h = 0;
const int maxHeight = QApplication::desktop()->height() - parentWidget()->sizeHint().height();
for (const QFileInfo &info : entries)
{
QUrl url(QUrl::fromLocalFile(info.absoluteFilePath()));
QString name;
QIcon icon;
KFileItem item(url);
if ( item.isDesktopFile() )
{
KDesktopFile desktopFile(info.absoluteFilePath());
if ( desktopFile.noDisplay() )
continue;
name = desktopFile.readName();
if ( name.isEmpty() )
name = desktopFile.readGenericName();
QString iconName = desktopFile.readIcon();
icon = QIcon::fromTheme(iconName.isEmpty() ? name : iconName);
}
else if ( info.isDir() )
{
if ( info.fileName() == "." )
{
name = info.dir().dirName();
icon = button->icon();
}
else
icon = QIcon::fromTheme("folder");
}
else
{
QMimeDatabase db;
icon = QIcon::fromTheme(db.mimeTypeForFile(info.absoluteFilePath()).iconName());
}
if ( name.isEmpty() )
name = info.fileName();
- AppButton *entryButton = new AppButton(this, icon, name);
- entryButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
- connect(entryButton, &AppButton::clicked, [this, url]() { popup->close(); new KRun(url, nullptr); });
+ IconButton *entryButton = new IconButton(this, icon, 32, name);
+ connect(entryButton, &IconButton::clicked, [this, url]() { popup->close(); new KRun(url, nullptr); });
h += entryButton->sizeHint().height();
if ( h >= maxHeight )
{
h = entryButton->sizeHint().height();
col++;
row = 0;
}
static_cast(popup->layout())->addWidget(entryButton, row++, col);
}
}
//--------------------------------------------------------------------------------
void AppMenu::showMenu()
{
popup->exec();
button->setDown(false);
}
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
Menu::Menu(QWidget *parent)
: QMenu(parent)
{
QGridLayout *grid = new QGridLayout(this);
grid->setContentsMargins(QMargins());
grid->setSpacing(0);
}
//--------------------------------------------------------------------------------
void Menu::hideEvent(QHideEvent *event)
{
Q_UNUSED(event);
eventLoop.exit();
}
//--------------------------------------------------------------------------------
void Menu::exec()
{
adjustSize();
QPoint p = parentWidget()->mapToGlobal(QPoint(0, 0));
move(p.x(), p.y() - height());
show();
eventLoop.exec();
}
//--------------------------------------------------------------------------------
-//--------------------------------------------------------------------------------
-//--------------------------------------------------------------------------------
-// helper class to ensure the positioning of the icon and text independent of the style
-
-#include
-
-AppButton::AppButton(QWidget *parent, const QIcon &icon, const QString &name)
- : QToolButton(parent)
-{
- setAutoRaise(true);
- QHBoxLayout *hbox = new QHBoxLayout(this);
-
- QLabel *iconLabel = new QLabel;
- iconLabel->setContextMenuPolicy(Qt::PreventContextMenu);
- iconLabel->setFixedSize(32, 32);
- iconLabel->setPixmap(icon.pixmap(QSize(32, 32)));
- hbox->addWidget(iconLabel);
-
- QLabel *textLabel = new QLabel(name);
- hbox->addWidget(textLabel);
-}
-
-//--------------------------------------------------------------------------------
-
-QSize AppButton::sizeHint() const
-{
- return layout()->sizeHint();
-}
-
-//--------------------------------------------------------------------------------
diff --git a/AppMenu.hxx b/AppMenu.hxx
index 5bd2c2b..9bfb17d 100644
--- a/AppMenu.hxx
+++ b/AppMenu.hxx
@@ -1,81 +1,70 @@
/*
Copyright 2017 Martin Koller, kollix@aon.at
This file is part of liquidshell.
liquidshell is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
liquidshell is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with liquidshell. If not, see .
*/
#ifndef _AppMenu_H_
#define _AppMenu_H_
#include
#include
#include
#include
#include
#include
//--------------------------------------------------------------------------------
class AppMenu : public Launcher
{
Q_OBJECT
public:
AppMenu(DesktopPanel *parent);
private Q_SLOTS:
void adjustIconSize();
void fill() override;
void showMenu();
private:
QToolButton *button;
class Menu *popup;
};
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
class Menu : public QMenu
{
Q_OBJECT
public:
Menu(QWidget *parent);
void exec();
protected:
void hideEvent(QHideEvent *event) override;
private:
QEventLoop eventLoop;
};
-//--------------------------------------------------------------------------------
-//--------------------------------------------------------------------------------
-
-class AppButton : public QToolButton
-{
- public:
- AppButton(QWidget *parent, const QIcon &icon, const QString &name);
-
- QSize sizeHint() const override;
-};
-
//--------------------------------------------------------------------------------
#endif
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8911248..3694d53 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,130 +1,131 @@
cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
project(liquidshell)
find_package(ECM 1.3.0 REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH})
include(KDEInstallDirs)
include(KDECompilerSettings NO_POLICY_SCOPE)
include(KDECMakeSettings)
include(ECMInstallIcons)
find_package(Qt5 5.6 CONFIG REQUIRED COMPONENTS
Core
Widgets
DBus
X11Extras
)
find_package(KF5 REQUIRED COMPONENTS
WindowSystem WidgetsAddons ConfigWidgets Config KIO IconThemes ItemViews Archive
Notifications I18n NetworkManagerQt Service Solid BluezQt KCMUtils Crash DBusAddons
NewStuff
)
find_package(packagekitqt5 REQUIRED)
set(SOURCES
desktop.cxx
DesktopWidget.cxx
DesktopPanel.cxx
OnScreenVolume.cxx
ConfigureDesktopDialog.cxx
StartMenu.cxx
Launcher.cxx
QuickLaunch.cxx
+ IconButton.cxx
AppMenu.cxx
Pager.cxx
PagerButton.cxx
WindowList.cxx
ClockWidget.cxx
ClockWidgetConfigureDialog.cxx
TaskBar.cxx
TaskBarButton.cxx
LockLogout.cxx
SysTray.cxx
SysTrayItem.cxx
SysTrayNotifyItem.cxx
DBusTypes.cxx
SysLoad.cxx
NotificationServer.cxx
NotificationList.cxx
Network.cxx
NetworkList.cxx
DeviceNotifier.cxx
DeviceList.cxx
Battery.cxx
Bluetooth.cxx
PopupMenu.cxx
PkUpdates.cxx
PkUpdateList.cxx
KdeConnect.cxx
DesktopApplet.cxx
WeatherApplet.cxx
WeatherAppletConfigureDialog.cxx
DiskUsageApplet.cxx
DiskUsageAppletConfigureDialog.cxx
)
# e.g. on openSuse Leap 42.3 compile fails as a GLib header included uses signals as var
add_definitions(-DQT_NO_SIGNALS_SLOTS_KEYWORDS)
ki18n_wrap_ui(UI_FILES
ConfigureDesktopDialog.ui
WeatherAppletConfigureDialog.ui
DiskUsageAppletConfigureDialog.ui
)
set(statusnotifieritem_xml ${KNOTIFICATIONS_DBUS_INTERFACES_DIR}/kf5_org.kde.StatusNotifierItem.xml)
set_source_files_properties(${statusnotifieritem_xml} PROPERTIES
INCLUDE "DBusTypes.hxx"
CLASSNAME OrgKdeStatusNotifierItem
)
qt5_add_dbus_interface(SOURCES ${statusnotifieritem_xml} statusnotifieritem_interface)
qt5_add_dbus_adaptor(SOURCES org.freedesktop.Notifications.xml NotificationServer.hxx NotificationServer)
set(TARGET liquidshell)
add_executable(${TARGET} ${SOURCES} ${UI_FILES})
set_property(TARGET ${TARGET} PROPERTY CXX_STANDARD 11)
target_link_libraries(${TARGET}
Qt5::Core
Qt5::Widgets
Qt5::DBus
Qt5::X11Extras
KF5::WindowSystem
KF5::WidgetsAddons
KF5::ConfigWidgets
KF5::ConfigCore
KF5::KIOCore
KF5::KIOWidgets
KF5::IconThemes
KF5::Notifications
KF5::I18n
KF5::NetworkManagerQt
KF5::Service
KF5::Solid
KF5::BluezQt
KF5::KCMUtils
KF5::Crash
KF5::DBusAddons
KF5::ItemViews
KF5::Archive
KF5::NewStuff
PK::packagekitqt5
)
install(TARGETS ${TARGET} ${INSTALL_TARGETS_DEFAULT_ARGS})
install(PROGRAMS org.kde.${TARGET}.desktop DESTINATION ${XDG_APPS_INSTALL_DIR})
install(FILES liquidshell.notifyrc DESTINATION ${KNOTIFYRC_INSTALL_DIR})
ecm_install_icons(ICONS
48-apps-liquidshell.png
DESTINATION ${ICON_INSTALL_DIR}
THEME hicolor)
diff --git a/DeviceList.cxx b/DeviceList.cxx
index ce0070c..8862d3c 100644
--- a/DeviceList.cxx
+++ b/DeviceList.cxx
@@ -1,539 +1,534 @@
/*
Copyright 2017, 2018 Martin Koller, kollix@aon.at
This file is part of liquidshell.
liquidshell is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
liquidshell is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with liquidshell. If not, see .
*/
#include
+#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//--------------------------------------------------------------------------------
DeviceItem::DeviceItem(Solid::Device dev, const QVector &deviceActions)
: device(dev)
{
setFrameShape(QFrame::StyledPanel);
QVBoxLayout *vbox = new QVBoxLayout(this);
QHBoxLayout *hbox = new QHBoxLayout;
vbox->addLayout(hbox);
QLabel *iconLabel = new QLabel;
iconLabel->setPixmap(QIcon::fromTheme(device.icon()).pixmap(32));
iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
newFlagLabel = new QLabel;
newFlagLabel->setPixmap(QIcon::fromTheme("emblem-important").pixmap(16));
newFlagLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
newFlagLabel->hide();
textLabel = new QLabel;
textLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
textLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
hbox->addWidget(iconLabel, 0, Qt::AlignLeft | Qt::AlignVCenter);
hbox->addWidget(newFlagLabel, 0, Qt::AlignCenter);
hbox->addWidget(textLabel, 0, Qt::AlignVCenter);
Solid::StorageAccess *storage = device.as();
if ( storage )
{
connect(storage, &Solid::StorageAccess::teardownDone, this, &DeviceItem::teardownDone);
connect(storage, &Solid::StorageAccess::setupDone, this, &DeviceItem::setupDone);
mountButton = new QToolButton;
mountButton->setIconSize(QSize(32, 32));
connect(mountButton, &QToolButton::clicked, mountButton,
[this]()
{
statusLabel->hide();
Solid::StorageAccess *storage = device.as();
if ( storage->isAccessible() ) // mounted -> unmount it
storage->teardown();
else
storage->setup();
}
);
hbox->addWidget(mountButton);
}
statusLabel = new QLabel;
statusLabel->setWordWrap(true);
statusLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
statusLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
vbox->addWidget(statusLabel);
statusLabel->hide();
statusTimer.setSingleShot(true);
statusTimer.setInterval(60000);
connect(&statusTimer, &QTimer::timeout, statusLabel, &QLabel::hide);
fillData();
// append actions
for (const DeviceAction &action : deviceActions)
{
QHBoxLayout *hbox = new QHBoxLayout;
hbox->addSpacing(iconLabel->sizeHint().width());
- QToolButton *button = new QToolButton;
- button->setAutoRaise(true);
- button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
- button->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
+ IconButton *button = new IconButton;
button->setIcon(QIcon::fromTheme(action.action.icon()));
button->setText(action.action.text() + " (" + QFileInfo(action.path).baseName() + ")");
- connect(button, &QToolButton::clicked, button,
+ connect(button, &IconButton::clicked, button,
[action, this]()
{
QString command = action.action.exec();
Solid::StorageAccess *storage = device.as();
if ( storage )
{
if ( !storage->isAccessible() )
{
statusLabel->hide();
storage->setup();
return;
}
command.replace("%f", storage->filePath());
}
if ( device.is() )
command.replace("%d", device.as()->device());
command.replace("%i", device.udi());
KRun::runCommand(command, this);
window()->hide();
}
);
hbox->addWidget(button);
vbox->addLayout(hbox);
}
}
//--------------------------------------------------------------------------------
DeviceItem::DeviceItem(const KdeConnect::Device &dev)
{
setFrameShape(QFrame::StyledPanel);
QVBoxLayout *vbox = new QVBoxLayout(this);
QHBoxLayout *hbox = new QHBoxLayout;
vbox->addLayout(hbox);
QLabel *iconLabel = new QLabel;
iconLabel->setPixmap(dev->icon.pixmap(32));
iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
newFlagLabel = new QLabel;
newFlagLabel->setPixmap(QIcon::fromTheme("emblem-important").pixmap(16));
newFlagLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
newFlagLabel->hide();
textLabel = new QLabel;
textLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
textLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
hbox->addWidget(iconLabel, 0, Qt::AlignLeft | Qt::AlignVCenter);
hbox->addWidget(newFlagLabel, 0, Qt::AlignCenter);
hbox->addWidget(textLabel, 0, Qt::AlignVCenter);
statusLabel = new QLabel;
hbox->addWidget(statusLabel, 0, Qt::AlignVCenter);
QLabel *chargeIcon = new QLabel;
hbox->addWidget(chargeIcon, 0, Qt::AlignVCenter);
if ( dev->charge >= 0 )
{
statusLabel->setText(QString::number(dev->charge) + '%');
chargeIcon->setPixmap(dev->chargeIcon.pixmap(22));
}
connect(dev.data(), &KdeConnectDevice::changed, this,
[this, chargeIcon, dev]()
{
textLabel->setText(dev->name);
if ( dev->charge >= 0 )
{
statusLabel->setText(QString::number(dev->charge) + '%');
chargeIcon->setPixmap(dev->chargeIcon.pixmap(22));
}
});
if ( dev->plugins.contains("kdeconnect_findmyphone") )
{
QToolButton *ringButton = new QToolButton;
ringButton->setIcon(QIcon::fromTheme("preferences-desktop-notification-bell"));
connect(ringButton, &QToolButton::clicked, dev.data(), [dev]() { dev->ringPhone(); });
hbox->addWidget(ringButton, 0, Qt::AlignVCenter);
}
QToolButton *configure = new QToolButton;
configure->setIcon(QIcon::fromTheme("configure"));
connect(configure, &QToolButton::clicked, configure,
[this]()
{
if ( !dialog )
{
dialog = new KCMultiDialog(nullptr);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->addModule("kcm_kdeconnect");
dialog->setWindowTitle(i18n("KDE Connect"));
dialog->adjustSize();
}
dialog->show();
});
hbox->addWidget(configure, 0, Qt::AlignVCenter);
textLabel->setText(dev->name);
if ( dev->plugins.contains("kdeconnect_sftp") )
{
QHBoxLayout *hbox = new QHBoxLayout;
hbox->addSpacing(iconLabel->sizeHint().width());
- QToolButton *button = new QToolButton;
- button->setAutoRaise(true);
- button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
- button->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
+ IconButton *button = new IconButton;
button->setIcon(QIcon::fromTheme("system-file-manager"));
button->setText(i18n("Open with File Manager"));
- connect(button, &QToolButton::clicked,
+ connect(button, &IconButton::clicked,
[dev]() { new KRun(QUrl(QLatin1String("kdeconnect://") + dev->id), nullptr); });
hbox->addWidget(button);
vbox->addLayout(hbox);
}
}
//--------------------------------------------------------------------------------
void DeviceItem::markAsNew()
{
newFlagLabel->show();
QTimer::singleShot(5000, newFlagLabel, &QLabel::hide);
}
//--------------------------------------------------------------------------------
void DeviceItem::fillData()
{
Solid::StorageAccess *storage = device.as();
QString text = device.description();
if ( !device.product().isEmpty() && (device.product() != text) )
text += " (" + device.product() + ")";
else if ( !device.vendor().isEmpty() && (device.vendor() != text) )
text += " (" + device.vendor() + ")";
Solid::StorageVolume *volume = device.as();
if ( volume )
text += " " + KIO::convertSize(volume->size());
if ( storage && !storage->filePath().isEmpty() )
text += '\n' + storage->filePath();
textLabel->setText(text);
if ( mountButton )
{
if ( storage && storage->isAccessible() )
mountButton->setIcon(QIcon::fromTheme("media-eject"));
else
{
if ( device.emblems().count() )
mountButton->setIcon(QIcon::fromTheme(device.emblems()[0]));
else
mountButton->setIcon(QIcon::fromTheme("emblem-unmounted"));
}
if ( storage )
{
mountButton->setToolTip(storage->isAccessible() ?
i18n("Device is mounted.\nClick to unmount/eject") :
i18n("Device is unmounted.\nClick to mount"));
}
}
}
//--------------------------------------------------------------------------------
QString DeviceItem::errorToString(Solid::ErrorType error)
{
switch ( error )
{
case Solid::UnauthorizedOperation: return i18n("Unauthorized Operation");
case Solid::DeviceBusy: return i18n("Device Busy");
case Solid::OperationFailed: return i18n("Operation Failed");
case Solid::UserCanceled: return i18n("User Canceled");
case Solid::InvalidOption: return i18n("Invalid Option");
case Solid::MissingDriver: return i18n("Missing Driver");
default: return QString();
}
}
//--------------------------------------------------------------------------------
void DeviceItem::mountDone(Action action, Solid::ErrorType error, QVariant errorData, const QString &udi)
{
Q_UNUSED(udi)
if ( error == Solid::NoError )
{
fillData();
if ( action == Unmount )
{
statusLabel->setText(i18n("The device can now be safely removed"));
statusLabel->show();
statusTimer.start();
}
}
else
{
QString text = (action == Mount) ? i18n("Mount failed:") : i18n("Unmount failed:");
statusLabel->setText("" + text + "" + errorToString(error) + "
" + errorData.toString());
statusLabel->show();
statusTimer.start();
}
}
//--------------------------------------------------------------------------------
void DeviceItem::teardownDone(Solid::ErrorType error, QVariant errorData, const QString &udi)
{
mountDone(Unmount, error, errorData, udi);
}
//--------------------------------------------------------------------------------
void DeviceItem::setupDone(Solid::ErrorType error, QVariant errorData, const QString &udi)
{
mountDone(Mount, error, errorData, udi);
}
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
DeviceList::DeviceList(QWidget *parent)
: QFrame(parent)
{
setWindowFlags(windowFlags() | Qt::Tool);
setFrameShape(QFrame::StyledPanel);
setAttribute(Qt::WA_AlwaysShowToolTips);
loadActions();
vbox = new QVBoxLayout(this);
vbox->setContentsMargins(QMargins());
vbox->addStretch();
predicate = Solid::Predicate(Solid::DeviceInterface::StorageAccess);
predicate |= Solid::Predicate(Solid::DeviceInterface::StorageDrive);
predicate |= Solid::Predicate(Solid::DeviceInterface::StorageVolume);
predicate |= Solid::Predicate(Solid::DeviceInterface::OpticalDrive);
predicate |= Solid::Predicate(Solid::DeviceInterface::OpticalDisc);
predicate |= Solid::Predicate(Solid::DeviceInterface::PortableMediaPlayer);
predicate |= Solid::Predicate(Solid::DeviceInterface::Camera);
QList devices = Solid::Device::listFromQuery(predicate);
for (Solid::Device device : devices)
addDevice(device);
connect(Solid::DeviceNotifier::instance(), &Solid::DeviceNotifier::deviceAdded,
this, &DeviceList::deviceAdded);
connect(Solid::DeviceNotifier::instance(), &Solid::DeviceNotifier::deviceRemoved,
this, &DeviceList::deviceRemoved);
connect(&kdeConnect, &KdeConnect::deviceAdded, this, &DeviceList::kdeConnectDeviceAdded);
connect(&kdeConnect, &KdeConnect::deviceRemoved, this, &DeviceList::deviceRemoved);
}
//--------------------------------------------------------------------------------
void DeviceList::loadActions()
{
actions.clear();
const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "solid/actions", QStandardPaths::LocateDirectory);
for (const QString &dirPath : dirs)
{
QDir dir(dirPath);
for (const QString &file : dir.entryList(QStringList(QLatin1String("*.desktop")), QDir::Files))
{
QString path = dir.absoluteFilePath(file);
KDesktopFile cfg(path);
const QString predicateString = cfg.desktopGroup().readEntry("X-KDE-Solid-Predicate");
QList actionList = KDesktopFileActions::userDefinedServices(path, true);
if ( !actionList.isEmpty() && !predicateString.isEmpty() )
actions.append(DeviceAction(path, Solid::Predicate::fromString(predicateString), actionList[0]));
}
}
}
//--------------------------------------------------------------------------------
DeviceItem *DeviceList::addDevice(Solid::Device device)
{
if ( items.contains(device.udi()) )
{
//qDebug() << device.udi() << "already known";
return nullptr;
}
QVector deviceActions;
for (const DeviceAction &action : actions)
{
if ( action.predicate.matches(device) )
deviceActions.append(action);
}
Solid::StorageVolume *storage = device.as();
if ( !storage ) // storage can at least be mounted; others need some specific actions
{
if ( deviceActions.isEmpty() )
{
//qDebug() << device.udi() << "no action found";
return nullptr;
}
}
else if ( storage->usage() != Solid::StorageVolume::FileSystem )
{
//qDebug() << device.udi() << "storage no filesystem";
return nullptr;
}
// show only removable devices
if ( device.is() &&
!device.as()->isRemovable() )
{
//qDebug() << device.udi() << "not Removable";
return nullptr;
}
// show only removable devices
if ( device.parent().is() &&
!device.parent().as()->isRemovable() )
{
//qDebug() << device.parent().udi() << "parent() not Removable";
return nullptr;
}
DeviceItem *item = new DeviceItem(device, deviceActions);
vbox->insertWidget(vbox->count() - 1, item); // insert before stretch
items.insert(device.udi(), item);
return item;
}
//--------------------------------------------------------------------------------
void DeviceList::deviceAdded(const QString &dev)
{
Solid::Device device(dev);
if ( !predicate.matches(device) )
return;
DeviceItem *item = addDevice(device);
// when we added a new device, make sure the DeviceNotifier shows and places this window
if ( item )
{
item->markAsNew();
emit deviceWasAdded();
}
}
//--------------------------------------------------------------------------------
void DeviceList::deviceRemoved(const QString &dev)
{
if ( items.contains(dev) )
{
delete items.take(dev);
emit deviceWasRemoved();
}
}
//--------------------------------------------------------------------------------
void DeviceList::kdeConnectDeviceAdded(const KdeConnect::Device &device)
{
if ( items.contains(device->id) )
{
//qDebug() << device->id << "already known";
return;
}
DeviceItem *item = new DeviceItem(device);
vbox->insertWidget(vbox->count() - 1, item); // insert before stretch
items.insert(device->id, item);
item->markAsNew();
// when we added a new device, make sure the DeviceNotifier shows and places this window
emit deviceWasAdded();
}
//--------------------------------------------------------------------------------
diff --git a/IconButton.cxx b/IconButton.cxx
new file mode 100644
index 0000000..198671c
--- /dev/null
+++ b/IconButton.cxx
@@ -0,0 +1,59 @@
+#include
+
+#include
+
+//--------------------------------------------------------------------------------
+
+IconButton::IconButton(QWidget *parent)
+ : QToolButton(parent)
+{
+ setAutoRaise(true);
+ setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
+
+ QHBoxLayout *hbox = new QHBoxLayout(this);
+
+ iconLabel = new QLabel;
+ iconLabel->setFixedSize(iconSize());
+ iconLabel->setContextMenuPolicy(Qt::PreventContextMenu);
+ hbox->addWidget(iconLabel);
+
+ textLabel = new QLabel;
+ hbox->addWidget(textLabel);
+}
+
+//--------------------------------------------------------------------------------
+
+IconButton::IconButton(QWidget *parent, const QIcon &icon, int theIconSize, const QString &name)
+ : IconButton(parent)
+{
+ if ( theIconSize != -1 )
+ setIconSize(QSize(theIconSize, theIconSize));
+
+ iconLabel->setFixedSize(iconSize());
+ iconLabel->setPixmap(icon.pixmap(iconSize()));
+
+ textLabel->setText(name);
+}
+
+//--------------------------------------------------------------------------------
+
+void IconButton::setText(const QString &txt)
+{
+ textLabel->setText(txt);
+}
+
+//--------------------------------------------------------------------------------
+
+void IconButton::setIcon(const QIcon &icon)
+{
+ iconLabel->setPixmap(icon.pixmap(iconSize()));
+}
+
+//--------------------------------------------------------------------------------
+
+QSize IconButton::sizeHint() const
+{
+ return layout()->sizeHint();
+}
+
+//--------------------------------------------------------------------------------
diff --git a/IconButton.hxx b/IconButton.hxx
new file mode 100644
index 0000000..873508e
--- /dev/null
+++ b/IconButton.hxx
@@ -0,0 +1,27 @@
+#ifndef _IconButton_H_
+#define _IconButton_H_
+
+#include
+#include
+
+// button class to ensure the positioning of the icon and text independent of the style
+
+class IconButton : public QToolButton
+{
+ Q_OBJECT
+
+ public:
+ IconButton(QWidget *parent = nullptr);
+ IconButton(QWidget *parent, const QIcon &icon, int iconSize, const QString &name);
+
+ void setText(const QString &txt);
+ void setIcon(const QIcon &icon);
+
+ QSize sizeHint() const override;
+
+ private:
+ QLabel *iconLabel = nullptr;
+ QLabel *textLabel = nullptr;
+};
+
+#endif
diff --git a/NetworkList.cxx b/NetworkList.cxx
index ec12a7a..946502e 100644
--- a/NetworkList.cxx
+++ b/NetworkList.cxx
@@ -1,289 +1,286 @@
/*
Copyright 2017 Martin Koller, kollix@aon.at
This file is part of liquidshell.
liquidshell is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
liquidshell is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with liquidshell. If not, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//--------------------------------------------------------------------------------
NetworkButton::NetworkButton(NetworkManager::Connection::Ptr c, NetworkManager::Device::Ptr dev)
: connection(c), device(dev)
{
- setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
- setAutoRaise(true);
setCheckable(true);
- setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
if ( connection )
{
for (const NetworkManager::ActiveConnection::Ptr &ac : NetworkManager::activeConnections())
{
if ( ac->uuid() == c->uuid() )
{
setChecked(true);
break;
}
}
connect(this, &NetworkButton::toggled, this, &NetworkButton::toggleNetworkStatus);
}
else
setEnabled(false);
}
//--------------------------------------------------------------------------------
void NetworkButton::toggleNetworkStatus(bool on)
{
if ( on )
{
switch ( connection->settings()->connectionType() )
{
case NetworkManager::ConnectionSettings::Wired:
{
NetworkManager::activateConnection(connection->path(), connection->settings()->interfaceName(), QString());
break;
}
case NetworkManager::ConnectionSettings::Wireless:
{
NetworkManager::activateConnection(connection->path(), device->uni(), QString());
break;
}
case NetworkManager::ConnectionSettings::Vpn:
{
NetworkManager::ActiveConnection::Ptr conn(NetworkManager::primaryConnection());
if ( conn && !conn->devices().isEmpty() )
NetworkManager::activateConnection(connection->path(), conn->devices()[0], QString());
break;
}
default: ; // TODO
}
}
else
{
for (const NetworkManager::ActiveConnection::Ptr &ac : NetworkManager::activeConnections())
{
if ( ac->uuid() == connection->uuid() )
{
NetworkManager::deactivateConnection(ac->path());
break;
}
}
}
}
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
NetworkList::NetworkList(QWidget *parent)
: QFrame(parent)
{
setWindowFlags(windowFlags() | Qt::Popup);
setFrameShape(QFrame::StyledPanel);
QVBoxLayout *vbox = new QVBoxLayout(this);
QHBoxLayout *hbox = new QHBoxLayout;
vbox->addLayout(hbox);
network = new QToolButton;
network->setIcon(QIcon::fromTheme("network-wired"));
network->setCheckable(true);
connect(network, &QToolButton::toggled, [](bool on) { NetworkManager::setNetworkingEnabled(on); });
connect(NetworkManager::notifier(), &NetworkManager::Notifier::networkingEnabledChanged, this, &NetworkList::statusUpdate);
hbox->addWidget(network);
wireless = new QToolButton;
wireless->setIcon(QIcon::fromTheme("network-wireless"));
wireless->setCheckable(true);
connect(wireless, &QToolButton::toggled, [](bool on) { NetworkManager::setWirelessEnabled(on); });
connect(NetworkManager::notifier(), &NetworkManager::Notifier::wirelessEnabledChanged, this, &NetworkList::statusUpdate);
hbox->addWidget(wireless);
statusUpdate();
hbox->addStretch();
QToolButton *configure = new QToolButton;
configure->setIcon(QIcon::fromTheme("configure"));
connect(configure, &QToolButton::clicked, this, &NetworkList::openConfigureDialog);
hbox->addWidget(configure);
// show connections
connectionsVbox = new QVBoxLayout;
connectionsVbox->setContentsMargins(QMargins());
vbox->addLayout(connectionsVbox);
fillConnections();
QTimer *checkConnectionsTimer = new QTimer(this);
checkConnectionsTimer->setInterval(1000);
connect(checkConnectionsTimer, &QTimer::timeout, this, &NetworkList::fillConnections);
checkConnectionsTimer->start();
}
//--------------------------------------------------------------------------------
void NetworkList::openConfigureDialog()
{
hide();
// newer plasma has already a KCM
KService::Ptr service = KService::serviceByDesktopName("kcm_networkmanagement");
if ( service )
KRun::runApplication(*service, QList(), this);
else
KRun::run("kde5-nm-connection-editor", QList(), this);
}
//--------------------------------------------------------------------------------
void NetworkList::statusUpdate()
{
network->setChecked(NetworkManager::isNetworkingEnabled());
wireless->setChecked(NetworkManager::isWirelessEnabled());
}
//--------------------------------------------------------------------------------
void NetworkList::fillConnections()
{
if ( underMouse() ) // avoid to delete the widget we are possibly hovering over
return;
QLayoutItem *child;
while ( (child = connectionsVbox->takeAt(0)) )
{
delete child->widget();
delete child;
}
NetworkManager::Connection::List allConnections = NetworkManager::listConnections();
for (const NetworkManager::Connection::Ptr c : allConnections)
{
if ( !c->isValid() )
continue;
if ( (c->settings()->connectionType() == NetworkManager::ConnectionSettings::Wired) &&
!c->uuid().isEmpty() )
{
- QToolButton *net = new NetworkButton(c);
+ NetworkButton *net = new NetworkButton(c);
net->setText(c->name());
net->setIcon(QIcon::fromTheme("network-wired"));
connectionsVbox->addWidget(net);
}
else if ( c->settings()->connectionType() == NetworkManager::ConnectionSettings::Vpn )
{
- QToolButton *vpn = new NetworkButton(c);
+ NetworkButton *vpn = new NetworkButton(c);
vpn->setText(c->name());
vpn->setIcon(QIcon::fromTheme("security-high"));
connectionsVbox->addWidget(vpn);
}
}
// show available wifi networks
if ( NetworkManager::isWirelessEnabled() )
{
for (const NetworkManager::Device::Ptr &device : NetworkManager::networkInterfaces())
{
if ( device->type() != NetworkManager::Device::Wifi )
continue;
NetworkManager::WirelessDevice::Ptr wifiDevice = device.objectCast();
for (const NetworkManager::WirelessNetwork::Ptr &network : wifiDevice->networks())
{
NetworkManager::AccessPoint::Ptr accessPoint = network->referenceAccessPoint();
if ( !accessPoint )
continue;
// check if we have a connection for this SSID
bool haveConnection = false;
NetworkManager::Connection::Ptr conn;
for (const NetworkManager::Connection::Ptr c : allConnections)
{
if ( c->isValid() && (c->settings()->connectionType() == NetworkManager::ConnectionSettings::Wireless) )
{
NetworkManager::Setting::Ptr setting = c->settings()->setting(NetworkManager::Setting::Wireless);
NetworkManager::WirelessSetting::Ptr s = setting.staticCast();
if ( s->ssid() == network->ssid() )
{
haveConnection = true;
conn = c;
break;
}
}
}
if ( haveConnection )
{
- QToolButton *net = new NetworkButton(conn, device);
+ NetworkButton *net = new NetworkButton(conn, device);
net->setText(QString("%1 (%2%)").arg(network->ssid()).arg(network->signalStrength()));
net->setIcon(QIcon::fromTheme("network-wireless"));
connectionsVbox->addWidget(net);
}
else
{
- QToolButton *net = new NetworkButton;
+ NetworkButton *net = new NetworkButton;
net->setText(QString("%1 (%2%)").arg(network->ssid()).arg(network->signalStrength()));
net->setIcon(QIcon::fromTheme("network-wireless"));
net->setEnabled(false); // TODO: allow to add a new connection. See NetworkManager::addAndActivateConnection
connectionsVbox->addWidget(net);
}
/*
NetworkManager::WirelessSecurityType security =
NetworkManager::findBestWirelessSecurity(wifiDevice->wirelessCapabilities(), true,
wifiDevice->mode() == NetworkManager::WirelessDevice::Adhoc,
accessPoint->capabilities(), accessPoint->wpaFlags(), accessPoint->rsnFlags());
if ( (security != NetworkManager::UnknownSecurity) && (security != NetworkManager::NoneSecurity) )
net->setIcon(QIcon::fromTheme("object-locked"));
else
net->setIcon(QIcon::fromTheme("object-unlocked"));
*/
}
}
}
connectionsVbox->addStretch();
adjustSize();
emit changed();
}
//--------------------------------------------------------------------------------
diff --git a/NetworkList.hxx b/NetworkList.hxx
index 924ba36..e16ec3a 100644
--- a/NetworkList.hxx
+++ b/NetworkList.hxx
@@ -1,67 +1,68 @@
/*
Copyright 2017 Martin Koller, kollix@aon.at
This file is part of liquidshell.
liquidshell is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
liquidshell is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with liquidshell. If not, see .
*/
#ifndef _NetworkList_H_
#define _NetworkList_H_
#include
#include
#include
class NetworkList : public QFrame
{
Q_OBJECT
public:
NetworkList(QWidget *parent);
Q_SIGNALS:
void changed();
private Q_SLOTS:
void statusUpdate();
void fillConnections();
void openConfigureDialog();
private:
QToolButton *network, *wireless;
QVBoxLayout *connectionsVbox;
};
//--------------------------------------------------------------------------------
#include
+#include
-class NetworkButton : public QToolButton
+class NetworkButton : public IconButton
{
Q_OBJECT
public:
NetworkButton(NetworkManager::Connection::Ptr c = NetworkManager::Connection::Ptr(),
NetworkManager::Device::Ptr dev = NetworkManager::Device::Ptr());
private Q_SLOTS:
void toggleNetworkStatus(bool on);
private:
NetworkManager::Connection::Ptr connection;
NetworkManager::Device::Ptr device;
};
#endif