move activities logic out of activity delegate

--all activities information/data for activities
and layouts are now handled properly from the
layoutsmodel in settings
pull/11/head
Michail Vourlakos 5 years ago
parent 11798211a9
commit c59dc52e1e

@ -1,5 +1,6 @@
set(lattedock-app_SRCS
${lattedock-app_SRCS}
${lattedock-app_SRCS}
${CMAKE_CURRENT_SOURCE_DIR}/activitydata.cpp
${CMAKE_CURRENT_SOURCE_DIR}/layoutdata.cpp
${CMAKE_CURRENT_SOURCE_DIR}/layoutstable.cpp
PARENT_SCOPE

@ -0,0 +1,83 @@
/*
* Copyright 2020 Michail Vourlakos <mvourlakos@gmail.com>
*
* This file is part of Latte-Dock
*
* Latte-Dock 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 2 of
* the License, or (at your option) any later version.
*
* Latte-Dock 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 this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "activitydata.h"
namespace Latte {
namespace Settings {
namespace Data {
Activity::Activity()
{
}
Activity::Activity(Activity &&o)
: id(o.id),
name(o.name),
icon(o.icon),
isCurrent(o.isCurrent),
state(o.state)
{
}
Activity::Activity(const Activity &o)
: id(o.id),
name(o.name),
icon(o.icon),
isCurrent(o.isCurrent),
state(o.state)
{
}
Activity &Activity::operator=(const Activity &rhs)
{
id = rhs.id;
name = rhs.name;
icon = rhs.icon;
isCurrent = rhs.isCurrent;
state = rhs.state;
return (*this);
}
Activity &Activity::operator=(Activity &&rhs)
{
id = rhs.id;
name = rhs.name;
icon = rhs.icon;
isCurrent = rhs.isCurrent;
state = rhs.state;
return (*this);
}
bool Activity::isValid() const
{
return (state != KActivities::Info::Invalid);
}
bool Activity::isRunning() const
{
return ((state == KActivities::Info::Running) || (state == KActivities::Info::Starting));
}
}
}
}

@ -0,0 +1,69 @@
/*
* Copyright 2020 Michail Vourlakos <mvourlakos@gmail.com>
*
* This file is part of Latte-Dock
*
* Latte-Dock 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 2 of
* the License, or (at your option) any later version.
*
* Latte-Dock 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 this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef SETTINGSDATAACTIVITY_H
#define SETTINGSDATAACTIVITY_H
//! Qt
#include <QMetaType>
#include <QIcon>
#include <QString>
//! KActivities
#include <KActivities/Info>
namespace Latte {
namespace Settings {
namespace Data {
class Activity
{
public:
Activity();
Activity(Activity &&o);
Activity(const Activity &o);
//! Layout data
QString id;
QString name;
QString icon;
bool isCurrent;
KActivities::Info::State state;
bool isValid() const;
bool isRunning() const;
//! Operators
Activity &operator=(const Activity &rhs);
Activity &operator=(Activity &&rhs);
};
//! This is an Activities map in the following structure:
//! #activityId -> activite_information
typedef QHash<const QString, Activity> ActivitiesMap;
}
}
}
Q_DECLARE_METATYPE(Latte::Settings::Data::Activity)
Q_DECLARE_METATYPE(Latte::Settings::Data::ActivitiesMap)
#endif

@ -21,6 +21,7 @@
// local
#include "persistentmenu.h"
#include "../data/activitydata.h"
#include "../data/layoutdata.h"
#include "../models/layoutsmodel.h"
#include "../tools/settingstools.h"
@ -36,9 +37,6 @@
#include <QString>
#include <QTextDocument>
// KDE
#include <KActivities/Info>
#include <KLocalizedString>
namespace Latte {
namespace Settings {
@ -50,16 +48,6 @@ Activities::Activities(QObject *parent)
{
}
QString Activities::freeActivities_text() const
{
return QString("[ " + i18n("All Free Activities...") + " ]");
}
QString Activities::freeActivities_icon() const
{
return "favorites";
}
QWidget *Activities::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QPushButton *button = new QPushButton(parent);
@ -69,31 +57,39 @@ QWidget *Activities::createEditor(QWidget *parent, const QStyleOptionViewItem &o
menu->setMinimumWidth(option.rect.width());
bool isLayoutActive = index.data(Model::Layouts::LAYOUTISACTIVEROLE).toBool();
QStringList allActivities = index.data(Model::Layouts::ALLACTIVITIESROLE).toStringList();
QStringList allActivities = index.data(Model::Layouts::ALLACTIVITIESSORTEDROLE).toStringList();
Data::ActivitiesMap allActivitiesData = index.data(Model::Layouts::ALLACTIVITIESDATAROLE).value<Data::ActivitiesMap>();
QStringList assignedActivities = index.data(Qt::UserRole).toStringList();
for (int i = 0; i < allActivities.count(); ++i) {
if (allActivities[i] == Data::Layout::FREEACTIVITIESID) {
bool isFreeActivitiesChecked = assignedActivities.contains(Data::Layout::FREEACTIVITIESID);
Data::Activity activitydata = allActivitiesData[allActivities[i]];
if (!activitydata.isValid()) {
continue;
}
QAction *action = new QAction(freeActivities_text());
action->setData(Data::Layout::FREEACTIVITIESID);
action->setIcon(QIcon::fromTheme(freeActivities_icon()));
action->setCheckable(true);
action->setChecked(isFreeActivitiesChecked);
bool ischecked = assignedActivities.contains(activitydata.id);
QAction *action = new QAction(activitydata.name);
action->setData(activitydata.id);
action->setIcon(QIcon::fromTheme(activitydata.icon));
action->setCheckable(true);
action->setChecked(ischecked);
if (activitydata.id == Data::Layout::FREEACTIVITIESID) {
if (isLayoutActive) {
QFont font = action->font();
font.setBold(true);
action->setFont(font);
}
menu->addAction(action);
if (isFreeActivitiesChecked) {
if (ischecked) {
menu->setMasterIndex(i);
}
connect(action, &QAction::toggled, this, [this, menu, button, action, i]() {
connect(action, &QAction::toggled, this, [this, menu, button, action, i, allActivitiesData]() {
if (action->isChecked()) {
menu->setMasterIndex(i);
} else {
@ -102,38 +98,28 @@ QWidget *Activities::createEditor(QWidget *parent, const QStyleOptionViewItem &o
}
}
updateButton(button);
updateButton(button, allActivitiesData);
});
} else {
KActivities::Info info(allActivities[i]);
if (info.state() != KActivities::Info::Invalid) {
QAction *action = new QAction(info.name());
action->setData(allActivities[i]);
action->setIcon(QIcon::fromTheme(info.icon()));
action->setCheckable(true);
action->setChecked(assignedActivities.contains(allActivities[i]));
if ((info.state() == KActivities::Info::Running) || (info.state() == KActivities::Info::Starting)) {
QFont font = action->font();
font.setBold(true);
action->setFont(font);
}
menu->addAction(action);
if (activitydata.isRunning()) {
QFont font = action->font();
font.setBold(true);
action->setFont(font);
}
connect(action, &QAction::toggled, this, [this, menu, button, action, i]() {
if (action->isChecked()) {
menu->setMasterIndex(-1);
}
connect(action, &QAction::toggled, this, [this, menu, button, action, i, allActivitiesData]() {
if (action->isChecked()) {
menu->setMasterIndex(-1);
}
updateButton(button);
});
}
updateButton(button, allActivitiesData);
});
}
menu->addAction(action);
}
connect(menu, &PersistentMenu::masterIndexChanged, this, [this, menu, button]() {
connect(menu, &PersistentMenu::masterIndexChanged, this, [this, menu, button, allActivitiesData]() {
int masterRow = menu->masterIndex();
if (masterRow>=0) {
auto actions = button->menu()->actions();
@ -152,7 +138,7 @@ QWidget *Activities::createEditor(QWidget *parent, const QStyleOptionViewItem &o
}
}
updateButton(button);
updateButton(button, allActivitiesData);
});
return button;
@ -160,7 +146,9 @@ QWidget *Activities::createEditor(QWidget *parent, const QStyleOptionViewItem &o
void Activities::setEditorData(QWidget *editor, const QModelIndex &index) const
{
updateButton(editor);
Data::ActivitiesMap allActivitiesData = index.data(Model::Layouts::ALLACTIVITIESDATAROLE).value<Data::ActivitiesMap>();
updateButton(editor, allActivitiesData);
}
void Activities::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
@ -183,7 +171,7 @@ void Activities::updateEditorGeometry(QWidget *editor, const QStyleOptionViewIte
}
bool Activities::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option,
const QModelIndex &index)
const QModelIndex &index)
{
Q_ASSERT(event);
Q_ASSERT(model);
@ -209,7 +197,14 @@ void Activities::paint(QPainter *painter, const QStyleOptionViewItem &option, co
if (!isSharedCapable) {
painter->save();
QStringList assignedActivities = index.model()->data(index, Qt::UserRole).toStringList();
QList<Data::Activity> assignedActivities;
QStringList assignedIds = index.model()->data(index, Qt::UserRole).toStringList();
Data::ActivitiesMap allActivitiesData = index.data(Model::Layouts::ALLACTIVITIESDATAROLE).value<Data::ActivitiesMap>();
for (int i=0; i<assignedIds.count(); ++i) {
assignedActivities << allActivitiesData[assignedIds[i]];
}
if (assignedActivities.count() > 0) {
myOptions.text = joinedActivities(assignedActivities, isLayoutActive);
@ -299,42 +294,33 @@ void Activities::paint(QPainter *painter, const QStyleOptionViewItem &option, co
}
}
QString Activities::joinedActivities(const QStringList &activities, bool isActive, bool formatText) const
QString Activities::joinedActivities(const QList<Data::Activity> &activities, bool isActive, bool formatText) const
{
QString finalText;
int i = 0;
for (const auto &activityId : activities) {
QString name;
for (int i=0; i<activities.count(); ++i) {
bool bold{false};
bool italic{false};
if (activityId == Data::Layout::FREEACTIVITIESID) {
name = freeActivities_text();
if (activities[i].id == Data::Layout::FREEACTIVITIESID) {
if (formatText) {
bold = isActive;
italic = !isActive;
}
} else {
KActivities::Info info(activityId);
if (info.state() != KActivities::Info::Invalid) {
if (i > 0) {
finalText += ", ";
}
i++;
if (formatText && ((info.state() == KActivities::Info::Running) || (info.state() == KActivities::Info::Starting))) {
bold = true;
}
name = info.name();
if (formatText && activities[i].isRunning()) {
bold = true;
}
}
QString styledText = name;
if (i > 0) {
finalText += ", ";
}
QString styledText = activities[i].name;
if (bold && formatText) {
styledText = "<b>" + styledText + "</b>";
@ -350,17 +336,18 @@ QString Activities::joinedActivities(const QStringList &activities, bool isActiv
return finalText;
}
void Activities::updateButton(QWidget *editor) const
void Activities::updateButton(QWidget *editor, const Data::ActivitiesMap &allActivitiesData) const
{
if (!editor) {
return;
}
QPushButton *button = static_cast<QPushButton *>(editor);
QStringList assignedActivities;
QList<Data::Activity> assignedActivities;
foreach (QAction *action, button->menu()->actions()) {
if (action->isChecked()) {
assignedActivities << action->data().toString();
assignedActivities << allActivitiesData[action->data().toString()];
}
}

@ -20,6 +20,9 @@
#ifndef ACTIVITIESDELEGATE_H
#define ACTIVITIESDELEGATE_H
// local
#include "../data/activitydata.h"
// Qt
#include <QItemDelegate>
@ -46,12 +49,9 @@ public:
virtual bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override;
private:
void updateButton(QWidget *editor) const;
QString freeActivities_text() const;
QString freeActivities_icon() const;
void updateButton(QWidget *editor, const Data::ActivitiesMap &allActivitiesData) const;
QString joinedActivities(const QStringList &activities, bool isActive = false, bool formatText = true) const;
QString joinedActivities(const QList<Data::Activity> &activities, bool isActive = false, bool formatText = true) const;
};
}

@ -33,6 +33,10 @@
// KDE
#include <KLocalizedString>
// KActivities
#include <KActivities/Consumer>
#include <KActivities/Info>
const QChar CheckMark{0x2714};
namespace Latte {
@ -43,6 +47,8 @@ Layouts::Layouts(QObject *parent, Latte::Corona *corona)
: QAbstractTableModel(parent),
m_corona(corona)
{
initActivities();
connect(this, &Layouts::inMultipleModeChanged, this, [&]() {
QVector<int> roles;
roles << Qt::DisplayRole;
@ -57,6 +63,11 @@ Layouts::Layouts(QObject *parent, Latte::Corona *corona)
connect(m_corona->layoutsManager(), &Latte::Layouts::Manager::centralLayoutsChanged, this, &Layouts::updateActiveStates);
}
Layouts::~Layouts()
{
qDeleteAll(m_activitiesInfo);
}
bool Layouts::containsCurrentName(const QString &name) const
{
return m_layoutsTable.containsCurrentName(name);
@ -324,11 +335,15 @@ QVariant Layouts::data(const QModelIndex &index, int role) const
return inMultipleMode();
} else if (role == LAYOUTNAMEWASEDITEDROLE) {
return m_layoutsTable[row].nameWasEdited();
} else if (role == ALLACTIVITIESROLE) {
} else if (role == ALLACTIVITIESSORTEDROLE) {
QStringList activities;
activities << QString(Data::Layout::FREEACTIVITIESID);
activities << m_corona->layoutsManager()->synchronizer()->activities();
return activities;
} else if (role == ALLACTIVITIESDATAROLE) {
QVariant activitiesData;
activitiesData.setValue(m_activitiesMap);
return activitiesData;
} else if (role == ALLLAYOUTSROLE) {
QVariant layouts;
layouts.setValue(m_layoutsTable);
@ -681,6 +696,107 @@ void Layouts::setCurrentData(Data::LayoutsTable &data)
emit rowsInserted();
}
//! Activities code
void Layouts::initActivities()
{
Data::Activity freeActivities;
freeActivities.id = Data::Layout::FREEACTIVITIESID;
freeActivities.name = QString("[ " + i18n("All Free Activities...") + " ]");
freeActivities.icon = "favorites";
freeActivities.state = KActivities::Info::Stopped;
m_activitiesMap[Data::Layout::FREEACTIVITIESID] = freeActivities;
QStringList activities = m_corona->layoutsManager()->synchronizer()->activities();;
for(const auto &id: activities) {
KActivities::Info info(id);
if (info.state() != KActivities::Info::Invalid) {
on_activityAdded(id);
}
}
connect(m_corona->activitiesConsumer(), &KActivities::Consumer::activityAdded, this, &Layouts::on_activityAdded);
connect(m_corona->activitiesConsumer(), &KActivities::Consumer::activityRemoved, this, &Layouts::on_activityRemoved);
connect(m_corona->activitiesConsumer(), &KActivities::Consumer::runningActivitiesChanged, this, &Layouts::on_runningActivitiesChanged);
activitiesStatesChanged();
}
void Layouts::activitiesStatesChanged()
{
QVector<int> roles;
roles << Qt::DisplayRole;
roles << Qt::UserRole;
roles << ALLACTIVITIESDATAROLE;
roles << ALLACTIVITIESSORTEDROLE;
emit dataChanged(index(0, BACKGROUNDCOLUMN), index(rowCount()-1, BACKGROUNDCOLUMN), roles);
emit dataChanged(index(0, ACTIVITYCOLUMN), index(rowCount()-1, ACTIVITYCOLUMN), roles);
}
void Layouts::on_activityAdded(const QString &id)
{
m_activitiesInfo[id] = new KActivities::Info(id, this);
Data::Activity activity;
activity.id = m_activitiesInfo[id]->id();
activity.name = m_activitiesInfo[id]->name();
activity.icon = m_activitiesInfo[id]->icon();
activity.state = m_activitiesInfo[id]->state();
m_activitiesMap[id] = activity;
connect(m_activitiesInfo[id], &KActivities::Info::nameChanged, [this, id]() {
on_activityChanged(id);
});
connect(m_activitiesInfo[id], &KActivities::Info::iconChanged, [this, id]() {
on_activityChanged(id);
});
}
void Layouts::on_activityRemoved(const QString &id)
{
if (m_activitiesMap.contains(id)) {
m_activitiesMap.remove(id);
}
if (m_activitiesInfo.contains(id)) {
KActivities::Info *info = m_activitiesInfo.take(id);
info->deleteLater();
}
activitiesStatesChanged();
}
void Layouts::on_activityChanged(const QString &id)
{
if (m_activitiesMap.contains(id) && m_activitiesInfo.contains(id)) {
m_activitiesMap[id].name = m_activitiesInfo[id]->name();
m_activitiesMap[id].icon = m_activitiesInfo[id]->icon();
m_activitiesMap[id].state = m_activitiesInfo[id]->state();
activitiesStatesChanged();
}
}
void Layouts::on_runningActivitiesChanged(const QStringList &runningIds)
{
Data::ActivitiesMap::iterator i;
for (i = m_activitiesMap.begin(); i != m_activitiesMap.end(); ++i){
if (runningIds.contains(i.key())) {
m_activitiesMap[i.key()].state = KActivities::Info::Running;
} else {
m_activitiesMap[i.key()].state = KActivities::Info::Stopped;
}
}
activitiesStatesChanged();
}
}
}
}

@ -22,6 +22,7 @@
#define SETTINGSLAYOUTSMODEL_H
// local
#include "../data/activitydata.h"
#include "../data/layoutdata.h"
#include "../data/layoutstable.h"
#include "../../lattecorona.h"
@ -59,12 +60,13 @@ public:
LAYOUTISSHAREDROLE,
LAYOUTNAMEWASEDITEDROLE,
INMULTIPLELAYOUTSROLE,
ALLACTIVITIESROLE,
RUNNINGACTIVITIESROLE,
ALLACTIVITIESSORTEDROLE,
ALLACTIVITIESDATAROLE,
ALLLAYOUTSROLE
};
explicit Layouts(QObject *parent, Latte::Corona *corona);
~Layouts();
bool containsCurrentName(const QString &name) const;
@ -110,7 +112,15 @@ signals:
private slots:
void updateActiveStates();
void activitiesStatesChanged();
void on_activityAdded(const QString &id);
void on_activityRemoved(const QString &id);
void on_activityChanged(const QString &id);
void on_runningActivitiesChanged(const QStringList &runningIds);
private:
void initActivities();
void autoAssignFreeActivitiesLayout();
void setActivities(const int &row, const QStringList &activities);
void setId(const int &row, const QString &newId);
@ -122,6 +132,9 @@ private:
bool m_inMultipleMode{false};
Data::LayoutsTable m_layoutsTable;
Data::ActivitiesMap m_activitiesMap;
QHash<QString, KActivities::Info *> m_activitiesInfo;
Latte::Corona *m_corona{nullptr};
};

Loading…
Cancel
Save