Chris@416: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@416: Chris@416: /* Chris@416: Sonic Visualiser Chris@416: An audio file viewer and annotation editor. Chris@416: Centre for Digital Music, Queen Mary, University of London. Chris@416: This file copyright 2008 QMUL. Chris@416: Chris@416: This program is free software; you can redistribute it and/or Chris@416: modify it under the terms of the GNU General Public License as Chris@416: published by the Free Software Foundation; either version 2 of the Chris@416: License, or (at your option) any later version. See the file Chris@416: COPYING included with this distribution for more information. Chris@416: */ Chris@416: Chris@416: #include "TransformFinder.h" Chris@416: Chris@424: #include "base/XmlExportable.h" Chris@416: #include "transform/TransformFactory.h" Chris@424: #include "SelectableLabel.h" Chris@416: Chris@421: #include Chris@416: #include Chris@416: #include Chris@416: #include Chris@416: #include Chris@416: #include Chris@421: #include Chris@423: #include Chris@424: #include Chris@426: #include Chris@421: Chris@416: TransformFinder::TransformFinder(QWidget *parent) : Chris@417: QDialog(parent), Chris@417: m_resultsFrame(0), Chris@417: m_resultsLayout(0) Chris@416: { Chris@416: setWindowTitle(tr("Find a Transform")); Chris@416: Chris@416: QGridLayout *mainGrid = new QGridLayout; Chris@421: mainGrid->setVerticalSpacing(0); Chris@416: setLayout(mainGrid); Chris@416: Chris@416: mainGrid->addWidget(new QLabel(tr("Find:")), 0, 0); Chris@416: Chris@416: QLineEdit *searchField = new QLineEdit; Chris@416: mainGrid->addWidget(searchField, 0, 1); Chris@416: connect(searchField, SIGNAL(textChanged(const QString &)), Chris@416: this, SLOT(searchTextChanged(const QString &))); Chris@416: Chris@416: m_resultsScroll = new QScrollArea; Chris@420: // m_resultsScroll->setWidgetResizable(true); Chris@416: mainGrid->addWidget(m_resultsScroll, 1, 0, 1, 2); Chris@416: mainGrid->setRowStretch(1, 10); Chris@416: Chris@416: QDialogButtonBox *bb = new QDialogButtonBox(QDialogButtonBox::Ok | Chris@416: QDialogButtonBox::Cancel); Chris@416: mainGrid->addWidget(bb, 2, 0, 1, 2); Chris@416: connect(bb, SIGNAL(accepted()), this, SLOT(accept())); Chris@416: connect(bb, SIGNAL(rejected()), this, SLOT(reject())); Chris@421: if (!m_resultsLayout) { Chris@421: std::cerr << "creating frame & layout" << std::endl; Chris@421: m_resultsFrame = new QWidget; Chris@421: QPalette palette = m_resultsFrame->palette(); Chris@421: palette.setColor(QPalette::Window, palette.color(QPalette::Base)); Chris@421: m_resultsFrame->setPalette(palette); Chris@421: m_resultsScroll->setPalette(palette); Chris@421: m_resultsLayout = new QVBoxLayout; Chris@423: m_resultsLayout->setSpacing(0); Chris@423: m_resultsLayout->setContentsMargins(0, 0, 0, 0); Chris@421: m_resultsFrame->setLayout(m_resultsLayout); Chris@421: m_resultsScroll->setWidget(m_resultsFrame); Chris@421: m_resultsFrame->show(); Chris@421: } Chris@416: Chris@426: QAction *up = new QAction(tr("Up"), this); Chris@426: up->setShortcut(tr("Up")); Chris@426: connect(up, SIGNAL(triggered()), this, SLOT(up())); Chris@426: addAction(up); Chris@426: Chris@426: QAction *down = new QAction(tr("Down"), this); Chris@426: down->setShortcut(tr("Down")); Chris@426: connect(down, SIGNAL(triggered()), this, SLOT(down())); Chris@426: addAction(down); Chris@426: Chris@423: QDesktopWidget *desktop = QApplication::desktop(); Chris@423: QRect available = desktop->availableGeometry(); Chris@423: Chris@423: int width = available.width() / 2; Chris@423: int height = available.height() / 2; Chris@423: if (height < 450) { Chris@423: if (available.height() > 500) height = 450; Chris@423: } Chris@423: if (width < 600) { Chris@423: if (available.width() > 650) width = 600; Chris@423: } Chris@423: Chris@423: resize(width, height); Chris@423: raise(); Chris@424: Chris@424: m_upToDateCount = 0; Chris@424: m_timer = new QTimer(this); Chris@424: connect(m_timer, SIGNAL(timeout()), this, SLOT(timeout())); Chris@425: m_timer->start(30); Chris@416: } Chris@416: Chris@416: TransformFinder::~TransformFinder() Chris@416: { Chris@416: } Chris@416: Chris@416: void Chris@416: TransformFinder::searchTextChanged(const QString &text) Chris@416: { Chris@416: std::cerr << "text is " << text.toStdString() << std::endl; Chris@424: m_newSearchText = text; Chris@424: } Chris@416: Chris@424: void Chris@424: TransformFinder::timeout() Chris@424: { Chris@424: int maxResults = 40; Chris@416: Chris@424: if (m_newSearchText != "") { Chris@416: Chris@424: QString text = m_newSearchText; Chris@424: m_newSearchText = ""; Chris@424: Chris@424: QStringList keywords = text.split(' ', QString::SkipEmptyParts); Chris@424: TransformFactory::SearchResults results = Chris@424: TransformFactory::getInstance()->search(keywords); Chris@424: Chris@424: std::cerr << results.size() << " result(s)..." << std::endl; Chris@424: Chris@431: std::set sorted; Chris@424: sorted.clear(); Chris@424: for (TransformFactory::SearchResults::const_iterator j = results.begin(); Chris@424: j != results.end(); ++j) { Chris@424: sorted.insert(j->second); Chris@424: } Chris@424: Chris@424: m_sortedResults.clear(); Chris@431: for (std::set::const_iterator j = sorted.end(); Chris@424: j != sorted.begin(); ) { Chris@424: --j; Chris@424: m_sortedResults.push_back(*j); Chris@424: if (m_sortedResults.size() == maxResults) break; Chris@424: } Chris@424: Chris@424: if (m_sortedResults.empty()) m_selectedTransform = ""; Chris@431: else m_selectedTransform = m_sortedResults.begin()->key; Chris@424: Chris@424: m_upToDateCount = 0; Chris@424: Chris@424: for (int j = m_labels.size(); j > m_sortedResults.size(); ) { Chris@424: m_labels[--j]->hide(); Chris@424: } Chris@424: Chris@424: return; Chris@416: } Chris@416: Chris@425: if (m_upToDateCount >= m_sortedResults.size()) return; Chris@425: Chris@425: while (m_upToDateCount < m_sortedResults.size()) { Chris@417: Chris@424: int i = m_upToDateCount; Chris@416: Chris@431: // std::cerr << "sorted size = " << m_sortedResults.size() << std::endl; Chris@417: Chris@431: TransformDescription desc; Chris@431: TransformId tid = m_sortedResults[i].key; Chris@431: TransformFactory *factory = TransformFactory::getInstance(); Chris@431: TransformFactory::TransformInstallStatus status = Chris@431: factory->getTransformInstallStatus(tid); Chris@431: QString suffix; Chris@431: Chris@431: if (status == TransformFactory::TransformInstalled) { Chris@431: desc = factory->getTransformDescription(tid); Chris@431: } else { Chris@431: desc = factory->getUninstalledTransformDescription(tid); Chris@431: suffix = tr(" (not installed)"); Chris@431: } Chris@419: Chris@419: QString labelText; Chris@431: labelText += tr("%1%2
") Chris@431: .arg(XmlExportable::encodeEntities(desc.name)) Chris@431: .arg(suffix); Chris@424: Chris@416: labelText += "..."; Chris@431: for (TextMatcher::Match::FragmentMap::const_iterator k = Chris@424: m_sortedResults[i].fragments.begin(); Chris@424: k != m_sortedResults[i].fragments.end(); ++k) { Chris@416: labelText += k->second; Chris@416: labelText += "... "; Chris@416: } Chris@416: labelText += tr(""); Chris@417: Chris@419: QString selectedText; Chris@431: selectedText += tr("%1%2
") Chris@431: .arg(XmlExportable::encodeEntities Chris@431: (desc.name == "" ? desc.identifier : desc.name)) Chris@431: .arg(suffix); Chris@431: Chris@431: if (desc.longDescription != "") { Chris@431: selectedText += tr("%1") Chris@431: .arg(XmlExportable::encodeEntities(desc.longDescription)); Chris@431: } else if (desc.description != "") { Chris@431: selectedText += tr("%1") Chris@431: .arg(XmlExportable::encodeEntities(desc.description)); Chris@431: } Chris@419: Chris@426: selectedText += tr("
"); Chris@431: if (desc.type != "") { Chris@431: selectedText += tr("      — Plugin type: %1
") Chris@431: .arg(XmlExportable::encodeEntities(desc.type)); Chris@431: } Chris@431: if (desc.category != "") { Chris@431: selectedText += tr("      — Category: %1
") Chris@431: .arg(XmlExportable::encodeEntities(desc.category)); Chris@431: } Chris@426: selectedText += tr("      — System identifier: %1") Chris@424: .arg(XmlExportable::encodeEntities(desc.identifier)); Chris@426: selectedText += tr("
"); Chris@419: Chris@417: if (i >= m_labels.size()) { Chris@419: SelectableLabel *label = new SelectableLabel(m_resultsFrame); Chris@421: m_resultsLayout->addWidget(label); Chris@420: connect(label, SIGNAL(selectionChanged()), this, Chris@420: SLOT(selectedLabelChanged())); Chris@424: connect(label, SIGNAL(doubleClicked()), this, Chris@424: SLOT(accept())); Chris@421: QPalette palette = label->palette(); Chris@421: label->setPalette(palette); Chris@417: m_labels.push_back(label); Chris@417: } Chris@421: Chris@420: m_labels[i]->setObjectName(desc.identifier); Chris@423: m_labels[i]->setFixedWidth(this->width() - 40); Chris@419: m_labels[i]->setUnselectedText(labelText); Chris@425: Chris@425: // std::cerr << "selected text: " << selectedText.toStdString() << std::endl; Chris@419: m_labels[i]->setSelectedText(selectedText); Chris@423: Chris@424: m_labels[i]->setSelected(m_selectedTransform == desc.identifier); Chris@425: Chris@425: if (!m_labels[i]->isVisible()) m_labels[i]->show(); Chris@417: Chris@424: ++m_upToDateCount; Chris@424: Chris@425: if (i == 0) break; Chris@416: } Chris@425: Chris@425: m_resultsFrame->resize(m_resultsFrame->sizeHint()); Chris@416: } Chris@416: Chris@420: void Chris@420: TransformFinder::selectedLabelChanged() Chris@420: { Chris@420: QObject *s = sender(); Chris@420: m_selectedTransform = ""; Chris@420: for (int i = 0; i < m_labels.size(); ++i) { Chris@420: if (!m_labels[i]->isVisible()) continue; Chris@420: if (m_labels[i] == s) { Chris@420: if (m_labels[i]->isSelected()) { Chris@420: m_selectedTransform = m_labels[i]->objectName(); Chris@420: } Chris@420: } else { Chris@420: if (m_labels[i]->isSelected()) { Chris@420: m_labels[i]->setSelected(false); Chris@420: } Chris@420: } Chris@420: } Chris@420: std::cerr << "selectedLabelChanged: selected transform is now \"" Chris@420: << m_selectedTransform.toStdString() << "\"" << std::endl; Chris@420: } Chris@420: Chris@416: TransformId Chris@416: TransformFinder::getTransform() const Chris@416: { Chris@424: return m_selectedTransform; Chris@416: } Chris@416: Chris@426: void Chris@426: TransformFinder::up() Chris@426: { Chris@426: for (int i = 0; i < m_labels.size(); ++i) { Chris@426: if (!m_labels[i]->isVisible()) continue; Chris@426: if (m_labels[i]->objectName() == m_selectedTransform) { Chris@426: if (i > 0) { Chris@426: m_labels[i]->setSelected(false); Chris@426: m_labels[i-1]->setSelected(true); Chris@426: m_selectedTransform = m_labels[i-1]->objectName(); Chris@426: } Chris@426: return; Chris@426: } Chris@426: } Chris@426: } Chris@426: Chris@426: void Chris@426: TransformFinder::down() Chris@426: { Chris@426: for (int i = 0; i < m_labels.size(); ++i) { Chris@426: if (!m_labels[i]->isVisible()) continue; Chris@426: if (m_labels[i]->objectName() == m_selectedTransform) { Chris@426: if (i+1 < m_labels.size() && Chris@426: m_labels[i+1]->isVisible()) { Chris@426: m_labels[i]->setSelected(false); Chris@426: m_labels[i+1]->setSelected(true); Chris@426: m_selectedTransform = m_labels[i+1]->objectName(); Chris@426: } Chris@426: return; Chris@426: } Chris@426: } Chris@426: } Chris@426: