1
0
mirror of https://github.com/KDE/latte-dock.git synced 2025-01-01 01:17:51 +03:00

Merge branch 'v0.9'

This commit is contained in:
Michail Vourlakos 2019-07-14 14:01:13 +03:00
commit b4e747c611
14 changed files with 254 additions and 10 deletions

View File

@ -1205,6 +1205,38 @@ void GenericLayout::syncLatteViewsToScreens(Layout::ViewsMap *occupiedMap)
qDebug() << "end of, syncLatteViewsToScreens ....";
}
QList<int> GenericLayout::viewsScreens()
{
QList<int> screens;
if (isActive()) {
for (const auto containment : m_containments) {
if (m_storage->isLatteContainment(containment)) {
int screenId = -1;
//! valid screen id
if (latteViewExists(containment)) {
screenId = m_latteViews[containment]->positioner()->currentScreenId();
} else {
screenId = containment->screen();
if (screenId == -1) {
screenId = containment->lastScreen();
}
}
if (screenId!=-1 &&!screens.contains(screenId)) {
screens << screenId;
}
}
}
return screens;
} else {
return m_storage->viewsScreens();
}
}
//! STORAGE

View File

@ -130,6 +130,8 @@ public:
//! that latteView
QList<Plasma::Containment *> unassignFromLayout(Latte::View *latteView);
QList<int> viewsScreens();
public slots:
Q_INVOKABLE void addNewView();
Q_INVOKABLE int viewsWithTasks() const;

View File

@ -76,6 +76,12 @@ bool Storage::isLatteContainment(Plasma::Containment *containment) const
return false;
}
bool Storage::isLatteContainment(const KConfigGroup &group) const
{
QString pluginId = group.readEntry("plugin", "");
return pluginId == "org.kde.latte.containment";
}
void Storage::lock()
{
QFileInfo layoutFileInfo(m_layout->file());
@ -344,6 +350,27 @@ QList<Plasma::Containment *> Storage::importLayoutFile(QString file)
return importedDocks;
}
QList<int> Storage::viewsScreens()
{
QList<int> screens;
KSharedConfigPtr lFile = KSharedConfig::openConfig(m_layout->file());
KConfigGroup containmentGroups = KConfigGroup(lFile, "Containments");
for (const auto &cId : containmentGroups.groupList()) {
if (isLatteContainment(containmentGroups.group(cId))) {
int screenId = containmentGroups.group(cId).readEntry("lastScreen", -1);
if (screenId != -1 && !screens.contains(screenId)) {
screens << screenId;
}
}
}
return screens;
}
QString Storage::availableId(QStringList all, QStringList assigned, int base)
{
bool found = false;

View File

@ -42,6 +42,7 @@ public:
bool isWritable() const;
bool isLatteContainment(Plasma::Containment *containment) const;
bool isLatteContainment(const KConfigGroup &group) const;
bool layoutIsBroken() const;
void importToCorona();
@ -51,6 +52,8 @@ public:
void copyView(Plasma::Containment *containment);
void syncToLayoutFile(bool removeLayoutId);
QList<int> viewsScreens();
/// STATIC
//! Check if an applet config group is valid or belongs to removed applet
static bool appletGroupIsValid(KConfigGroup appletGroup);

View File

@ -28,6 +28,9 @@
#include <QGuiApplication>
#include <QScreen>
// KDE
#include <KLocalizedString>
// X11
#if HAVE_X11
#include <QtX11Extras/QX11Info>
@ -101,6 +104,66 @@ ScreenPool::~ScreenPool()
}
QString ScreenPool::reportHtml(const QList<int> &assignedScreens) const
{
QString report;
report += "<table cellspacing='8'>";
report += "<tr><td align='center'><b>" + i18nc("screen id","ID") + "</b></td>" +
"<td align='center'><b>" + i18nc("screen name", "Name") + "</b></td>" +
"<td align='center'><b>" + i18nc("screen type", "Type") + "</b></td>" +
"<td align='center'><b>" + i18n("Docks/Panels") + "</b></td></tr>";
report += "<tr><td colspan='4'><hr></td></tr>";
for(const QString &connector : m_connectorForId) {
int scrId = id(connector);
bool hasViews = assignedScreens.contains(scrId);
bool primary = m_primaryConnector == connector;
bool secondary = !primary && screenExists(scrId);
report += "<tr>";
//! ScreenId
QString idStr = QString::number(scrId);
if (primary || secondary) {
idStr = "<b>" + idStr +"</b>";
}
report += "<td align='center'>" + idStr + "</td>";
//! ScreenName and Primary flag
QString connectorStr = connector;
if (primary || secondary) {
connectorStr = "<b>"+ connector + "</b>";
}
report += "<td align='center'>" + connectorStr + "</td>";
//! ScreenType
QString typeStr = "";
if (primary) {
typeStr = "<b><font color='green'>[" + i18nc("primary screen","Primary") + "]</font></b>";
} else if (secondary) {
typeStr = "<b>[" + i18nc("secondary screen","Secondary") + "]</b>";
}
report += "<td align='center'>" + typeStr +"</td>";
//! Screen has not assigned any docks/panels
QString notAssignedStr = "";
if (!hasViews) {
notAssignedStr = "<font color='red'><i>[" + i18nc("it has not latte docks/panels", "none") + "]</i></font>";
}
report += "<td align='center'>" + notAssignedStr +"</td>";
report += "</tr>";
}
report += "</table>";
return report;
}
void ScreenPool::reload(QString path)
{
QFile rcfile(QString(path + "/lattedockrc"));
@ -226,12 +289,12 @@ QList <int> ScreenPool::knownIds() const
return m_connectorForId.keys();
}
bool ScreenPool::hasId(int id)
bool ScreenPool::hasId(int id) const
{
return ((id!=-1) && m_connectorForId.keys().contains(id));
}
bool ScreenPool::screenExists(int id)
bool ScreenPool::screenExists(int id) const
{
if (id != -1 && knownIds().contains(id)) {
QString scrName = connector(id);

View File

@ -43,8 +43,8 @@ public:
void load();
~ScreenPool() override;
bool hasId(int id);
bool screenExists(int id);
bool hasId(int id) const;
bool screenExists(int id) const;
int primaryScreenId() const;
QString primaryConnector() const;
@ -59,6 +59,8 @@ public:
int firstAvailableId() const;
QString reportHtml(const QList<int> &assignedScreens) const;
//all ids that are known, included screens not enabled at the moment
QList <int> knownIds() const;

View File

@ -25,6 +25,7 @@
#include "universalsettings.h"
#include "ui_settingsdialog.h"
#include "../lattecorona.h"
#include "../screenpool.h"
#include "../layout/genericlayout.h"
#include "../layout/centrallayout.h"
#include "../layout/sharedlayout.h"
@ -154,14 +155,31 @@ SettingsDialog::SettingsDialog(QWidget *parent, Latte::Corona *corona)
QMenu *fileMenu = new QMenu(i18n("File"), menuBar);
menuBar->addMenu(fileMenu);
QMenu *layoutMenu = new QMenu(i18n("Layout"), menuBar);
//rightAlignedMenuBar->addMenu(helpMenu);
menuBar->addMenu(layoutMenu);
QMenu *helpMenu = new QMenu(i18n("Help"), menuBar);
//rightAlignedMenuBar->addMenu(helpMenu);
menuBar->addMenu(helpMenu);
QAction *quitAction = fileMenu->addAction(i18n("Quit Latte"));
QAction *screensAction = fileMenu->addAction(i18n("Sc&reens..."));
screensAction->setIcon(QIcon::fromTheme("document-properties"));
screensAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_R));
QAction *quitAction = fileMenu->addAction(i18n("&Quit Latte"));
quitAction->setIcon(QIcon::fromTheme("application-exit"));
quitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q));
m_editLayoutAction = layoutMenu->addAction(i18nc("edit layout","&Edit..."));
m_editLayoutAction->setIcon(QIcon::fromTheme("document-edit"));
m_editLayoutAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_E));
m_editLayoutAction->setToolTip("You can edit layout file when layout is not active or locked");
QAction *infoLayoutAction = layoutMenu->addAction(i18nc("layout information","&Information..."));
infoLayoutAction->setIcon(QIcon::fromTheme("document-properties"));
infoLayoutAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_I));
QAction *aboutAction = helpMenu->addAction(i18n("About Latte"));
aboutAction->setIcon(QIcon::fromTheme("latte-dock"));
@ -227,6 +245,16 @@ SettingsDialog::SettingsDialog(QWidget *parent, Latte::Corona *corona)
m_corona->closeApplication();
});
connect(m_editLayoutAction, &QAction::triggered, this, [&]() {
QString file = idForRow(ui->layoutsView->currentIndex().row());
if (!file.isEmpty()) {
QProcess::startDetached("kwrite \"" + file + "\"");
}
});
connect(screensAction, &QAction::triggered, this, &SettingsDialog::showScreensInformation);
//! update all layouts view when runningActivities changed. This way we update immediately
//! the running Activities in Activities checkboxes which are shown as bold
connect(m_corona->activitiesConsumer(), &KActivities::Consumer::runningActivitiesChanged,
@ -1365,6 +1393,7 @@ void SettingsDialog::updatePerLayoutButtonsState()
QString originalName = m_layouts.contains(id) ? m_layouts[id]->name() : "";
bool lockedInModel = m_model->data(m_model->index(currentRow, NAMECOLUMN), Qt::UserRole).toBool();
bool sharedInModel = !m_model->data(m_model->index(currentRow, SHAREDCOLUMN), Qt::UserRole).toStringList().isEmpty();
bool editable = !isActive(originalName) && !lockedInModel;
//! Switch Button
if (id.startsWith("/tmp/") || originalName != nameInModel) {
@ -1413,6 +1442,12 @@ void SettingsDialog::updatePerLayoutButtonsState()
} else {
ui->sharedButton->setChecked(false);
}
if (editable) {
m_editLayoutAction->setEnabled(true);
} else {
m_editLayoutAction->setEnabled(false);
}
}
void SettingsDialog::updateSharedLayoutsStates()
@ -1519,6 +1554,34 @@ bool SettingsDialog::dataAreAccepted()
return true;
}
void SettingsDialog::showScreensInformation()
{
QList<int> assignedScreens;
for (int i = 0; i < m_model->rowCount(); ++i) {
QString id = m_model->data(m_model->index(i, IDCOLUMN), Qt::DisplayRole).toString();
QString name = m_model->data(m_model->index(i, NAMECOLUMN), Qt::DisplayRole).toString();
Layout::GenericLayout *genericActive= m_corona->layoutsManager()->synchronizer()->layout(m_layouts[id]->name());
Layout::GenericLayout *generic = genericActive ? genericActive : m_layouts[id];
QList<int> vScreens = generic->viewsScreens();
for (const int scrId : vScreens) {
if (!assignedScreens.contains(scrId)) {
assignedScreens << scrId;
}
}
}
auto msg = new QMessageBox(this);
msg->setIcon(QMessageBox::Information);
msg->setWindowTitle(i18n("Screens Information"));
msg->setText(m_corona->screenPool()->reportHtml(assignedScreens));
msg->open();
}
bool SettingsDialog::saveAllChanges()
{
if (!dataAreAccepted()) {

View File

@ -94,6 +94,7 @@ private slots:
void reject() override;
void apply();
void restoreDefaults();
void showScreensInformation();
void updatePerLayoutButtonsState();
void layoutsChanged();
@ -144,6 +145,8 @@ private:
Latte::Corona *m_corona{nullptr};
QAction *m_editLayoutAction{nullptr};
QStandardItemModel *m_model{nullptr};
Ui::SettingsDialog *ui;

View File

@ -62,6 +62,10 @@ PrimaryConfigView::PrimaryConfigView(Plasma::Containment *containment, Latte::Vi
setupWaylandIntegration();
if (KWindowSystem::isPlatformX11()) {
m_corona->wm()->registerIgnoredWindow(winId());
}
setScreen(m_latteView->screen());
if (containment) {
@ -121,6 +125,10 @@ PrimaryConfigView::~PrimaryConfigView()
{
qDebug() << "ConfigView deleting ...";
if (KWindowSystem::isPlatformX11()) {
m_corona->wm()->unregisterIgnoredWindow(winId());
}
deleteSecondaryWindow();
for (const auto &var : connections) {

View File

@ -56,6 +56,10 @@ SecondaryConfigView::SecondaryConfigView(Latte::View *view, QWindow *parent)
setupWaylandIntegration();
if (KWindowSystem::isPlatformX11()) {
m_corona->wm()->registerIgnoredWindow(winId());
}
setResizeMode(QQuickView::SizeViewToRootObject);
setScreen(m_latteView->screen());
@ -102,6 +106,10 @@ SecondaryConfigView::~SecondaryConfigView()
{
qDebug() << "SecDockConfigView deleting ...";
if (KWindowSystem::isPlatformX11()) {
m_corona->wm()->unregisterIgnoredWindow(winId());
}
for (const auto &var : connections) {
QObject::disconnect(var);
}

View File

@ -69,7 +69,7 @@ View::View(Plasma::Corona *corona, QScreen *targetScreen, bool byPassWM)
m_contextMenu(new ViewPart::ContextMenu(this)),
m_effects(new ViewPart::Effects(this)),
m_positioner(new ViewPart::Positioner(this)) //needs to be created after Effects because it catches some of its signals
{
{
setTitle(corona->kPackage().metadata().name());
setIcon(qGuiApp->windowIcon());
setResizeMode(QuickViewSharedEngine::SizeRootObjectToView);
@ -139,6 +139,10 @@ View::View(Plasma::Corona *corona, QScreen *targetScreen, bool byPassWM)
m_corona = qobject_cast<Latte::Corona *>(this->corona());
if (m_corona) {
if (KWindowSystem::isPlatformX11()) {
m_corona->wm()->registerIgnoredWindow(winId());
}
connect(m_corona, &Latte::Corona::viewLocationChanged, this, &View::dockLocationChanged);
}
}
@ -147,6 +151,10 @@ View::~View()
{
m_inDelete = true;
if (KWindowSystem::isPlatformX11()) {
m_corona->wm()->unregisterIgnoredWindow(winId());
}
//! clear Layout connections
m_visibleHackTimer1.stop();
m_visibleHackTimer2.stop();

View File

@ -96,6 +96,24 @@ Tracker::Windows *AbstractWindowInterface::windowsTracker() const
return m_windowsTracker;
}
//! Register Latte Normal Windows in order to be tracked
void AbstractWindowInterface::registerIgnoredWindow(WindowId wid)
{
if (!m_ignoredWindows.contains(wid)) {
m_ignoredWindows.append(wid);
emit windowChanged(wid);
}
}
void AbstractWindowInterface::unregisterIgnoredWindow(WindowId wid)
{
if (!m_ignoredWindows.contains(wid)) {
m_ignoredWindows.removeAll(wid);
emit windowRemoved(wid);
}
}
//! Activities switching
void AbstractWindowInterface::switchToNextActivity()
{

View File

@ -117,6 +117,9 @@ public:
QString currentDesktop() const;
QString currentActivity() const;
void registerIgnoredWindow(WindowId wid);
void unregisterIgnoredWindow(WindowId wid);
void switchToNextActivity();
void switchToPreviousActivity();
@ -139,6 +142,10 @@ protected:
QString m_currentDesktop;
QString m_currentActivity;
//! windows that must be ignored from tracking, a good example are Latte::Views and
//! their Configuration windows
QList<WindowId> m_ignoredWindows;
QPointer<KActivities::Consumer> m_activities;
//! Sending too fast plenty of signals for the same window

View File

@ -574,8 +574,8 @@ bool XWindowInterface::isValidWindow(const KWindowInfo &winfo) const
NET::WindowType winType = winfo.windowType(types);
const auto winClass = KWindowInfo(winfo.win(), 0, NET::WM2WindowClass).windowClassName();
//! ignore latte related windows from tracking
if (winClass == "latte-dock") {
//! ignored windows from tracking
if (m_ignoredWindows.contains(winfo.win())) {
return false;
}
@ -625,8 +625,8 @@ void XWindowInterface::windowChangedProxy(WId wid, NET::Properties prop1, NET::P
const auto winClass = info.windowClassName();
//! ignore latte related windows from tracking
if (winClass == "latte-dock") {
//! ignored windows do not trackd
if (m_ignoredWindows.contains(wid)) {
return;
}