on bcbc40d help sign in
unity8/plugins/WindowManager/WorkspaceModel.cpp
220 lines 6.3 kB history raw
1/*
2 * Copyright (C) 2017 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
17#include "WorkspaceModel.h"
18#include "WorkspaceManager.h"
19#include "Workspace.h"
21#include <QQmlEngine>
23Q_LOGGING_CATEGORY(WORKSPACES, "Workspaces", QtInfoMsg)
25#define DEBUG_MSG qCDebug(WORKSPACES).nospace().noquote() << __func__
26#define INFO_MSG qCInfo(WORKSPACES).nospace().noquote() << __func__
28WorkspaceModel::WorkspaceModel(QObject *parent)
29 : QAbstractListModel(parent)
33void WorkspaceModel::append(Workspace *workspace)
35 insert(m_workspaces.count(), workspace);
38void WorkspaceModel::insert(int index, Workspace *workspace)
40 beginInsertRows(QModelIndex(), index, index);
42 m_workspaces.insert(index, workspace);
44 endInsertRows();
46 Q_EMIT workspaceInserted(index, workspace);
47 Q_EMIT countChanged();
50void WorkspaceModel::remove(Workspace *workspace)
52 int index = m_workspaces.indexOf(workspace);
53 if (index < 0) return;
55 beginRemoveRows(QModelIndex(), index, index);
57 m_workspaces.removeAt(index);
59 endRemoveRows();
61 Q_EMIT workspaceRemoved(workspace);
62 Q_EMIT countChanged();
65void WorkspaceModel::move(int from, int to)
67 if (from == to) return;
68 DEBUG_MSG << " from=" << from << " to=" << to;
70 if (from >= 0 && from < m_workspaces.size() && to >= 0 && to < m_workspaces.size()) {
71 QModelIndex parent;
73 beginMoveRows(parent, from, from, parent, to + (to > from ? 1 : 0));
74#if QT_VERSION < QT_VERSION_CHECK(5, 6, 0)
75 const auto &window = m_windowModel.takeAt(from);
76 m_workspaces.insert(to, window);
77#else
78 m_workspaces.move(from, to);
79#endif
80 endMoveRows();
82 Q_EMIT workspaceMoved(from, to);
83 }
86int WorkspaceModel::indexOf(Workspace *workspace) const
88 return m_workspaces.indexOf(workspace);
91Workspace *WorkspaceModel::get(int index) const
93 if (index < 0 || index >= rowCount()) return nullptr;
94 return m_workspaces.at(index);
97int WorkspaceModel::rowCount(const QModelIndex &) const
99 return m_workspaces.count();
102QVariant WorkspaceModel::data(const QModelIndex &index, int role) const
104 if (index.row() < 0 || index.row() >= m_workspaces.size())
105 return QVariant();
107 if (role == WorkspaceRole) {
108 Workspace *workspace = m_workspaces.at(index.row());
109 return QVariant::fromValue(workspace);
110 } else {
111 return QVariant();
112 }
115void WorkspaceModel::sync(WorkspaceModel *proxy)
117 if (!proxy) return;
118 m_syncing = proxy;
119 const auto& proxyList = proxy->list();
121 // check for removals
122 int removedIndexWhichWasActive = -1;
123 QVector<Workspace*> dpCpy(this->list());
124 Q_FOREACH(auto workspace, dpCpy) {
126 bool found = false;
127 Q_FOREACH(auto p, proxyList) {
128 auto workspaceProxy = qobject_cast<WorkspaceProxy*>(p);
129 if (workspaceProxy->proxyObject() == workspace) {
130 found = true;
131 break;
132 }
133 }
134 if (!found) {
135 if (workspace->isActive()) {
136 removedIndexWhichWasActive = indexOf(workspace);
137 }
138 workspace->unassign();
139 }
140 }
142 // existing
143 QSet<Workspace*> newWorkspaces;
144 for (int i = 0; i < proxyList.count(); i++) {
145 auto workspaceProxy = qobject_cast<WorkspaceProxy*>(proxyList[i]);
146 auto workspace = workspaceProxy->proxyObject();
148 int oldIndex = this->indexOf(workspace);
150 if (oldIndex < 0) {
151 workspace->assign(this, QVariant(i));
152 } else if (oldIndex != i) {
153 this->move(oldIndex, i);
154 }
155 newWorkspaces.insert(workspace);
156 }
158 // Make sure we have at least one workspace in the model.
159 if (rowCount() == 0) {
160 Workspace* workspace = WorkspaceManager::instance()->createWorkspace();
161 workspace->assign(this);
162 (new WorkspaceProxy(workspace))->assign(proxy);
163 }
165 if (removedIndexWhichWasActive != -1) {
166 int newActiveIndex = qMin(removedIndexWhichWasActive, this->rowCount()-1);
167 Workspace* newActiveWorkspace = newActiveIndex >= 0 ? this->get(newActiveIndex) : nullptr;
169 WorkspaceManager::instance()->setActiveWorkspace(newActiveWorkspace);
170 }
171 m_syncing = nullptr;
174bool WorkspaceModel::isSyncingWith(WorkspaceModel *m)
176 return m_syncing == m;
179WorkspaceModelProxy::WorkspaceModelProxy(WorkspaceModel * const model)
180 : m_original(model)
182 Q_FOREACH(auto workspace, model->list()) {
183 auto proxy = new WorkspaceProxy(workspace);
184 QQmlEngine::setObjectOwnership(proxy, QQmlEngine::CppOwnership);
185 proxy->assign(this);
186 }
187 connect(m_original, &WorkspaceModel::workspaceInserted, this, [this](int index, Workspace* inserted) {
188 if (m_original->isSyncingWith(this)) return;
190 (new WorkspaceProxy(inserted))->assign(this, index);
191 });
192 connect(m_original, &WorkspaceModel::workspaceRemoved, this, [this](Workspace* removed) {
193 if (m_original->isSyncingWith(this)) return;
195 for (int i = 0; i < rowCount(); i++) {
196 auto workspaceProxy = qobject_cast<WorkspaceProxy*>(get(i));
197 auto w = workspaceProxy->proxyObject();
198 if (w == removed) {
199 remove(workspaceProxy);
200 break;
201 }
202 }
203 });
204 connect(m_original, &WorkspaceModel::workspaceMoved, this, [this](int from, int to) {
205 if (m_original->isSyncingWith(this)) return;
207 move(from, to);
208 });
211WorkspaceModelProxy::~WorkspaceModelProxy()
213 qDeleteAll(m_workspaces.toList()); // make a copy so the list doesnt edit itself during delete.
214 m_workspaces.clear();
217void WorkspaceModelProxy::move(int from, int to)
219 WorkspaceModel::move(from, to);