summaryrefslogtreecommitdiffstats
path: root/src/cardwidget.cc
diff options
context:
space:
mode:
authorSimon Rettberg2021-11-04 14:47:38 +0100
committerSimon Rettberg2021-11-04 14:47:38 +0100
commita11c084f904c21607bd6f925b2280e95d5592082 (patch)
treea4393bc7889a5cc81f64cfc4b5dfc9da9f5b002a /src/cardwidget.cc
parent"Fix" compile on older distros by killing off i18n for now (diff)
downloadpavucontrol-slx-a11c084f904c21607bd6f925b2280e95d5592082.tar.gz
pavucontrol-slx-a11c084f904c21607bd6f925b2280e95d5592082.tar.xz
pavucontrol-slx-a11c084f904c21607bd6f925b2280e95d5592082.zip
Try to group the output configurations in the last tab
This introduces a second combobox that is supposed to list the different output configurations for a selected output. The idea is to list the most resonable configration first (i.e. make it the default) and have the primary combobox only list the different outputs themselves. Otherwise the UI might appear quite overwhelming to a novice user, depending on their hardware. Some platforms for exmaple list 4-7 HDMI ports each with stereo, 5.1 and 7.1 configurations. Having all this in a flat list is confusing and bad UX, as it doesn't even fit on a single screen. Unfortunately the pa-api isn't hierarchical and pretty much enumerates the configurations exactly the way they get displayed by pavucontrol, so we need to employ some fuzzy matching logic for grouping, which might or might not need some refining in the future.
Diffstat (limited to 'src/cardwidget.cc')
-rw-r--r--src/cardwidget.cc137
1 files changed, 112 insertions, 25 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;
}