annotate installer.cpp @ 46:6dc29a50b89a

Start fancifying layout
author Chris Cannam
date Wed, 22 Jan 2020 13:54:03 +0000
parents 4aea515b404f
children c9e811d9edbe
rev   line source
Chris@33 1
Chris@33 2 #include <QApplication>
Chris@33 3 #include <QString>
Chris@33 4 #include <QFile>
Chris@33 5 #include <QDir>
Chris@33 6
Chris@42 7 #include <QDialog>
Chris@42 8 #include <QFrame>
Chris@42 9 #include <QVBoxLayout>
Chris@42 10 #include <QCheckBox>
Chris@46 11 #include <QScrollArea>
Chris@42 12 #include <QDialogButtonBox>
Chris@46 13 #include <QLabel>
Chris@42 14
Chris@41 15 #include <vamp-hostsdk/PluginHostAdapter.h>
Chris@41 16
Chris@43 17 #include <dataquay/BasicStore.h>
Chris@43 18 #include <dataquay/RDFException.h>
Chris@43 19
Chris@33 20 #include <iostream>
Chris@43 21 #include <set>
Chris@43 22
Chris@33 23 using namespace std;
Chris@43 24 using namespace Dataquay;
Chris@32 25
Chris@42 26 QString
Chris@42 27 getDefaultInstallDirectory()
Chris@32 28 {
Chris@41 29 auto pathList = Vamp::PluginHostAdapter::getPluginPath();
Chris@41 30 if (pathList.empty()) {
Chris@41 31 cerr << "Failed to look up Vamp plugin path" << endl;
Chris@42 32 return QString();
Chris@41 33 }
Chris@41 34
Chris@42 35 auto firstPath = *pathList.begin();
Chris@42 36 QString target = QString::fromUtf8(firstPath.c_str(), firstPath.size());
Chris@42 37 return target;
Chris@42 38 }
Chris@42 39
Chris@42 40 QStringList
Chris@42 41 getPluginLibraryList()
Chris@42 42 {
Chris@33 43 QDir dir(":out/");
Chris@33 44 auto entries = dir.entryList({ "*.so", "*.dll", "*.dylib" });
Chris@33 45
Chris@33 46 for (auto e: entries) {
Chris@33 47 cerr << e.toStdString() << endl;
Chris@33 48 }
Chris@33 49
Chris@42 50 return entries;
Chris@42 51 }
Chris@33 52
Chris@43 53 unique_ptr<BasicStore>
Chris@43 54 loadLibrariesRdf()
Chris@43 55 {
Chris@43 56 QDir dir(":out/");
Chris@43 57 auto entries = dir.entryList({ "*.ttl", "*.n3" });
Chris@43 58
Chris@43 59 unique_ptr<BasicStore> store(new BasicStore);
Chris@43 60
Chris@43 61 for (auto e: entries) {
Chris@43 62
Chris@43 63 QFile f(":out/" + e);
Chris@43 64 if (!f.open(QFile::ReadOnly | QFile::Text)) {
Chris@43 65 cerr << "Failed to open RDF resource file "
Chris@43 66 << e.toStdString() << endl;
Chris@43 67 continue;
Chris@43 68 }
Chris@43 69
Chris@43 70 QByteArray content = f.readAll();
Chris@43 71 f.close();
Chris@43 72
Chris@43 73 try {
Chris@43 74 store->importString(QString::fromUtf8(content),
Chris@43 75 Uri("file:" + e),
Chris@43 76 BasicStore::ImportIgnoreDuplicates);
Chris@43 77 } catch (const RDFException &ex) {
Chris@43 78 cerr << "Failed to import RDF resource file "
Chris@43 79 << e.toStdString() << ": " << ex.what() << endl;
Chris@43 80 }
Chris@43 81 }
Chris@43 82
Chris@43 83 return store;
Chris@43 84 }
Chris@43 85
Chris@43 86 struct LibraryInfo {
Chris@43 87 QString id;
Chris@43 88 QString fileName;
Chris@43 89 QString title;
Chris@43 90 QString maker;
Chris@43 91 QString description;
Chris@43 92 };
Chris@43 93
Chris@43 94 vector<LibraryInfo>
Chris@43 95 getLibraryInfo(const Store &store, QStringList libraries)
Chris@43 96 {
Chris@43 97 /* e.g.
Chris@43 98
Chris@43 99 plugbase:library a vamp:PluginLibrary ;
Chris@43 100 vamp:identifier "qm-vamp-plugins" ;
Chris@43 101 dc:title "Queen Mary plugin set"
Chris@43 102 */
Chris@43 103
Chris@43 104 Triples tt = store.match(Triple(Node(),
Chris@43 105 Uri("a"),
Chris@43 106 store.expand("vamp:PluginLibrary")));
Chris@43 107
Chris@43 108 std::map<QString, QString> wanted; // basename -> full lib name
Chris@43 109 for (auto lib: libraries) {
Chris@43 110 wanted[QFileInfo(lib).baseName()] = lib;
Chris@43 111 }
Chris@43 112
Chris@43 113 vector<LibraryInfo> results;
Chris@43 114
Chris@43 115 for (auto t: tt) {
Chris@43 116
Chris@43 117 Node libId = store.complete(Triple(t.subject(),
Chris@43 118 store.expand("vamp:identifier"),
Chris@43 119 Node()));
Chris@43 120 if (libId.type != Node::Literal) {
Chris@43 121 continue;
Chris@43 122 }
Chris@43 123 auto wi = wanted.find(libId.value);
Chris@43 124 if (wi == wanted.end()) {
Chris@43 125 continue;
Chris@43 126 }
Chris@43 127
Chris@43 128 LibraryInfo info;
Chris@43 129 info.id = wi->first;
Chris@43 130 info.fileName = wi->second;
Chris@43 131
Chris@43 132 Node title = store.complete(Triple(t.subject(),
Chris@43 133 store.expand("dc:title"),
Chris@43 134 Node()));
Chris@43 135 if (title.type == Node::Literal) {
Chris@43 136 info.title = title.value;
Chris@43 137 } else {
Chris@43 138 info.title = info.id;
Chris@43 139 }
Chris@43 140
Chris@43 141 Node maker = store.complete(Triple(t.subject(),
Chris@43 142 store.expand("foaf:maker"),
Chris@43 143 Node()));
Chris@43 144 if (maker.type == Node::Literal) {
Chris@43 145 info.maker = maker.value;
Chris@46 146 } else if (maker != Node()) {
Chris@46 147 maker = store.complete(Triple(maker,
Chris@46 148 store.expand("foaf:name"),
Chris@46 149 Node()));
Chris@46 150 if (maker.type == Node::Literal) {
Chris@46 151 info.maker = maker.value;
Chris@46 152 }
Chris@43 153 }
Chris@46 154
Chris@43 155 Node desc = store.complete(Triple(t.subject(),
Chris@43 156 store.expand("dc:description"),
Chris@43 157 Node()));
Chris@43 158 if (desc.type == Node::Literal) {
Chris@43 159 info.description = desc.value;
Chris@43 160 }
Chris@43 161
Chris@43 162 results.push_back(info);
Chris@43 163 }
Chris@43 164
Chris@43 165 return results;
Chris@43 166 }
Chris@43 167
Chris@42 168 void
Chris@42 169 installLibrary(QString library, QString target)
Chris@42 170 {
Chris@42 171 QFile f(":out/" + library);
Chris@42 172 QString destination = target + "/" + library;
Chris@42 173 cerr << "Copying " << library.toStdString() << " to "
Chris@42 174 << destination.toStdString() << "..." << endl;
Chris@42 175 if (!f.copy(destination)) {
Chris@42 176 cerr << "Failed to copy " << library.toStdString()
Chris@42 177 << " to target " << destination.toStdString() << endl;
Chris@42 178 return;
Chris@42 179 }
Chris@42 180 if (!QFile::setPermissions
Chris@42 181 (destination,
Chris@42 182 QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner |
Chris@42 183 QFile::ReadGroup | QFile::ExeGroup |
Chris@42 184 QFile::ReadOther | QFile::ExeOther)) {
Chris@42 185 cerr << "Failed to set permissions on "
Chris@42 186 << library.toStdString() << endl;
Chris@42 187 return;
Chris@42 188 }
Chris@42 189 }
Chris@42 190
Chris@42 191 QStringList
Chris@43 192 getUserApprovedPluginLibraries(vector<LibraryInfo> libraries)
Chris@42 193 {
Chris@42 194 QDialog dialog;
Chris@46 195
Chris@46 196 auto mainLayout = new QGridLayout;
Chris@46 197 dialog.setLayout(mainLayout);
Chris@46 198
Chris@46 199 int mainRow = 0;
Chris@46 200
Chris@46 201 //!!! at top: title and check/uncheck all button
Chris@46 202
Chris@46 203 auto scroll = new QScrollArea;
Chris@46 204 mainLayout->addWidget(scroll, mainRow, 0, 1, 2);
Chris@46 205 mainLayout->setRowStretch(mainRow, 10);
Chris@46 206 ++mainRow;
Chris@46 207
Chris@46 208 auto selectionFrame = new QWidget;
Chris@46 209
Chris@46 210 auto selectionLayout = new QGridLayout;
Chris@46 211 selectionFrame->setLayout(selectionLayout);
Chris@46 212 int selectionRow = 0;
Chris@42 213
Chris@43 214 map<QString, QCheckBox *> checkBoxMap;
Chris@43 215
Chris@43 216 map<QString, LibraryInfo> orderedInfo;
Chris@43 217 for (auto info: libraries) {
Chris@43 218 orderedInfo[info.title] = info;
Chris@43 219 }
Chris@42 220
Chris@43 221 for (auto ip: orderedInfo) {
Chris@46 222
Chris@46 223 auto cb = new QCheckBox;
Chris@46 224 selectionLayout->addWidget(cb, selectionRow, 0, Qt::AlignTop);
Chris@46 225
Chris@43 226 LibraryInfo info = ip.second;
Chris@46 227
Chris@46 228 QString text = QObject::tr("<b>%1</b> (%2)<br><i>%3</i>")
Chris@46 229 .arg(info.title)
Chris@46 230 .arg(info.id)
Chris@46 231 .arg(info.maker);
Chris@46 232
Chris@46 233 auto label = new QLabel(text);
Chris@46 234
Chris@46 235 selectionLayout->addWidget(label, selectionRow, 1, Qt::AlignTop);
Chris@46 236
Chris@46 237 ++selectionRow;
Chris@46 238
Chris@43 239 checkBoxMap[info.fileName] = cb;
Chris@42 240 }
Chris@42 241
Chris@46 242 scroll->setWidget(selectionFrame);
Chris@46 243
Chris@42 244 auto bb = new QDialogButtonBox(QDialogButtonBox::Ok |
Chris@42 245 QDialogButtonBox::Cancel);
Chris@46 246 mainLayout->addWidget(bb, mainRow, 0, 1, 2);
Chris@46 247 ++mainRow;
Chris@42 248 QObject::connect(bb, SIGNAL(accepted()), &dialog, SLOT(accept()));
Chris@42 249 QObject::connect(bb, SIGNAL(rejected()), &dialog, SLOT(reject()));
Chris@42 250
Chris@42 251 if (dialog.exec() == QDialog::Accepted) {
Chris@42 252 cerr << "accepted" << endl;
Chris@42 253 } else {
Chris@42 254 cerr << "rejected" << endl;
Chris@42 255 }
Chris@42 256
Chris@42 257 QStringList approved;
Chris@42 258 for (const auto &p: checkBoxMap) {
Chris@42 259 if (p.second->isChecked()) {
Chris@42 260 approved.push_back(p.first);
Chris@33 261 }
Chris@42 262 }
Chris@42 263
Chris@42 264 return approved;
Chris@42 265 }
Chris@42 266
Chris@42 267 int main(int argc, char **argv)
Chris@42 268 {
Chris@42 269 QApplication app(argc, argv);
Chris@42 270
Chris@42 271 QString target = getDefaultInstallDirectory();
Chris@42 272 if (target == "") {
Chris@42 273 return 1;
Chris@42 274 }
Chris@42 275
Chris@42 276 QStringList libraries = getPluginLibraryList();
Chris@42 277
Chris@43 278 auto rdfStore = loadLibrariesRdf();
Chris@43 279
Chris@43 280 auto info = getLibraryInfo(*rdfStore, libraries);
Chris@43 281
Chris@43 282 QStringList toInstall = getUserApprovedPluginLibraries(info);
Chris@42 283
Chris@42 284 for (auto lib: toInstall) {
Chris@42 285 installLibrary(lib, target);
Chris@33 286 }
Chris@33 287
Chris@32 288 return 0;
Chris@32 289 }