QtCanpool 3.3.0
载入中...
搜索中...
未找到
dockgroupmanager.cpp
浏览该文件的文档.
1
5#include "dockgroupmanager.h"
7#include "dockgroup.h"
8#include "docksubwindow.h"
9
10#include <QAction>
11#include <QMenu>
12#include <QInputDialog>
13#include <QMessageBox>
14#include <QFile>
15#include <QDir>
16#include <QSettings>
17
18#define GROUP_PREFIX QString("Group")
19
21
22// Partially bypass QxDock perspective management, store list here
23// and then QxDock will only have one perspective loaded
24// this is because all docking widgets must exist when a perspective is loaded
25// we will guarantee that!
26class PerspectiveInfo
27{
28public:
29 std::shared_ptr<QSettings> settings;
30 QMap<QString, QStringList> groups;
31};
32
33class DockGroupManagerPrivate
34{
35public:
36 QX_DECLARE_PUBLIC(DockGroupManager)
37public:
38 DockGroupManagerPrivate();
39public:
40 QMap<QString, PerspectiveInfo> m_perspectives;
41 QString m_perspectivesFolder;
42};
43
44DockGroupManagerPrivate::DockGroupManagerPrivate()
45{
46}
47
48DockGroupManager::DockGroupManager(const QString &perspectivesFolder)
49{
52 d->m_perspectivesFolder = perspectivesFolder;
53}
54
55DockGroupManager::~DockGroupManager()
56{
58 // remove temp files:
59 for (auto perspective : d->m_perspectives) {
60 QString fileName = perspective.settings->fileName();
61 perspective.settings.reset();
62 QFile::remove(fileName);
63 }
65}
66
67QStringList DockGroupManager::perspectiveNames() const
68{
69 Q_D(const DockGroupManager);
70 return d->m_perspectives.keys();
71}
72
73void DockGroupManager::addPerspective(const QString &name, DockGroup *group)
74{
76 if (!d->m_perspectivesFolder.isEmpty()) {
77 d->m_perspectives[name].settings = getSettingsObject(getSettingsFileName(name, true));
78 d->m_perspectives[name].groups = group->subWindow()->getGroupContents();
79
80 // save perspective internally
82 // store it in QSettings object
83 group->subWindow()->savePerspectivesRec(*(d->m_perspectives[name].settings));
84 // remove internal perspectives
86 } else {
87 assert(false);
88 }
89
90 Q_EMIT perspectivesListChanged();
91}
92
93DockWidget *findWidget(QString name, const std::vector<DockSubWindow *> &sws)
94{
95 for (auto sw : sws) {
96 auto widget = sw->findDockWidget(name);
97 if (widget)
98 return widget;
99 }
100 return NULL;
101}
102
103void DockGroupManager::openPerspective(const QString &name, DockGroup *group)
104{
105 Q_D(DockGroupManager);
106 assert(group->topLevelGroup() == group);
107
108 if (!d->m_perspectivesFolder.isEmpty()) {
109 if (d->m_perspectives.contains(name)) {
110 Q_EMIT openingPerspective();
111
112 if (group->canCreateNewGroups()) {
113 auto sws = group->subWindow()->allSubWindows(true, true);
114 for (auto grpName : d->m_perspectives[name].groups.keys()) {
115 bool found = false;
116 for (auto sw : sws) {
117 if (sw->getPersistGroupName() == grpName) {
118 found = true;
119 break;
120 }
121 }
122 if (!found) {
123 grpName = DockSubWindow::getGroupNameFromPersistGroupName(grpName);
124
125 // restore group in file but not in GUI yet
126 DockPanel *insertPos = nullptr;
127 group->createGroup(grpName, insertPos);
128 }
129 }
130
131 sws = group->subWindow()->allSubWindows(false, true);
132 for (auto sw : sws) {
133 if (!d->m_perspectives[name].groups.keys().contains(sw->getPersistGroupName())) {
134 group->destroyGroup(sw->group());
135 }
136 }
137 }
138
139 auto sws = group->subWindow()->allSubWindows(true, true);
140 for (auto grpName : d->m_perspectives[name].groups.keys()) {
141 for (auto sw : sws) {
142 if (sw->getPersistGroupName() == grpName) {
143 for (QString widgetName : d->m_perspectives[name].groups[grpName]) {
144 DockWidget *dw = findWidget(widgetName, {sw});
145 if (dw) {
146 // OK, widget is already in the good manager!
147 } else {
148 dw = findWidget(widgetName, sws);
149 if (dw) {
150 // move dock widget in the same group as it used to be when perspective was saved
151 // this guarantee load/open perspectives will work smartly
152 MoveDockWidgetAction::move(dw, sw);
153 }
154 }
155 }
156 }
157 }
158 }
159
160 // internally load perspectives from QSettings
161 group->subWindow()->loadPerspectivesRec(*(d->m_perspectives[name].settings));
162 // load perspective (update GUI)
164 // remove internal perspectives
166
167 Q_EMIT openedPerspective();
168 }
169 } else {
170 assert(false);
171 }
172}
173
174void DockGroupManager::removePerspectives()
175{
176 Q_D(DockGroupManager);
177 d->m_perspectives.clear();
178 Q_EMIT perspectivesListChanged();
179}
180
181void DockGroupManager::removePerspective(const QString &name)
182{
183 Q_D(DockGroupManager);
184 d->m_perspectives.remove(name);
185 Q_EMIT perspectivesListChanged();
186}
187
188void DockGroupManager::loadPerspectives()
189{
190 Q_D(DockGroupManager);
191 if (!d->m_perspectivesFolder.isEmpty()) {
192 QDir().mkpath(d->m_perspectivesFolder);
193
194 d->m_perspectives.clear();
195
196 auto mainSettings = getSettingsObject(getSettingsFileName("", false));
197 std::string debug = mainSettings->fileName().toStdString();
198
199 int Size = mainSettings->beginReadArray("Perspectives");
200
201 for (int i = 0; i < Size; ++i) {
202 mainSettings->setArrayIndex(i);
203 QString perspective = mainSettings->value("Name").toString();
204
205 if (!perspective.isEmpty()) {
206 // load perspective file:
207 auto toLoad = getSettingsFileName(perspective, false);
208 auto loaded = getSettingsFileName(perspective, true);
209
210#ifdef _DEBUG
211 std::string debug1 = loaded.toStdString();
212 std::string debug2 = toLoad.toStdString();
213#endif
214
215 QFile::remove(loaded);
216 if (!QFile::copy(toLoad, loaded))
217 assert(false);
218
219 d->m_perspectives[perspective].settings = getSettingsObject(loaded);
220
221 // load group info:
222 mainSettings->beginGroup(GROUP_PREFIX);
223 for (const auto &key : mainSettings->allKeys()) {
224 d->m_perspectives[perspective].groups[key] = mainSettings->value(key).toStringList();
225 }
226 mainSettings->endGroup();
227 } else {
228 assert(false);
229 }
230 }
231
232 mainSettings->endArray();
233 }
234
235 Q_EMIT perspectivesListChanged();
236}
237
238void DockGroupManager::savePerspectives() const
239{
240 Q_D(const DockGroupManager);
241 if (!d->m_perspectivesFolder.isEmpty()) {
242 auto mainSettings = getSettingsObject(getSettingsFileName("", false));
243
244 // Save list of perspective and group organization
245 mainSettings->beginWriteArray("Perspectives", d->m_perspectives.size());
246 int i = 0;
247 for (auto perspective : d->m_perspectives.keys()) {
248 mainSettings->setArrayIndex(i);
249 mainSettings->setValue("Name", perspective);
250 mainSettings->beginGroup(GROUP_PREFIX);
251 for (auto group : d->m_perspectives[perspective].groups.keys()) {
252 mainSettings->setValue(group, d->m_perspectives[perspective].groups[group]);
253 }
254 mainSettings->endGroup();
255 ++i;
256 }
257 mainSettings->endArray();
258
259 // Save perspectives themselves
260 for (auto perspectiveName : d->m_perspectives.keys()) {
261 auto toSave = getSettingsFileName(perspectiveName, false);
262 QSettings &settings = *(d->m_perspectives[perspectiveName].settings);
263 settings.sync();
264
265#ifdef _DEBUG
266 std::string debug1 = settings.fileName().toStdString();
267 std::string debug2 = toSave.toStdString();
268#endif
269
270 QFile::remove(toSave);
271 if (!QFile::copy(settings.fileName(), toSave))
272 assert(false);
273 }
274 }
275}
276
277QString DockGroupManager::getSettingsFileName(const QString &perspective, bool temp) const
278{
279 Q_D(const DockGroupManager);
280 auto name = (perspective.isEmpty()) ? QStringLiteral("perspectives.ini")
281 : QStringLiteral("perspective_") + perspective + (temp ? ".tmp" : ".ini");
282
283 return d->m_perspectivesFolder + "/" + name;
284}
285
286std::shared_ptr<QSettings> DockGroupManager::getSettingsObject(const QString &filePath) const
287{
288 return std::make_shared<QSettings>(filePath, QSettings::IniFormat);
289}
290
291// CreateChildDockAction
292CreateChildDockAction::CreateChildDockAction(DockGroup *group, QMenu *menu)
293 : QAction(tr("New group..."), menu)
294 , m_group(group)
295{
296 connect(this, SIGNAL(triggered()), this, SLOT(createGroup()));
297}
298
300{
301 QString name = "";
302 while (true) {
303 bool ok = false;
304 name = QInputDialog::getText(NULL, this->text(), tr("Enter group name"), QLineEdit::Normal, name, &ok);
305 if (ok) {
306 QString error = "";
307 if (m_group->topLevelGroup())
308 error = m_group->topLevelGroup()->getGroupNameError(name);
309 else
310 assert(false);
311
312 if (error.isEmpty()) {
313 DockPanel *insertPos = NULL;
314 m_group->createGroup(name, insertPos);
315 break;
316 } else {
317 QMessageBox::critical(NULL, "Error", error);
318 continue;
319 }
320 } else {
321 break;
322 }
323 }
324}
325
326// DestroyGroupAction
328 : QAction(tr("Destroy ") + group->subWindow()->getGroupName(), menu)
329 , m_group(group)
330{
331 connect(this, SIGNAL(triggered()), this, SLOT(destroyGroup()));
332}
333
335{
336 m_group->topLevelGroup()->destroyGroup(m_group);
337}
338
339// MoveDockWidgetAction
341 : QAction(menu)
342 , m_widget(widget)
343 , m_moveTo(moveTo)
344{
345 if (moveTo->group()->isTopLevel()) {
346 setText(tr("To top"));
347 } else {
348 setText(tr("To ") + moveTo->group()->objectName());
349 }
350 connect(this, SIGNAL(triggered()), this, SLOT(move()));
351}
352
354{
355 move(m_widget, m_moveTo);
356}
357
359{
360 if (widget && moveTo) {
361 widget->dockWindow()->removeDockWidget(widget);
363 } else {
364 assert(false);
365 }
366}
367
368// LoadPerspectiveAction
369LoadPerspectiveAction::LoadPerspectiveAction(QMenu *parent, const QString &name, DockGroup *group)
370 : QAction(name, parent)
371 , name(name)
372 , m_group(group)
373{
374 connect(this, SIGNAL(triggered()), this, SLOT(load()));
375}
376
378{
379 m_group->groupManager()->openPerspective(name, m_group);
380}
381
382// RemovePerspectiveAction
384 : QAction(name, parent)
385 , name(name)
386 , m_group(group)
387{
388 connect(this, SIGNAL(triggered()), this, SLOT(remove()));
389}
390
392{
393 m_group->groupManager()->removePerspective(name);
394}
395
DestroyGroupAction(DockGroup *group, QMenu *menu)
void removePerspective(const QString &name)
void openPerspective(const QString &name, DockGroup *group)
bool canCreateNewGroups() const
void destroyGroup(DockGroup *group)
DockGroup * topLevelGroup() const
DockGroupManager * groupManager() const
DockSubWindow * subWindow() const
QString getGroupNameError(const QString &groupName)
DockGroup * createGroup(const QString &groupName, DockPanel *insertPos)
Definition dockgroup.cpp:88
DockPanel manages multiple instances of DockWidgets.
Definition dockpanel.h:31
void openPerspectiveRec(const QString &name)
QMap< QString, QStringList > getGroupContents()
void savePerspectivesRec(QSettings &Settings) const
DockPanel * getInsertDefaultPos()
void loadPerspectivesRec(QSettings &Settings)
std::vector< DockSubWindow * > allSubWindows(bool includeThis, bool rec) const
void addPerspectiveRec(const QString &name)
The DockWidget class provides a widget that can be docked inside a DockWindow or floated as a top-lev...
Definition dockwidget.h:31
DockWindow * dockWindow() const
Returns the dock window that manages the dock widget or 0 if the widget has not been assigned to any ...
void removePerspectives(const QStringList &names)
void removeDockWidget(DockWidget *w)
QStringList perspectiveNames() const
DockPanel * addDockWidget(Qx::DockWidgetArea area, DockWidget *w, DockPanel *p=nullptr, int index=-1)
Adds dockwidget into the given area.
LoadPerspectiveAction(QMenu *parent, const QString &name, DockGroup *group)
MoveDockWidgetAction(DockWidget *widget, DockSubWindow *moveTo, QMenu *menu)
RemovePerspectiveAction(QMenu *parent, const QString &name, DockGroup *group)
#define GROUP_PREFIX
Copyleft (C) 2024 maminjie canpool@163.com SPDX-License-Identifier: MulanPSL-2.0
DockWidget * findWidget(QString name, const std::vector< DockSubWindow * > &sws)
@ CenterDockWidgetArea
#define QX_INIT_PRIVATE(Class)
#define QX_DECLARE_PUBLIC(Class)
#define QX_FINI_PRIVATE()
#define QX_DOCK_END_NAMESPACE
#define QX_DOCK_BEGIN_NAMESPACE
const char * fileName
Definition qxtheme.cpp:26
const char * name
Definition qxtheme.cpp:25
QColor text