soliduiserver: implement feature to execute actions under certain conditions

can implement condition for when device changes occurs too but I have no
plans to use it for something, not yet that is. the remove condition can
(and probably will be) used to start kvkbd when there is no keyboard
plugged in altough that will require program to check when to do that

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2023-09-08 19:25:44 +03:00
parent 6692330c26
commit e4366d3493
11 changed files with 40 additions and 16 deletions

View file

@ -1,5 +1,6 @@
[Desktop Entry]
X-KDE-Solid-Predicate=Input.inputType == 'Mouse'
X-KDE-Solid-When=Add
Type=Service
Actions=configure;

View file

@ -1,5 +1,6 @@
[Desktop Entry]
X-KDE-Solid-Predicate=Input.inputType == 'Joystick'
X-KDE-Solid-When=Add
Type=Service
Actions=configure;

View file

@ -1,5 +1,6 @@
[Desktop Entry]
X-KDE-Solid-Predicate=Input.inputType == 'Keyboard'
X-KDE-Solid-When=Add
Type=Service
Actions=configure;

View file

@ -1,5 +1,6 @@
[Desktop Entry]
X-KDE-Solid-Predicate=Camera.supportedDrivers == 'gphoto'
X-KDE-Solid-When=Add,Search
Type=Service
Actions=open;

View file

@ -1,5 +1,6 @@
[Desktop Entry]
X-KDE-Solid-Predicate=PortableMediaPlayer.supportedProtocols == 'mtp'
X-KDE-Solid-When=Add,Search
Type=Service
Actions=open;

View file

@ -34,6 +34,7 @@
#include <Solid/Block>
static const QChar s_actionidseparator = QChar::fromLatin1('#');
static const QString s_whensearch = QString::fromLatin1("Search");
static QString kSolidUDI(const QString &matchid)
{
@ -98,7 +99,13 @@ QList<QAction*> SolidRunner::actionsForMatch(const Plasma::QueryMatch &match)
const QStringList solidactions = KGlobal::dirs()->findAllResources("data", "solid/actions/");
foreach (const QString &solidaction, solidactions) {
KDesktopFile kdestopfile(solidaction);
const QString solidpredicatestring = kdestopfile.desktopGroup().readEntry("X-KDE-Solid-Predicate");
KConfigGroup kconfiggroup = kdestopfile.desktopGroup();
const QStringList solidwhenlist = kconfiggroup.readEntry("X-KDE-Solid-When", QStringList());
if (!solidwhenlist.contains(s_whensearch)) {
continue;
}
const QString solidpredicatestring = kconfiggroup.readEntry("X-KDE-Solid-Predicate");
const Solid::Predicate solidpredicate = Solid::Predicate::fromString(solidpredicatestring);
if (solidpredicate.matches(soliddevice)) {
const QList<KServiceAction> kserviceactions = KDesktopFileActions::userDefinedServices(solidaction, true);
@ -214,7 +221,7 @@ void SolidRunner::run(const Plasma::RunnerContext &context, const Plasma::QueryM
const QList<KServiceAction> kserviceactions = KDesktopFileActions::userDefinedServices(actionfilepath, true);
foreach (const KServiceAction &kserviceaction, kserviceactions) {
if (kserviceaction.name() == actionname) {
QStringList actioncommand = kSolidActionCommand(kserviceaction.exec(), kSolidUDI(match.id()));
QStringList actioncommand = kSolidActionCommand(kserviceaction.exec(), kSolidUDI(match.id()), true);
if (actioncommand.size() == 0) {
kWarning() << "invalid action command" << actionname << "in" << actionfilepath;
return;

View file

@ -1,5 +1,6 @@
[Desktop Entry]
X-KDE-Solid-Predicate=[ [ [ StorageVolume.ignored == false AND [ StorageVolume.usage == 'FileSystem' OR StorageVolume.usage == 'Encrypted' ] ] OR [ IS StorageAccess AND StorageDrive.driveType == 'Floppy' ] ] OR StorageAccess.ignored == false ]
X-KDE-Solid-When=Add,Search
Type=Service
Actions=open;

View file

@ -26,10 +26,12 @@
SolidUiDialog::SolidUiDialog(const Solid::Device &soliddevice,
const QList<KServiceAction> &kserviceactions,
const bool mount,
QWidget *parent)
: KDialog(parent),
m_soliddevice(soliddevice),
m_serviceactions(kserviceactions),
m_mount(mount),
m_mainwidget(nullptr),
m_mainlayout(nullptr),
m_devicepixmap(nullptr),
@ -111,7 +113,7 @@ void SolidUiDialog::slotOkClicked()
const QListWidgetItem* selecteditem = selecteditems.first();
const int kserviceactionindex = selecteditem->data(Qt::UserRole).toInt();
Q_ASSERT(kserviceactionindex >= 0 && kserviceactionindex < m_serviceactions.size());
kExecuteAction(m_serviceactions.at(kserviceactionindex), m_soliddevice.udi());
kExecuteAction(m_serviceactions.at(kserviceactionindex), m_soliddevice.udi(), m_mount);
}
#include "moc_soliduidialog.cpp"

View file

@ -33,6 +33,7 @@ class SolidUiDialog : public KDialog
public:
SolidUiDialog(const Solid::Device &soliddevce,
const QList<KServiceAction> &kserviceactions,
const bool mount,
QWidget *parent = nullptr);
~SolidUiDialog();
@ -43,6 +44,7 @@ private Q_SLOTS:
private:
Solid::Device m_soliddevice;
QList<KServiceAction> m_serviceactions;
bool m_mount;
QWidget* m_mainwidget;
QGridLayout* m_mainlayout;
KPixmapWidget* m_devicepixmap;

View file

@ -42,8 +42,9 @@
#include <QDir>
K_PLUGIN_FACTORY(SolidUiServerFactory, registerPlugin<SolidUiServer>();)
K_EXPORT_PLUGIN(SolidUiServerFactory("soliduiserver"))
static const QString s_whenadd = QString::fromLatin1("Add");
static const QString s_whenremove = QString::fromLatin1("Remove");
static void kNotifyError(const Solid::ErrorType error, const bool unmount)
{
@ -51,6 +52,9 @@ static void kNotifyError(const Solid::ErrorType error, const bool unmount)
KNotification::event("soliduiserver/mounterror", title, Solid::errorString(error));
}
K_PLUGIN_FACTORY(SolidUiServerFactory, registerPlugin<SolidUiServer>();)
K_EXPORT_PLUGIN(SolidUiServerFactory("soliduiserver"))
SolidUiServer::SolidUiServer(QObject* parent, const QList<QVariant>&)
: KDEDModule(parent)
{
@ -250,22 +254,26 @@ QString SolidUiServer::errorString(const int error)
void SolidUiServer::handleActions(const Solid::Device &soliddevice, const bool added)
{
// TODO: check if the actions are for when device is added or removed
Q_UNUSED(added);
QList<KServiceAction> kserviceactions;
const QStringList solidactions = KGlobal::dirs()->findAllResources("data", "solid/actions/");
foreach (const QString &solidaction, solidactions) {
KDesktopFile kdestopfile(solidaction);
const QString solidpredicatestring = kdestopfile.desktopGroup().readEntry("X-KDE-Solid-Predicate");
KConfigGroup kconfiggroup = kdestopfile.desktopGroup();
const QStringList solidwhenlist = kconfiggroup.readEntry("X-KDE-Solid-When", QStringList());
if (!solidwhenlist.contains(added ? s_whenadd : s_whenremove)) {
continue;
}
const QString solidpredicatestring = kconfiggroup.readEntry("X-KDE-Solid-Predicate");
const Solid::Predicate solidpredicate = Solid::Predicate::fromString(solidpredicatestring);
if (solidpredicate.matches(soliddevice)) {
kserviceactions.append(KDesktopFileActions::userDefinedServices(solidaction, true));
}
}
if (kserviceactions.size() == 1) {
kExecuteAction(kserviceactions.first(), soliddevice.udi());
kExecuteAction(kserviceactions.first(), soliddevice.udi(), added);
} else if (!kserviceactions.isEmpty()) {
SolidUiDialog* soliddialog = new SolidUiDialog(soliddevice, kserviceactions);
SolidUiDialog* soliddialog = new SolidUiDialog(soliddevice, kserviceactions, added);
connect(soliddialog, SIGNAL(finished(int)), this, SLOT(slotDialogFinished()));
m_soliddialogs.append(soliddialog);
soliddialog->show();
@ -285,8 +293,7 @@ void SolidUiServer::slotDeviceRemoved(const QString &udi)
QMutableListIterator<Solid::Device> iter(m_soliddevices);
while (iter.hasNext()) {
Solid::Device soliddevice = iter.next();
// TODO: enable once add and remove are checked for, see above
// handleActions(soliddevice, false);
handleActions(soliddevice, false);
if (soliddevice.udi() == udi) {
iter.remove();
}

View file

@ -61,11 +61,11 @@ static void kSolidEjectUDI(const QString &solidudi)
}
// simplified version of KMacroExpander specialized for solid actions
static QStringList kSolidActionCommand(const QString &command, const QString &solidudi)
static QStringList kSolidActionCommand(const QString &command, const QString &solidudi, const bool mount)
{
Solid::Device soliddevice(solidudi);
Solid::StorageAccess* solidstorageacces = soliddevice.as<Solid::StorageAccess>();
if (solidstorageacces && !solidstorageacces->isAccessible()) {
if (mount && solidstorageacces && !solidstorageacces->isAccessible()) {
kSolidMountUDI(solidudi);
}
@ -97,9 +97,9 @@ static QStringList kSolidActionCommand(const QString &command, const QString &so
return KShell::splitArgs(actioncommand);
}
static void kExecuteAction(const KServiceAction &kserviceaction, const QString &solidudi)
static void kExecuteAction(const KServiceAction &kserviceaction, const QString &solidudi, const bool mount)
{
QStringList actioncommand = kSolidActionCommand(kserviceaction.exec(), solidudi);
QStringList actioncommand = kSolidActionCommand(kserviceaction.exec(), solidudi, mount);
if (actioncommand.size() == 0) {
kWarning() << "invalid action command" << kserviceaction.name();
return;