KDDockWidgets API Documentation 2.0
Loading...
Searching...
No Matches
layoutlinter_main.cpp
Go to the documentation of this file.
1/*
2 This file is part of KDDockWidgets.
3
4 SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
5 Author: SĂ©rgio Martins <sergio.martins@kdab.com>
6
7 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
8
9 Contact KDAB at <info@kdab.com> for commercial licensing options.
10*/
11
12#include "Config.h"
14
15#include "core/MainWindow.h"
16#include "core/DockWidget.h"
17#include "core/Platform.h"
18
19#include <QDebug>
20#include <QString>
21#include <QApplication>
22#include <QCommandLineParser>
23#include <QDir>
24#include <QFileInfo>
25#include <QTimer>
26
27#include "nlohmann/json.hpp"
28
29using namespace KDDockWidgets;
30using namespace KDDockWidgets::Core;
31
32static bool s_isVerbose = false;
33
34struct LinterConfig
35{
36 struct MainWindow
37 {
38 std::string name;
39 MainWindowOptions options = {};
40 bool maximize = false;
41 };
42
43 RestoreOptions restoreOptions = {};
44 std::vector<std::string> filesToLint;
45 std::vector<MainWindow> mainWindows;
46
47 bool isEmpty() const
48 {
49 return filesToLint.empty();
50 }
51};
52
53inline void from_json(const nlohmann::json &j, LinterConfig::MainWindow &mw)
54{
55 mw.name = j["name"];
56 mw.options = MainWindowOptions(j.value("options", 0));
57 mw.maximize = j.value("maximize", false);
58}
59
60inline void from_json(const nlohmann::json &j, LinterConfig &ls)
61{
62 ls.filesToLint = j.value("files", std::vector<std::string>());
63 ls.mainWindows = j.value("mainWindows", std::vector<LinterConfig::MainWindow>());
64 ls.restoreOptions = RestoreOptions(j.value("restoreOptions", int(RestoreOption::RestoreOption_None)));
65}
66
67LinterConfig requestedLinterConfig(const QCommandLineParser &parser, const QString &configFile)
68{
69 LinterConfig c;
70
71 const auto positionalArguments = parser.positionalArguments();
72 if (configFile.isEmpty() && positionalArguments.isEmpty()) {
73 qWarning() << "Expected either a config file or positional arguments";
74 return {};
75 } else if (!configFile.isEmpty() && !positionalArguments.isEmpty()) {
76 qWarning() << "Expected either a config file or positional arguments, not both";
77 return {};
78 } else if (!positionalArguments.isEmpty()) {
79 std::transform(positionalArguments.begin(), positionalArguments.end(), std::back_inserter(c.filesToLint),
80 [](const QString &str) {
81 return str.toStdString();
82 });
83 } else {
84 QFile f(configFile);
85 if (!f.open(QIODevice::ReadOnly)) {
86 qWarning() << "Failed to open" << configFile;
87 return {};
88 }
89 const QByteArray jsonData = f.readAll();
90 QDir::setCurrent(QFileInfo(configFile).path());
91 nlohmann::json j = nlohmann::json::parse(jsonData, nullptr, /*allow_exceptions=*/false);
92 from_json(j, c);
93 }
94
95 return c;
96}
97
98static bool lint(const QString &filename, LinterConfig config, bool isVerbose)
99{
100 if (isVerbose) {
101 qDebug() << "Linting" << filename << "with options" << config.restoreOptions;
102 }
103
104 DockWidgetFactoryFunc dwFunc = [](const QString &dwName) {
106 };
107
109 MainWindowFactoryFunc mwFunc = [](const QString &mwName, MainWindowOptions mainWindowOptions) {
110 return Platform::instance()->createMainWindow(mwName, {}, mainWindowOptions);
111 };
112
115
116 // Create the main windows specified from -c <file>
117 for (auto mw : config.mainWindows) {
118 const QString name = QString::fromStdString(mw.name);
119 if (isVerbose)
120 qDebug() << "Pre-creating main window" << name << "with options" << mw.options;
121
122 auto mainWindow = Platform::instance()->createMainWindow(name, {}, mw.options);
123 if (mw.maximize)
124 mainWindow->view()->showMaximized();
125 else
126 mainWindow->view()->show();
127 }
128
129 LayoutSaver restorer(config.restoreOptions);
130 return restorer.restoreFromFile(filename);
131}
132
133int main(int argc, char *argv[])
134{
135 QApplication app(argc, argv);
136
137 const auto frontends = Platform::frontendTypes();
138 if (frontends.empty()) {
139 qWarning() << "Error: Your KDDockWidgets installation doesn't support any frontend!";
140 return -1;
141 }
142
143 QCommandLineParser parser;
144 parser.setApplicationDescription("KDDockWidgets layout linter");
145 QCommandLineOption forceQtQuick = { { "q", "force-qtquick" }, "Forces usage of QtQuick" };
146 QCommandLineOption configFileOpt = { { "c", "config" }, "Linter config file", "configfile" };
147 QCommandLineOption verboseOpt = { { "v", "verbose" }, "Verbose output" };
148 QCommandLineOption strictOpt = { { "s", "strict" }, "Strict mode" };
149 QCommandLineOption waitAtEndOpt = { { "w", "wait" }, "Waits instead of exiting. For debugging purposes." };
150
151 parser.addOption(configFileOpt);
152 parser.addOption(verboseOpt);
153 parser.addOption(waitAtEndOpt);
154 parser.addOption(strictOpt);
155 parser.addPositionalArgument("layout", "layout json file");
156 parser.addHelpOption();
157
158 FrontendType frontendType = FrontendType::QtWidgets;
159
160#if defined(KDDW_FRONTEND_QTQUICK)
161#if defined(KDDW_FRONTEND_QTWIDGETS)
162 // There's both frontends, so add a switch to chose QtQuick
163 parser.addOption(forceQtQuick);
164#else
165 // There's only QtQuick
166 frontendType = FrontendType::QtQuick;
167#endif
168#endif
169
170 parser.process(*qApp);
171
172#if defined(KDDW_FRONTEND_QTQUICK) && defined(KDDW_FRONTEND_QTWIDGETS)
173 if (parser.isSet(forceQtQuick))
174 frontendType = FrontendType::QtQuick;
175#endif
176
177 KDDockWidgets::initFrontend(frontendType);
179
180 s_isVerbose = parser.isSet(verboseOpt);
181 const LinterConfig lc = requestedLinterConfig(parser, parser.isSet(configFileOpt) ? parser.value(configFileOpt) : QString());
182 if (lc.isEmpty()) {
183 qWarning() << "Bailing out";
184 return 3;
185 }
186
187 int exitCode = 0;
188 for (const std::string &layout : lc.filesToLint) {
189 if (!lint(QString::fromStdString(layout), lc, s_isVerbose))
190 exitCode = 2;
191 }
192
193 if (s_isVerbose) {
194 if (exitCode == 0) {
195 qDebug() << "Success";
196 } else {
197 qDebug() << "Error";
198 }
199 }
200
201 if (parser.isSet(waitAtEndOpt)) {
202 // For debugging inspection purposes.
203
204 QTimer::singleShot(1000, [] {
205 LayoutSaver saver;
206 const QByteArray saved = saver.serializeLayout();
207 if (s_isVerbose)
208 qDebug() << "Testing if serialize works" << !saved.isEmpty();
209 });
210
211 app.exec();
212 }
213
214 return exitCode;
215}
Application-wide config to tune certain behaviours of the framework.
void setDockWidgetFactoryFunc(DockWidgetFactoryFunc)
Registers a DockWidgetFactoryFunc.
Definition Config.cpp:135
Core::ViewFactory * viewFactory() const
getter for the framework view factory
Definition Config.cpp:162
static Config & self()
returns the singleton Config instance
Definition Config.cpp:87
void setMainWindowFactoryFunc(MainWindowFactoryFunc)
counter-part of DockWidgetFactoryFunc but for the main window. Should be rarely used....
Definition Config.cpp:145
void setLayoutSaverStrictMode(bool)
Definition Config.cpp:382
The MainWindow base-class. MainWindow and MainWindowBase are only split in two so we can share some c...
MainWindowOptions options() const
Returns the main window options that were passed via constructor.
static std::vector< KDDockWidgets::FrontendType > frontendTypes()
list the list of frontend types supported by this build
static Platform * instance()
Returns the platform singleton.
virtual View * createDockWidget(const QString &uniqueName, DockWidgetOptions options={}, LayoutSaverOptions layoutSaverOptions={}, Qt::WindowFlags windowFlags={}) const =0
Creates a dock widget. This is only used by MainWindow's persistent widget feature....
Core::DockWidget * asDockWidgetController() const
LayoutSaver allows to save or restore layouts.
Definition LayoutSaver.h:56
QByteArray serializeLayout() const
saves the layout into a byte array
bool restoreFromFile(const QString &jsonFilename)
restores the layout from a JSON file
The DockWidget controller that's shared between QtWidgets and QtQuick frontends.
The MainWindow base-class that's shared between QtWidgets and QtQuick stack.
int main(int argc, char *argv[])
LinterConfig requestedLinterConfig(const QCommandLineParser &parser, const QString &configFile)
void from_json(const nlohmann::json &j, LinterConfig::MainWindow &mw)
static bool s_isVerbose
static bool lint(const QString &filename, LinterConfig config, bool isVerbose)
Class to abstract QAction, so code still works with QtQuick and Flutter.
void DOCKS_EXPORT initFrontend(FrontendType)
Initializes the desired frontend This function should be called before using any docking....
KDDockWidgets::Core::DockWidget *(* DockWidgetFactoryFunc)(const QString &name)
Definition Config.h:35
KDDockWidgets::Core::MainWindow *(* MainWindowFactoryFunc)(const QString &name, KDDockWidgets::MainWindowOptions)
Definition Config.h:36
bool isEmpty() const const
QCommandLineOption addHelpOption()
bool addOption(const QCommandLineOption &option)
void addPositionalArgument(const QString &name, const QString &description, const QString &syntax)
bool isSet(const QString &name) const const
QStringList positionalArguments() const const
void process(const QStringList &arguments)
void setApplicationDescription(const QString &description)
QString value(const QString &optionName) const const
bool setCurrent(const QString &path)
virtual bool open(QIODevice::OpenMode mode) override
QByteArray readAll()
QString fromStdString(const std::string &str)
bool isEmpty() const const
A factory class for allowing the user to customize some internal widgets.

© Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/
KDDockWidgets
Advanced Dock Widget Framework for Qt
https://www.kdab.com/development-resources/qt-tools/kddockwidgets/
Generated by doxygen 1.9.8