void SearchTab::searchButtonClicked() { QString search = ui->searchQuery->text(); if (search.isEmpty()) return; SqlUtilities::clearSearch(); ui->searchWidget->hide(); ui->searchSpinnerWidget->show(); pSpinnerMovie->start(); mSearchCount = 0; int index = ui->trackerCombo->currentIndex(); QString selected = ui->trackerCombo->currentText(); QSettings settings("Entomologist"); settings.setValue("last-search-query", search); QMapIterator<QString, Backend*> i(mIdMap); while (i.hasNext()) { i.next(); Backend *b = i.value(); if ((index == 0) || (b->name() == selected)) { mSearchCount++; b->search(search); } } }
void MainWindow::openSearchedBug(const QString &trackerName, const QString &bugId) { for (int i = 0; i < mBackendList.size(); ++i) { Backend *b = mBackendList.at(i); if (b->name() == trackerName) { qDebug() << "openSearchedBug: mSyncRequests is now " << mSyncRequests; b->displayWidget()->loadSearchResult(bugId); } } }
void MainWindow::syncNextTracker() { if (mBackendList.empty()) return; Backend *b = mBackendList.at(mSyncPosition); mSyncPosition++; if (mUploading) { mSyncRequests++; ui->syncingLabel->setText(QString("Uploading changes to %1").arg(b->name())); b->uploadAll(); } else { syncTracker(b); } }
void DirectorPlugin::pass(HttpRequest* r, const std::string& directorName, const std::string& backendName) { auto i = directors_.find(directorName); if (i == directors_.end()) { r->log(Severity::error, "director.pass(): No director with name '%s' configured.", directorName.c_str()); internalServerError(r); return; } Director* director = i->second.get(); // custom backend route Backend* backend = nullptr; if (!backendName.empty()) { backend = director->findBackend(backendName); if (!backend) { // explicit backend specified, but not found -> do not serve. r->log(Severity::error, "director: Requested backend '%s' not found.", backendName.c_str()); internalServerError(r); return; } } #if !defined(NDEBUG) server().log(Severity::trace, "director: passing request to %s [backend %s].", director->name().c_str(), backend->name().c_str()); #endif auto rn = requestNotes(r); rn->manager = director; r->onPostProcess.connect(std::bind(&DirectorPlugin::addVia, this, r)); director->schedule(rn, backend); return; }
void MainWindow::deleteTracker(const QString &id) { Backend *b = mBackendMap[id]; mBackendMap.remove(id); for (int i = 0; i < mBackendList.size(); ++i) { if (mBackendList.at(i) == b) { mBackendList.removeAt(i); break; } } QString name = b->name(); SqlUtilities::removeTracker(b->id(), name); pSearchTab->removeTracker(b); delete b; // This removes the tab as well, as the widget is destroyed QSettings settings("Entomologist"); settings.remove(QString("%1-sort-column").arg(name)); settings.remove(QString("%1-sort-order").arg(name)); settings.remove(QString("%1-header-geometry").arg(name)); }
// Called from the tracker tab to display the context menu void MainWindow::showMenu(int tabIndex) { QMenu contextMenu(tr("Context menu"), this); QAction *a; // Show a different context menu for the search tab int searchIndex = ui->trackerTab->indexOf(pSearchTab); if (tabIndex == searchIndex) { QAction *searchAction = contextMenu.addAction(tr("Clear Results")); a = contextMenu.exec(QCursor::pos()); if (a == searchAction) { SqlUtilities::clearSearch(); QSettings settings("Entomologist"); settings.setValue("last-search-query", ""); pSearchTab->refreshResults(); } return; } QString trackerName = ui->trackerTab->tabText(tabIndex); Backend *b = NULL; for (int i = 0; i < mBackendList.size(); ++i) { b = mBackendList.at(i); if (trackerName == b->name()) break; } if (b == NULL) return; QString id = b->id(); QAction *editAction = contextMenu.addAction(tr("Edit")); QAction *deleteAction = contextMenu.addAction(tr("Delete")); QAction *resyncAction = contextMenu.addAction(tr("Resync")); a = contextMenu.exec(QCursor::pos()); if (a == editAction) { NewTracker t(this, true); QString tmpName = b->name(); t.setName(b->name()); t.setHost(b->url()); t.setUsername(b->username()); t.setPassword(b->password()); t.setTrackerType(b->type()); if (t.exec() == QDialog::Accepted) { bool updateName = false; if (t.data().value("name") != tmpName) updateName = true; updateTracker(id, t.data(), updateName); } } else if (a == deleteAction) { QMessageBox box; box.setText(QString("Are you sure you want to delete %1?").arg(b->name())); box.setStandardButtons(QMessageBox::Yes|QMessageBox::No); if (box.exec() == QMessageBox::Yes) { deleteTracker(id); } } else if (a == resyncAction) { mSyncPosition = mBackendList.size(); syncTracker(b); } }
// When the user edits tracker information, this is called to save their new // data void MainWindow::updateTracker(const QString &id, QMap<QString, QString> data, bool updateName) { Backend *b = mBackendMap[id]; if (updateName) { for (int i = 0; i < mBackendList.size(); ++i) { if (data["name"] == mBackendList.at(i)->name()) { QMessageBox box; box.setText(QString("A tracker named <b>%1</b> already exists.").arg(data["name"])); box.exec(); return; } } QString iconDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation); iconDir.append(QDir::separator()).append("entomologist"); // Rename the icon, if necessary QString oldPath = QString ("%1%2%3.png") .arg(iconDir) .arg(QDir::separator()) .arg(b->name()); QString newPath = QString ("%1%2%3.png") .arg(iconDir) .arg(QDir::separator()) .arg(data["name"]); if (QFile::exists(oldPath) && !QFile::exists(newPath)) QFile::rename(oldPath, newPath); QString oldName, newName; oldName = b->name(); newName = data["name"]; ui->trackerTab->setTabText(ui->trackerTab->currentIndex(), newName); pSearchTab->renameTracker(oldName, newName); b->setName(newName); QSettings settings("Entomologist"); QVariant oldSortCol = settings.value(QString("%1-sort-column").arg(oldName)); settings.remove(QString("%1-sort-column").arg(oldName)); settings.setValue(QString("%1-sort-column").arg(newName), oldSortCol); QVariant oldSortOrd = settings.value(QString("%1-sort-order").arg(oldName)); settings.remove(QString("%1-sort-order").arg(oldName)); settings.setValue(QString("%1-sort-order").arg(newName), oldSortOrd); QVariant oldGeom = settings.value(QString("%1-header-geometry").arg(oldName)); settings.remove(QString("%1-header-geometry").arg(oldName)); settings.setValue(QString("%1-header-geometry").arg(newName), oldGeom); } b->setUsername(data["username"]); b->setPassword(data["password"]); if (!SqlUtilities::renameTracker(id, data["name"], data["username"], data["password"])) { backendError("An error occurred updating the tracker"); return; } }
int main(int argc, char *argv[]) { int ret = -1; LibraryCleanupHandler cleanup; { ::initApp("tokoloshtail", argc, argv); QCoreApplication app(argc, argv); if (!QDBusConnection::sessionBus().isConnected()) { fprintf(stderr, "Cannot connect to the D-Bus session bus.\n" "To start it, run:\n" "\teval `dbus-launch --auto-syntax`\n"); return 1; } { QDBusInterface iface(SERVICE_NAME, "/"); if (iface.isValid()) { iface.call("quit"); } } // const QString pluginDirectory = Config::value<QString>("plugindir", PLUGINDIR); // ### Can't make this work const QString pluginDirectory = Config::value<QString>("plugindir", QDir::cleanPath(QCoreApplication::applicationDirPath() + "/../plugins")); Log::log(10) << "Using plugin directory" << pluginDirectory; const QString backendName = Config::value<QString>("backend", "xine"); Log::log(10) << "Searching for backend" << backendName; QDir dir(pluginDirectory); if (!dir.exists()) { Log::log(0) << pluginDirectory << " doesn't seem to exist"; return 1; } { Tail tail; Backend *backend = 0; QLibrary *library = 0; QHash<QLibrary*, BackendPlugin*> candidates; foreach(const QFileInfo &fi, dir.entryInfoList(QDir::Files, QDir::Size)) { QLibrary *lib = new QLibrary(fi.absoluteFilePath()); CreateBackend createBackend = 0; if (lib->load() && (createBackend = (CreateBackend)lib->resolve("createTokoloshBackendInterface"))) { BackendPlugin *interface = createBackend(); if (interface && interface->keys().contains(backendName, Qt::CaseInsensitive)) { backend = interface->createBackend(&tail); if (backend) { library = lib; break; } else { Log::log(0) << fi.absoluteFilePath() << "doesn't seem to be able to create a backend"; } delete interface; } else if (!interface) { delete lib; } else { candidates[lib] = interface; } } else { if (lib->isLoaded()) { Log::log(1) << "Can't load" << fi.absoluteFilePath() << lib->errorString(); } delete lib; } } Q_ASSERT(!backend == !library); if (!backend) { for (QHash<QLibrary*, BackendPlugin*>::const_iterator it = candidates.begin(); it != candidates.end(); ++it) { const bool hadBackend = backend != 0; if (!backend) backend = it.value()->createBackend(&app); if (hadBackend || !backend) { it.key()->unload(); delete it.key(); } else { library = it.key(); } delete it.value(); } } if (!backend) { Log::log(0) << "Can't find a suitable backend"; return 1; } cleanup.library = library; bool registered = false; for (int i=0; i<5; ++i) { if (QDBusConnection::sessionBus().registerService(SERVICE_NAME)) { registered = true; break; } ::sleep(500); } if (!registered) { Log::log(0) << "Can't seem to register service" << QDBusConnection::sessionBus().lastError().message(); return 1; } if (!tail.setBackend(backend)) { Log::log(0) << backend->errorMessage() << backend->errorCode(); return 1; } QDBusConnection::sessionBus().registerObject("/", &tail, QDBusConnection::ExportScriptableSlots |QDBusConnection::ExportScriptableSignals); Log::log(10) << "Using" << backend->name(); ret = app.exec(); } } return ret; }
// PUT /:director_id/backends bool ApiRequest::createBackend(Director* director) { if (!director) { request_->status = x0::HttpStatus::NotFound; request_->finish(); return true; } std::string name; if (!loadParam("name", name)) return false; if (name.empty()) return badRequest("Failed parsing attribute 'name'. value is empty."); BackendRole role = BackendRole::Active; if (!loadParam("role", role)) return false; bool enabled = false; if (!loadParam("enabled", enabled)) return false; size_t capacity = 0; if (!loadParam("capacity", capacity)) return false; bool terminateProtection = false; if (hasParam("terminate-protection")) if (!loadParam("terminate-protection", terminateProtection)) return false; std::string protocol; if (!loadParam("protocol", protocol)) return false; if (protocol != "fastcgi" && protocol != "http") return false; SocketSpec socketSpec; std::string path; if (loadParam("path", path)) { socketSpec = SocketSpec::fromLocal(path); } else { std::string hostname; if (!loadParam("hostname", hostname)) return false; int port; if (!loadParam("port", port)) return false; socketSpec = SocketSpec::fromInet(IPAddress(hostname), port); } TimeSpan hcInterval; if (!loadParam("health-check-interval", hcInterval)) return false; HealthMonitor::Mode hcMode; if (!loadParam("health-check-mode", hcMode)) return false; if (!director->isMutable()) { request_->log(Severity::error, "director: Could not create backend '%s' at director '%s'. Director immutable.", name.c_str(), director->name().c_str()); request_->status = x0::HttpStatus::Forbidden; request_->finish(); return true; } Backend* backend = director->createBackend(name, protocol, socketSpec, capacity, role); if (!backend) return badRequest("Creating backend failed."); backend->setTerminateProtection(terminateProtection); backend->setEnabled(enabled); backend->healthMonitor()->setInterval(hcInterval); backend->healthMonitor()->setMode(hcMode); director->save(); request_->status = x0::HttpStatus::Created; request_->log(Severity::info, "director: %s created backend: %s.", director->name().c_str(), backend->name().c_str()); request_->finish(); return true; }