Remove the existing offline plugins documentation

This commit is contained in:
Dmitri Ovodok 2019-03-22 16:44:38 +02:00
parent 3cfde39f10
commit d601f8f0e6
7 changed files with 25 additions and 525 deletions

View file

@ -236,6 +236,7 @@ if (APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fPIC -stdlib=libc++ -Wno-inconsistent-missing-override")
# This is necessary for genManual to be executed during the build phase,
# it needs to be able to get the Qt libs.
# TODO: is it still needed? genManual is removed.
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
SET(CMAKE_INSTALL_RPATH "${QT_INSTALL_LIBS}")
else (APPLE)
@ -899,14 +900,7 @@ add_custom_target(lrelease
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
)
##
## Create and install the plugin framework manual
##
add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/plugins
COMMAND genManual ${PROJECT_SOURCE_DIR} ${PROJECT_BINARY_DIR}
DEPENDS genManual
)
add_dependencies(mscore pluginDocumentation)
##

View file

@ -10,62 +10,16 @@
# the file LICENSE.GPL
#=============================================================================
include (${PROJECT_SOURCE_DIR}/build/CopyFilesMacros.cmake)
include (${PROJECT_SOURCE_DIR}/build/functions.cmake)
include_directories(
${PROJECT_BINARY_DIR}
${PROJECT_SOURCE_DIR}
set(MANUAL_DEST "${PROJECT_BINARY_DIR}/share/manual/plugins/plugins3.html")
fn__copy_during_build(
"${CMAKE_CURRENT_SOURCE_DIR}/plugins3.html"
"${MANUAL_DEST}"
)
if (APPLE)
file(GLOB_RECURSE INCS "*.h")
else (APPLE)
set(INCS "")
endif (APPLE)
add_executable(
genManual
${INCS}
genManual.cpp
)
target_link_libraries(
genManual
${QT_LIBRARIES}
)
if(APPLE)
set_target_properties (
genManual
PROPERTIES
COMPILE_FLAGS "-include all.h -D TESTROOT=\\\\\"${PROJECT_SOURCE_DIR}\\\\\" -g -Wall -Wextra"
)
else(APPLE)
if (NOT MSVC)
set_target_properties (
genManual
PROPERTIES
COMPILE_FLAGS "-include all.h -D TESTROOT=\\\"${PROJECT_SOURCE_DIR}\\\" -g -Wall -Wextra"
)
else (NOT MSVC)
set_target_properties (
genManual
PROPERTIES
COMPILE_FLAGS "${PCH_INCLUDE} -D TESTROOT=\\\"${PROJECT_SOURCE_DIR}\\\""
)
endif (NOT MSVC)
endif(APPLE)
if(NOT MSVC)
ADD_DEPENDENCIES(genManual mops1)
endif(NOT MSVC)
add_custom_target(pluginDocumentation
ALL
DEPENDS genManual
)
add_custom_command(TARGET pluginDocumentation
POST_BUILD
COMMAND ${PROJECT_BINARY_DIR}/manual/${CMAKE_CFG_INTDIR}/genManual ${PROJECT_SOURCE_DIR} ${PROJECT_BINARY_DIR}/share/manual
DEPENDS "${MANUAL_DEST}"
)

View file

@ -1,20 +0,0 @@
This program creates the manual pages for the plugin
framework from the sources.
It reads in several header files and writes the output
to mscore/share/manual/plugins/.
Understood annotations in the source:
//@ object description
@@ ObjectName
/// object description
@P propertyName propertyType propertyDescription
//@ methodDescription
//@ ...
Q_INVOKABLE methodDeclaration

View file

@ -1,443 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2002-2011 Werner Schweer
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2
// as published by the Free Software Foundation and appearing in
// the file LICENCE.GPL
//=============================================================================
#include <stdio.h>
#include <QString>
QString srcPath;
QString dstPath;
//---------------------------------------------------------
// Prop
//---------------------------------------------------------
struct Prop {
QString name;
QString type;
QString description;
};
//---------------------------------------------------------
// Proc
//---------------------------------------------------------
struct Proc {
QString name;
QString type;
QStringList description;
};
//---------------------------------------------------------
// Class
//---------------------------------------------------------
struct Class {
QString name;
QStringList description;
QString parent;
QList<Prop> props;
QList<Proc> procs;
bool operator<(const Class& c) const {
return name < c.name;
}
};
static QList<Class> classes;
//---------------------------------------------------------
// addHeader
//---------------------------------------------------------
static void addHeader(QString& out)
{
out += "<!DOCTYPE html>\n"
"<html>\n"
"<head>\n"
" <meta charset=\"utf-8\">\n"
" </head>\n"
"<body>\n";
}
//---------------------------------------------------------
// addFooter
//---------------------------------------------------------
static void addFooter(QString& out)
{
out += /* "<div class=\"footer\"><a href=\"https://musescore.org/\">MuseScore</a> - Free music notation software<br/>\n"
"&copy; 2002-2016 Werner Schweer &amp; others</div>\n" */
"</body>\n"
"</html>\n";
}
//---------------------------------------------------------
// parseClass
//---------------------------------------------------------
static void parseClass(const QString& name, const QString& in)
{
Class cl;
cl.name = name;
QStringList sl = in.split("\n");
QStringList methodDescription;
QRegExp re("@P ([^\\s]+)\\s+([^\\s]+)(.*)");
// matches Q_INVOKABLE void mops(int a); // comment
QRegExp re1("Q_INVOKABLE +([^ ]+) +([^;]+); */*(.*)");
QRegExp re2("Q_INVOKABLE +([^ ]+) +([^\\{]+)\\{");
QRegExp re3("Q_INVOKABLE +([^ ]+) +(\\w+\\([^\\)]*\\))\\s+const\\s*([^\\{]*)\\{");
QRegExp reD("//@ (.*)");
QRegExp re4 ("class +(\\w+) *(?:final)* *: *public +(\\w+) *\\{");
QRegExp re4b("class +(\\w+) *(?:final)* *: *public +(\\w+), *public");
Q_ASSERT(re1.isValid() && re2.isValid() && re3.isValid());
bool parseClassDescription = true;
for(const QString& s : sl) {
if (re.indexIn(s, 0) != -1) { //@P
parseClassDescription = false;
Prop p;
p.name = re.cap(1);
p.type = re.cap(2);
p.description = re.cap(3);
cl.props.append(p);
}
else if (re2.indexIn(s, 0) != -1) {
parseClassDescription = false;
Proc p;
p.type = re2.cap(1);
p.name = re2.cap(2);
p.description = methodDescription;
methodDescription.clear();
cl.procs.append(p);
}
else if (re1.indexIn(s, 0) != -1) {
parseClassDescription = false;
Proc p;
p.type = re1.cap(1);
p.name = re1.cap(2);
p.description = methodDescription;
methodDescription.clear();
cl.procs.append(p);
}
else if (re3.indexIn(s, 0) != -1) {
parseClassDescription = false;
Proc p;
p.type = re3.cap(1);
p.name = re3.cap(2);
p.description = methodDescription;
methodDescription.clear();
cl.procs.append(p);
}
else if ((reD.indexIn(s, 0) != -1)) {
if (parseClassDescription)
cl.description.append(reD.cap(1));
else
methodDescription.append(reD.cap(1));
}
else if (s.startsWith("///")) {
QString ss = s.mid(3);
if (parseClassDescription)
cl.description.append(ss);
else
methodDescription.append(ss);
}
else if (re4.indexIn(s, 0) != -1) {
parseClassDescription = false;
QString parent = re4.cap(2).simplified();
if (name == re4.cap(1).simplified()) {
cl.parent = parent;
}
else {
printf("?<%s>!=<%s> derived from <%s>\n",
qPrintable(name), qPrintable(re4.cap(1).simplified()), qPrintable(parent));
}
}
else if (re4b.indexIn(s, 0) != -1) {
parseClassDescription = false;
QString parent = re4b.cap(2).simplified();
if (name == re4b.cap(1).simplified()) {
cl.parent = parent;
}
else {
printf("?<%s>!=<%s> derived from <%s>\n",
qPrintable(name), qPrintable(re4b.cap(1).simplified()), qPrintable(parent));
}
}
}
classes.append(cl);
}
//---------------------------------------------------------
// scanFile
//---------------------------------------------------------
static void scanFile(const QString& in)
{
QList<Prop> props;
QList<Proc> procs;
QRegExp re("@@ ([^\\n]*)");
int gpos = 0;
QString className;
for (;;) {
int rv = re.indexIn(in, gpos);
if (rv == -1) {
if (!className.isEmpty())
parseClass(className, in.mid(gpos, in.size() - gpos));
break;
}
int next = rv + re.matchedLength();
if (gpos)
parseClass(className, in.mid(gpos, next-gpos));
className = re.cap(1).simplified();
gpos = next;
}
}
//---------------------------------------------------------
// linkClass
//
// Given something like "array[Note]", will return "array[<a href="note.html">Note</a>]"
//---------------------------------------------------------
static QRegExp reClasses("");
static QString linkClass(const QString& in)
{
if (reClasses.pattern().isEmpty()) {
QStringList classNames;
foreach(const Class& cl, classes)
classNames.append(cl.name);
reClasses.setPattern("\\b(" + classNames.join('|') + ")\\b");
Q_ASSERT(reClasses.isValid());
}
int pos = reClasses.indexIn(in);
if (pos != -1) {
QString out(in);
out.insert(pos + reClasses.matchedLength(), "</a>");
out.insert(pos, "<a href=\"" + in.mid(pos, reClasses.matchedLength()).toLower() + ".html\">");
return out;
}
return in;
}
//---------------------------------------------------------
// writeOutput
//---------------------------------------------------------
static void writeOutput()
{
for(const Class& cl : classes) {
QString out;
addHeader(out);
out += QString("<h3>%1</h3>\n").arg(cl.name);
if (!cl.parent.isEmpty()) {
// show parent only if its part of the exported classes
for(const Class& lcl : classes) {
if (lcl.name == cl.parent) {
QString path = cl.parent.toLower();
out += QString("<div class=\"class-inherit\">inherits <a href=\"%1.html\">%2</a></div>\n").arg(path).arg(cl.parent);
break;
}
}
}
if (!cl.description.isEmpty()) {
out += "<div class=\"class-description\">\n";
for(const QString& s : cl.description) {
out += s.simplified().replace("\\brief ", "");
out += "\n";
}
out += "</div>\n";
}
else
out += "<br/>";
if (!cl.procs.isEmpty()) {
out += "<h4>Methods</h4>\n";
out += "<div class=\"methods\">\n";
for(const Proc& p : cl.procs) {
out += "<div class=\"method\">\n";
out += linkClass(p.type) + " ";
QRegExp re("([^(]+)\\(([^)]*)\\)");
if (re.indexIn(p.name, 0) != -1) {
out += QString("<b>%2</b>(%3)\n") .arg(re.cap(1)).arg(linkClass(re.cap(2)));
}
else {
out += QString("<b>%2</b>\n").arg(p.name);
}
out += "</div>\n";
if (!p.description.isEmpty()) {
out += "<div class=\"method-description\">\n";
for(const QString& s : p.description) {
out += s.simplified();
out += "<br/>\n";
}
out += "</div>\n";
}
}
out += "</div>\n";
}
if (!cl.props.isEmpty()) {
out += "<h4>Properties</h4>\n";
out += "<div class=\"properties\">\n";
out += "<table>\n";
int count = 1;
for(const Prop& m : cl.props) {
out += QString("<tr class=\"prop-%1\">") .arg( (count & 1) ? "odd" : "even");
out += QString("<td class=\"prop-name\">%1</td>"
"<td class=\"prop-type\">%2</td>"
"<td class=\"prop-desc\">%3</td>")
.arg(m.name).arg(linkClass(m.type)).arg(m.description);
out += "</tr>\n";
count++;
}
out += "</table></div>\n";
}
addFooter(out);
QString ofile = dstPath + "/plugins/" + cl.name.toLower() + ".html";
QFile of(ofile);
if (!of.open(QIODevice::WriteOnly)) {
fprintf(stderr, "open <%s> failed: %s\n", qPrintable(ofile), qPrintable(of.errorString()));
exit(-4);
}
of.write(out.toUtf8());
of.close();
}
//
// write index
//
QString out;
addHeader(out);
out += "<h2>Score Elements</h2>\n";
out += "<h3>Quick Guide</h3>\n";
out += "<p>Below are all the various classes you can use."
"<br>The main class is <a href='musescore.html'>MuseScore</a>."
"<br>Use 'New' to create a skeleton plugin."
"<br>Plugins are coded in <a href='http://doc.qt.io/qt-5/qmlapplications.html#what-is-qml'>QML</a>"
"</p>\n";
out += "<ul>\n";
qSort(classes);
for(const Class& s : classes) {
out += QString("<li><a href=\"%1\">%2</a></li>\n")
.arg(s.name.toLower() + ".html").arg(s.name);
}
out += "</ul>\n";
addFooter(out);
QString ofile = dstPath + "/plugins/plugins.html";
QFile of(ofile);
if (!of.open(QIODevice::WriteOnly)) {
fprintf(stderr, "open <%s> failed\n", qPrintable(ofile));
exit(-4);
}
of.write(out.toUtf8());
of.close();
}
//---------------------------------------------------------
// copyAssets
//---------------------------------------------------------
static void copyAssets(QString& lSrcPath, QString& lDstPath)
{
QString assetDstPath = lDstPath + "/plugins/";
QString assetSrcPath = lSrcPath + "/manual/";
// QStringList files = {"manual.css", "manual-dark.css", "mscore.png" };
QStringList files = {"mscore.png" };
// copy files from source to destination path
for (QString f : files) {
// be sure destination files do not exist
QFile dst(assetDstPath + f);
dst.remove();
if (!QFile::copy(assetSrcPath + f, assetDstPath + f))
fprintf(stderr, "Cannot copy %s to %s\n",
qPrintable(assetSrcPath + f),
qPrintable(assetDstPath + f));
}
}
//---------------------------------------------------------
// usage
//---------------------------------------------------------
static void usage(const char* program, const char* hint)
{
fprintf(stderr, "%s: %s\n", program, hint);
fprintf(stderr, "usage: %s srcPath dstPath\n", program);
}
//---------------------------------------------------------
// main
//---------------------------------------------------------
int main(int argc, char* argv[])
{
if (argc != 3) {
usage(argv[0], "bad arguments");
return -1;
}
srcPath = argv[1];
dstPath = argv[2];
QStringList files;
files << "mscore/plugin/qmlplugin.h";
files << "mscore/svggenerator.h";
QDir libdir(srcPath + "/libmscore");
QStringList filter;
filter << "*.h";
QStringList fl = libdir.entryList(filter, QDir::Files);
for(QString f : fl)
files << "libmscore/" + f;
for(const QString& s : files) {
QString infile = srcPath + "/" + s;
QFile inFile(infile);
if (!inFile.open(QIODevice::ReadOnly)) {
fprintf(stderr, "%s: cannot open input file <%s>\n",
argv[0], qPrintable(infile));
return -2;
}
//printf("ScanFile %s\n", qPrintable(infile));
QString in = inFile.readAll();
scanFile(in);
inFile.close();
}
QDir dir;
QString opath = dstPath + "/plugins";
if (!dir.mkpath(opath)) {
fprintf(stderr, "%s: cannot create destination path: <%s>\n",
argv[0], qPrintable(dstPath));
return -3;
}
writeOutput();
copyAssets(srcPath, dstPath);
return 0;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

15
manual/plugins3.html Normal file
View file

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<title>Plugins manual</title>
<meta content="">
<style></style>
</head>
<body>
See
<a href="https://musescore.org/handbook/developers-handbook/plugins-3x">
this Handbook page
</a>
to find the most recent version of documentation on plugins development.
</body>
</html>

View file

@ -119,7 +119,7 @@ PluginCreator::PluginCreator(QWidget* parent)
QString PluginCreator::manualPath()
{
QString _path = mscoreGlobalShare;
_path += "/manual/plugins/plugins.html";
_path += "/manual/plugins/plugins3.html";
return _path;
}