diff options
-rw-r--r-- | src/cardwidget.cc | 137 | ||||
-rw-r--r-- | src/cardwidget.h | 27 | ||||
-rw-r--r-- | src/cardwidget.ui | 53 | ||||
-rw-r--r-- | src/mainwindow.cc | 21 |
4 files changed, 162 insertions, 76 deletions
diff --git a/src/cardwidget.cc b/src/cardwidget.cc index d5b4e63..3b4c8b3 100644 --- a/src/cardwidget.cc +++ b/src/cardwidget.cc @@ -24,46 +24,59 @@ #include "cardwidget.h" +#include <QDebug> +#include <QHash> +#include <QSet> + /*** CardWidget ***/ CardWidget::CardWidget(QWidget* parent) : QWidget(parent) { setupUi(this); connect(profileList, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &CardWidget::onProfileChange); - connect(profileCB, &QAbstractButton::toggled, this, &CardWidget::onProfileCheck); + connect(profileFlavorList, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &CardWidget::onProfileFlavorChange); } void CardWidget::prepareMenu() { int idx = 0; - const bool off = activeProfile == noInOutProfile; profileList->clear(); /* Fill the ComboBox */ - for (const auto & profile : profiles) { - QByteArray name = profile.first; - // skip the "off" profile - if (name == noInOutProfile) - continue; - QString desc = QString::fromUtf8(profile.second); - profileList->addItem(desc, name); - if (profile.first == activeProfile - || (off && profile.first == lastActiveProfile) - ) - { + for (auto k : profiles.keys()) { + auto & profile = profiles[k]; + auto desc = profile.getProfileName(); + profileList->addItem(desc, k); + if (profile.containsProfile(activeProfile)) { profileList->setCurrentIndex(idx); - lastActiveProfile = profile.first; + changeProfile(k); } ++idx; } - - profileCB->setChecked(!off); } -void CardWidget::changeProfile(const QByteArray & name) +void CardWidget::changeProfile(const QString & name) { + auto &profile = profiles[name]; + auto old = profileFlavorList->currentText(); + profileFlavorList->clear(); + int idx = 0; + for (auto & entry : profile.entries) { + auto name = entry.getName(); + profileFlavorList->addItem(name, entry.id); + if (name == old || entry.id == activeProfile) { + profileFlavorList->setCurrentIndex(idx); + } + ++idx; + } + if (profileFlavorList->currentIndex() == -1) { + profileFlavorList->setCurrentIndex(0); + } +} + +void CardWidget::changeProfileFlavor(const QByteArray & id) { pa_operation* o; - if (!(o = pa_context_set_card_profile_by_index(get_context(), index, name.constData(), nullptr, nullptr))) { + if (!(o = pa_context_set_card_profile_by_index(get_context(), index, id.constData(), nullptr, nullptr))) { show_error(tr("pa_context_set_card_profile_by_index() failed").toUtf8().constData()); return; } @@ -76,17 +89,91 @@ void CardWidget::onProfileChange(int active) { return; if (active != -1) - changeProfile(profileList->itemData(active).toByteArray()); + changeProfile(profileList->itemData(active).toString()); } -void CardWidget::onProfileCheck(bool on) -{ +void CardWidget::onProfileFlavorChange(int active) { if (updating) return; - if (on) - onProfileChange(profileList->currentIndex()); - else - changeProfile(noInOutProfile); + if (active != -1) + changeProfileFlavor(profileFlavorList->itemData(active).toByteArray()); +} + +QString ProfileGroup::getProfileName() { + if (!name.isEmpty()) + return name; + // TODO + QHash<QString, int> counts; + qDebug() << "Entries" << this; + for (auto n : entries) { + qDebug() << n.tokens; + QSet<QString> tmp = n.tokens.toSet(); //(n.tokens.begin(), n.tokens.end()); + for (auto t : tmp) { + counts[t]++; + } + } + qDebug() << counts; + QSet<QString> todo = counts.keys().toSet(); + for (auto &pe : entries) { + QMutableListIterator<QString> it(pe.tokens); + while (it.hasNext()) { + auto s = it.next(); + if (counts[s] == entries.size()) { + it.remove(); + if (todo.remove(s)) { + if (!name.isEmpty()) { + name.append(QLatin1Char(' ')); + } + name.append(s); + } + } + } + } + return name; +} + +void ProfileGroup::addEntry(const char *id, const char *name) { + auto *pe = new ProfileEntry; + bool paren = false; + const char *pos = name, *tokenStart = name; + qDebug() << name << "is" << id; + while (*pos != '\0') { + if (!paren && isspace(*pos)) { + if (pos > tokenStart) { + qDebug() << tokenStart; + pe->tokens.append(QString::fromUtf8(tokenStart, pos - tokenStart)); + } + tokenStart = pos + 1; + } + if (paren && *pos == ')') { + qDebug() << tokenStart; + pe->tokens.append(QString::fromUtf8(tokenStart, pos - tokenStart + 1)); + paren = false; + tokenStart = pos + 1; + } + if (tokenStart == pos && *pos == '(') { + paren = true; + } + pos++; + } + if (pos > tokenStart) { + qDebug() << tokenStart; + pe->tokens.append(QString::fromUtf8(tokenStart, pos - tokenStart)); + } + pe->id = id; + this->entries.append(*pe); + delete pe; +} + +QString ProfileEntry::getName() const { + return tokens.join(QLatin1String(" ")); +} +bool ProfileGroup::containsProfile(const QByteArray &pro) const { + for (const auto &e : this->entries) { + if (e.id == pro) + return true; + } + return false; } diff --git a/src/cardwidget.h b/src/cardwidget.h index 71f6ebc..7bd87d2 100644 --- a/src/cardwidget.h +++ b/src/cardwidget.h @@ -24,6 +24,23 @@ #include "pavucontrol.h" #include "ui_cardwidget.h" #include <QWidget> +#include <QMap> +#include <QString> +#include <QList> + +struct ProfileEntry { + QByteArray id; + QStringList tokens; + QString getName() const; +}; + +struct ProfileGroup { + QString name; + QList<ProfileEntry> entries; + QString getProfileName(); + void addEntry(const char* id, const char* name); + bool containsProfile(const QByteArray &pro) const; +}; class PortInfo { public: @@ -45,20 +62,20 @@ public: uint32_t index; bool updating; - std::vector< std::pair<QByteArray,QByteArray> > profiles; + + QMap<QString, ProfileGroup> profiles; std::map<QByteArray, PortInfo> ports; QByteArray activeProfile; - QByteArray noInOutProfile; - QByteArray lastActiveProfile; bool hasSinks; bool hasSources; void prepareMenu(); protected: - void changeProfile(const QByteArray & name); + void changeProfile(const QString & name); + void changeProfileFlavor(const QByteArray & id); void onProfileChange(int active); - void onProfileCheck(bool on); + void onProfileFlavorChange(int active); }; diff --git a/src/cardwidget.ui b/src/cardwidget.ui index 28ea7ab..a75654b 100644 --- a/src/cardwidget.ui +++ b/src/cardwidget.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>368</width> - <height>79</height> + <height>106</height> </rect> </property> <property name="windowTitle"> @@ -33,14 +33,7 @@ </layout> </item> <item> - <layout class="QHBoxLayout" name="profileHLayout" stretch="0,0,1"> - <item> - <widget class="QCheckBox" name="profileCB"> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> + <layout class="QHBoxLayout" name="profileHLayout" stretch="0,1"> <item> <widget class="QLabel" name="profileLabel"> <property name="text"> @@ -54,6 +47,13 @@ </layout> </item> <item> + <layout class="QHBoxLayout" name="variantHLayout"> + <item> + <widget class="QComboBox" name="profileFlavorList"/> + </item> + </layout> + </item> + <item> <widget class="Line" name="line"> <property name="orientation"> <enum>Qt::Horizontal</enum> @@ -63,38 +63,5 @@ </layout> </widget> <resources/> - <connections> - <connection> - <sender>profileCB</sender> - <signal>toggled(bool)</signal> - <receiver>profileLabel</receiver> - <slot>setEnabled(bool)</slot> - <hints> - <hint type="sourcelabel"> - <x>137</x> - <y>47</y> - </hint> - <hint type="destinationlabel"> - <x>147</x> - <y>47</y> - </hint> - </hints> - </connection> - <connection> - <sender>profileCB</sender> - <signal>toggled(bool)</signal> - <receiver>profileList</receiver> - <slot>setEnabled(bool)</slot> - <hints> - <hint type="sourcelabel"> - <x>137</x> - <y>47</y> - </hint> - <hint type="destinationlabel"> - <x>315</x> - <y>47</y> - </hint> - </hints> - </connection> - </connections> + <connections/> </ui> diff --git a/src/mainwindow.cc b/src/mainwindow.cc index 76e81bf..66c0ac4 100644 --- a/src/mainwindow.cc +++ b/src/mainwindow.cc @@ -22,6 +22,7 @@ #include <config.h> #endif +#include <QDebug> #include <set> #include "mainwindow.h" @@ -258,9 +259,23 @@ void MainWindow::updateCard(const pa_card_info &info) { if (!p_profile->available) desc += tr(" (unavailable)").toUtf8().constData(); - w->profiles.push_back(std::pair<QByteArray,QByteArray>(p_profile->name, desc)); - if (p_profile->n_sinks == 0 && p_profile->n_sources == 0) - w->noInOutProfile = p_profile->name; + QString parseId = QString::fromUtf8(p_profile->name); + int plus = parseId.indexOf(QLatin1Char('+')); + if (plus != -1) { + parseId = parseId.left(plus); + } + auto list = parseId.split(QRegularExpression(QLatin1String("[:\\-]"))); + parseId.clear(); + for (auto p : list) { + if (p == QLatin1String("input") || p == QLatin1String("output")) + continue; + if (parseId.isEmpty() || p.startsWith(QLatin1String("extra"))) { + parseId.append(p); + } + } + qDebug() << "ParseID:" << parseId; + ProfileGroup &group = w->profiles[parseId]; + group.addEntry(p_profile->name, desc.constData()); } w->activeProfile = info.active_profile ? info.active_profile->name : ""; |