diff options
| author | Florian Jung <flo@windfisch.org> | 2012-09-02 18:37:06 +0000 | 
|---|---|---|
| committer | Florian Jung <flo@windfisch.org> | 2012-09-02 18:37:06 +0000 | 
| commit | 00d38a64c11bfc363fd762a351225f3e4902d44e (patch) | |
| tree | 420fd5f8bda0c8046c02bdf0b6474f59fc31c39c | |
| parent | 58136c7acf8f5f3281fe8e339aeaca251f2d1b7f (diff) | |
plugins can now be grouped
| -rw-r--r-- | muse2/muse/conf.cpp | 5 | ||||
| -rw-r--r-- | muse2/muse/plugin.cpp | 409 | ||||
| -rw-r--r-- | muse2/muse/plugin.h | 75 | 
3 files changed, 467 insertions, 22 deletions
diff --git a/muse2/muse/conf.cpp b/muse2/muse/conf.cpp index cca3cb94..37959f0f 100644 --- a/muse2/muse/conf.cpp +++ b/muse2/muse/conf.cpp @@ -64,6 +64,7 @@  #include "midiseq.h"  #include "amixer.h"  #include "track.h" +#include "plugin.h"  namespace MusECore { @@ -917,6 +918,8 @@ void readConfiguration(Xml& xml, bool doReadMidiPortConfig, bool doReadGlobalCon                                MusEGlobal::config.unhideTracks = xml.parseInt();                          else if (tag == "smartFocus")                                MusEGlobal::config.smartFocus = xml.parseInt(); +                        else if (tag == "plugin_groups") +                              MusEGlobal::readPluginGroupConfiguration(xml);                          // ---- the following only skips obsolete entries ----                          else if ((tag == "arranger") || (tag == "geometryPianoroll") || (tag == "geometryDrumedit")) @@ -1321,6 +1324,8 @@ void MusE::writeGlobalConfiguration(int level, MusECore::Xml& xml) const        xml.colorTag(level, "bigtimeBackgroundcolor", MusEGlobal::config.bigTimeBackgroundColor);        xml.colorTag(level, "waveEditBackgroundColor", MusEGlobal::config.waveEditBackgroundColor); +      MusEGlobal::writePluginGroupConfiguration(level, xml); +        writeSeqConfiguration(level, xml, false);        MusEGui::DrumEdit::writeConfiguration(level, xml); diff --git a/muse2/muse/plugin.cpp b/muse2/muse/plugin.cpp index e8b0489c..f1d817c9 100644 --- a/muse2/muse/plugin.cpp +++ b/muse2/muse/plugin.cpp @@ -31,6 +31,7 @@  #include <QButtonGroup>  #include <QCheckBox> +#include <QInputDialog>  #include <QComboBox>  #include <QCursor>  #include <QDir> @@ -70,6 +71,9 @@  #include "fastlog.h"  #include "checkbox.h"  #include "verticalmeter.h" +#include "popupmenu.h" +#include "menutitleitem.h" +  #include "audio.h"  #include "al/dsp.h" @@ -84,10 +88,14 @@  namespace MusEGlobal {  MusECore::PluginList plugins; +MusECore::PluginGroups plugin_groups; +QList<QString> plugin_group_names; +  }  namespace MusEGui {  int PluginDialog::selectedPlugType = 0; +int PluginDialog::selectedGroup = 0;  QStringList PluginDialog::sortItems = QStringList();  QRect PluginDialog::geometrySave = QRect();  QByteArray PluginDialog::listSave = QByteArray(); @@ -623,6 +631,9 @@ void ladspaControlRange(const LADSPA_Descriptor* plugin, unsigned long port, flo              *max = 1.0;        } + + +  //---------------------------------------------------------  //   Plugin  //--------------------------------------------------------- @@ -631,6 +642,7 @@ Plugin::Plugin(QFileInfo* f, const LADSPA_Descriptor* d, bool isDssi, bool isDss  {    _isDssi = isDssi;    _isDssiSynth = isDssiSynth; +      #ifdef DSSI_SUPPORT    dssi_descr = NULL;    #endif @@ -1021,6 +1033,40 @@ static void loadPluginDir(const QString& s)              }        } + +void PluginGroups::shift_left(int first, int last) +{ +  for (int i=first; i<=last; i++) +    replace_group(i, i-1); +} + +void PluginGroups::shift_right(int first, int last) +{ +  for (int i=last; i>=first; i--) +    replace_group(i,i+1); +} + +void PluginGroups::erase(int index) +{ +  for (PluginGroups::iterator it=begin(); it!=end(); it++) +  { +    it->remove(index); +  } +} + +void PluginGroups::replace_group(int old, int now) +{ +  for (PluginGroups::iterator it=begin(); it!=end(); it++) +  { +    if (it->contains(old)) +    { +      it->remove(old); +      it->insert(now); +    } +  } +} + +  //---------------------------------------------------------  //   initPlugins  //--------------------------------------------------------- @@ -2822,14 +2868,23 @@ namespace MusEGui {  PluginDialog::PluginDialog(QWidget* parent)    : QDialog(parent)        { +      group_info=NULL;        setWindowTitle(tr("MusE: select plugin"));        if(!geometrySave.isNull())          setGeometry(geometrySave);        QVBoxLayout* layout = new QVBoxLayout(this); - +     +      tabBar = new QTabBar(this); +      tabBar->setToolTip(tr("Plugin categories.\nRight-click on tabs to manage.\nRight-click on plugins to add/remove from a category.")); +      tabBar->addTab("All"); +      for (QList<QString>::iterator it=MusEGlobal::plugin_group_names.begin(); it!=MusEGlobal::plugin_group_names.end(); it++) +        tabBar->addTab(*it); +       +              pList  = new QTreeWidget(this); +              pList->setColumnCount(12);        // "Note: In order to avoid performance issues, it is recommended that sorting         //   is enabled after inserting the items into the tree. Alternatively, you could  @@ -2862,7 +2917,9 @@ PluginDialog::PluginDialog(QWidget* parent)        pList->setSelectionMode(QAbstractItemView::SingleSelection);        pList->setAlternatingRowColors(true);        pList->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); +      pList->setContextMenuPolicy(Qt::CustomContextMenu); +      layout->addWidget(tabBar);        layout->addWidget(pList);        //--------------------------------------------------- @@ -2920,6 +2977,23 @@ PluginDialog::PluginDialog(QWidget* parent)              case SEL_M:   onlyM->setChecked(true);   break;              case SEL_ALL: allPlug->setChecked(true); break;              } +       +      tabBar->setCurrentIndex(selectedGroup); +      tabBar->setContextMenuPolicy(Qt::ActionsContextMenu); +      newGroupAction= new QAction(tr("&create new group"),tabBar); +      delGroupAction= new QAction(tr("&delete currently selected group"),tabBar); +      renGroupAction= new QAction(tr("re&name currently selected group"),tabBar); +      tabBar->addAction(newGroupAction); +      tabBar->addAction(delGroupAction); +      tabBar->addAction(renGroupAction); +       +      if (selectedGroup==0) +      { +				delGroupAction->setEnabled(false); +				renGroupAction->setEnabled(false); +			} +      //tabBar->setMovable(true); //not yet. need to find a way to forbid moving the zeroth tab +              plugSelGroup->setToolTip(tr("Select which types of plugins should be visible in the list.<br>"                               "Note that using mono plugins on stereo tracks is not a problem, two will be used in parallel.<br>" @@ -2968,21 +3042,122 @@ PluginDialog::PluginDialog(QWidget* parent)        connect(pList,   SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), SLOT(accept()));        connect(pList,   SIGNAL(itemClicked(QTreeWidgetItem*,int)), SLOT(enableOkB())); +      connect(pList,   SIGNAL(customContextMenuRequested(const QPoint&)), SLOT(plistContextMenu(const QPoint&)));        connect(cancelB, SIGNAL(clicked()), SLOT(reject()));        connect(okB,     SIGNAL(clicked()), SLOT(accept())); -      connect(plugSel, SIGNAL(buttonClicked(QAbstractButton*)), SLOT(fillPlugs(QAbstractButton*))); +      connect(plugSel, SIGNAL(buttonClicked(QAbstractButton*)), SLOT(pluginTypeSelectionChanged(QAbstractButton*))); +      connect(tabBar,  SIGNAL(currentChanged(int)), SLOT(tabChanged(int))); +      //connect(tabBar,  SIGNAL(tabMoved(int,int)), SLOT(tabMoved(int,int))); //not yet. need to find a way to forbid moving the zeroth tab        connect(sortBox, SIGNAL(editTextChanged(const QString&)),SLOT(fillPlugs())); +      connect(newGroupAction, SIGNAL(activated()), SLOT(newGroup())); +      connect(delGroupAction, SIGNAL(activated()), SLOT(delGroup())); +      connect(renGroupAction, SIGNAL(activated()), SLOT(renameGroup()));        sortBox->setFocus();        } +void PluginDialog::plistContextMenu(const QPoint& point) +{ +  QTreeWidgetItem* item = pList->currentItem(); +  if (item) +  { +    group_info = &MusEGlobal::plugin_groups.get(item->text(1), item->text(2)); +    QMenu* menu = new MusEGui::PopupMenu(this, true); +    QSignalMapper* mapper = new QSignalMapper(this); +    menu->addAction(new MusEGui::MenuTitleItem(tr("Associated categories"), menu)); +     +    if (tabBar->count()==1) +    { +      QAction* tmp=menu->addAction(tr("You need to define some categories first.")); +      tmp->setEnabled(false); +    } +    else +    { +      for (int i=1; i<tabBar->count(); i++) // ignore the first tab ("All") +      { +        QAction* act=menu->addAction(tabBar->tabText(i)); +        act->setCheckable(true); +        act->setChecked(group_info->contains(i)); +        connect(act,SIGNAL(toggled(bool)), mapper, SLOT(map())); +        mapper->setMapping(act, i); +      } +      connect(mapper, SIGNAL(mapped(int)), this, SLOT(groupMenuEntryToggled(int))); +    } +     +    menu->exec(mapToGlobal(point)); +     +    delete mapper; +    delete menu; +     +    if (selectedGroup!=0 && !group_info->contains(selectedGroup)) // we removed the entry from the currently visible group +      fillPlugs(); +     +    group_info=NULL; +  } +} + +void PluginDialog::groupMenuEntryToggled(int index) +{ +  if (group_info) +  { +    if (group_info->contains(index)) +      group_info->remove(index); +    else +      group_info->insert(index); +  } +  else +  { +    fprintf(stderr,"THIS SHOULD NEVER HAPPEN: groupMenuEntryToggled called but group_info is NULL!\n"); +  } +} + + +  //---------------------------------------------------------  //   enableOkB  //---------------------------------------------------------  void PluginDialog::enableOkB() -      { -	okB->setEnabled(true); -      } +{ +  okB->setEnabled(true); +} + + +void PluginDialog::newGroup() +{ +  MusEGlobal::plugin_groups.shift_right(selectedGroup+1, tabBar->count()); +  tabBar->insertTab(selectedGroup+1, tr("new group")); +  MusEGlobal::plugin_group_names.insert(selectedGroup, tr("new group")); +} + +void PluginDialog::delGroup() +{ +  if (selectedGroup!=0) +  { +    MusEGlobal::plugin_groups.erase(selectedGroup); +    MusEGlobal::plugin_groups.shift_left(selectedGroup+1, tabBar->count()); +    tabBar->removeTab(selectedGroup); +    MusEGlobal::plugin_group_names.removeAt(selectedGroup-1); +  } +} + +void PluginDialog::renameGroup() +{ +  if (selectedGroup!=0) +  { +    bool ok; +    QString newname = QInputDialog::getText(this, tr("Enter the new group name"), +                                        tr("Enter the new group name"), QLineEdit::Normal, +                                        tabBar->tabText(selectedGroup), &ok); +    if (ok) +    { +      tabBar->setTabText(selectedGroup, newname); +      MusEGlobal::plugin_group_names.replace(selectedGroup-1, newname); +    } +  } +} + + +  //---------------------------------------------------------  //   value @@ -3042,10 +3217,10 @@ void PluginDialog::reject()  }  //--------------------------------------------------------- -//    fillPlugs +//    pluginTypeSelectionChanged  //--------------------------------------------------------- -void PluginDialog::fillPlugs(QAbstractButton* ab) +void PluginDialog::pluginTypeSelectionChanged(QAbstractButton* ab)        {        if (ab == allPlug)              selectedPlugType = SEL_ALL; @@ -3058,11 +3233,42 @@ void PluginDialog::fillPlugs(QAbstractButton* ab)        fillPlugs();        } +void PluginDialog::tabChanged(int index) +{ +  renGroupAction->setEnabled(index!=0); +  delGroupAction->setEnabled(index!=0); +   +  selectedGroup=index; +  fillPlugs(); +} + +void PluginDialog::tabMoved(int from, int to) +{ +//all the below doesn't work :/ +/*  static bool recurse=false; +   +  if (!recurse) +  { +    if (from==0 && to!=0) {recurse=true; tabBar->moveTab(to, from);} +    if (from!=0 && to==0) {recurse=true; tabBar->moveTab(from, to);} +  } +  recurse=false;*/ +   +   +   //if ((from==0 && to!=0) || (from!=0 && to==0)) { tabBar->setMovable(false); tabBar->setMovable(true); } +   printf("**** %i -> %i\n", from, to); +   +  //FINDMICH TODO +} +  void PluginDialog::fillPlugs()  {      QString type_name;      pList->clear(); -    for (MusECore::iPlugin i = MusEGlobal::plugins.begin(); i != MusEGlobal::plugins.end(); ++i) { +    okB->setEnabled(false); +    for (MusECore::iPlugin i = MusEGlobal::plugins.begin(); i != MusEGlobal::plugins.end(); ++i) +       if (selectedGroup==0 || MusEGlobal::plugin_groups.get(*i).contains(selectedGroup)) +       {            unsigned long ai = i->inports();                   unsigned long ao = i->outports();            unsigned long ci = i->controlInPorts(); @@ -4267,6 +4473,191 @@ QWidget* PluginLoader::createWidget(const QString & className, QWidget * parent,      return new Slider(parent, name.toLatin1().constData(), Qt::Horizontal);     return QUiLoader::createWidget(className, parent, name); -}; +}  } // namespace MusEGui + + +namespace MusEGlobal { + +static void writePluginGroupNames(int level, MusECore::Xml& xml) +{ +  xml.tag(level++, "group_names"); +   +  for (QList<QString>::iterator it=plugin_group_names.begin(); it!=plugin_group_names.end(); it++) +    xml.strTag(level, "name", *it); +   +  xml.etag(--level, "group_names"); +} + +static void writePluginGroupMap(int level, MusECore::Xml& xml) +{ +  using MusECore::PluginGroups; +   +  xml.tag(level++, "group_map"); +   +  for (PluginGroups::iterator it=plugin_groups.begin(); it!=plugin_groups.end(); it++) +		if (!it.value().empty()) +		{ +			xml.tag(level++, "entry"); +			 +			xml.strTag(level, "lib", it.key().first); +			xml.strTag(level, "label", it.key().second); +			 +			for (QSet<int>::iterator it2=it.value().begin(); it2!=it.value().end(); it2++) +				xml.intTag(level, "group", *it2); + +			xml.etag(--level, "entry"); +		} +   +  xml.etag(--level, "group_map"); +} + +void writePluginGroupConfiguration(int level, MusECore::Xml& xml) +{ +  xml.tag(level++, "plugin_groups"); + +  writePluginGroupNames(level, xml); +  writePluginGroupMap(level, xml); +   +  xml.etag(--level, "plugin_groups"); +} + +static void readPluginGroupNames(MusECore::Xml& xml) +{ +	plugin_group_names.clear(); +	 +	for (;;) +	{ +		MusECore::Xml::Token token = xml.parse(); +		if (token == MusECore::Xml::Error || token == MusECore::Xml::End) +			break; +			 +		const QString& tag = xml.s1(); +		switch (token) +		{ +			case MusECore::Xml::TagStart: +				if (tag=="name") +					plugin_group_names.append(xml.parse1()); +				else +					xml.unknown("readPluginGroupNames"); +				break; +				 +			case MusECore::Xml::TagEnd: +				if (tag == "group_names") +					return; +				 +			default: +				break; +		} +	} +} +   +static void readPluginGroupMap(MusECore::Xml& xml) +{ +	plugin_groups.clear(); +	 +	for (;;) +	{ +		MusECore::Xml::Token token = xml.parse(); +		if (token == MusECore::Xml::Error || token == MusECore::Xml::End) +			break; +			 +		const QString& tag = xml.s1(); +		switch (token) +		{ +			case MusECore::Xml::TagStart: +				if (tag=="entry") +				{ +					QString lib; +					QString label; +					QSet<int> groups; +					bool read_lib=false, read_label=false; +					 +					for (;;) +					{ +						MusECore::Xml::Token token = xml.parse(); +						if (token == MusECore::Xml::Error || token == MusECore::Xml::End) +							break; +							 +						const QString& tag = xml.s1(); +						switch (token) +						{ +							case MusECore::Xml::TagStart: +								if (tag=="lib") +								{ +									lib=xml.parse1(); +									read_lib=true; +								} +								else if (tag=="label") +								{ +									label=xml.parse1(); +									read_label=true; +								} +								else if (tag=="group") +									groups.insert(xml.parseInt()); +								else +									xml.unknown("readPluginGroupMap"); +								break; +								 +							case MusECore::Xml::TagEnd: +								if (tag == "entry") +									goto done_reading_entry; +								 +							default: +								break; +						} +					} + +done_reading_entry: + +					if (read_lib && read_label) +						plugin_groups.get(lib,label)=groups; +					else +						fprintf(stderr,"ERROR: plugin group map entry without lib or label!\n"); +				} +				else +					xml.unknown("readPluginGroupMap"); +				break; +				 +			case MusECore::Xml::TagEnd: +				if (tag == "group_map") +					return; +				 +			default: +				break; +		} +	} +} + +void readPluginGroupConfiguration(MusECore::Xml& xml) +{ +	for (;;) +	{ +		MusECore::Xml::Token token = xml.parse(); +		if (token == MusECore::Xml::Error || token == MusECore::Xml::End) +			break; +			 +		const QString& tag = xml.s1(); +		switch (token) +		{ +			case MusECore::Xml::TagStart: +				if (tag=="group_names") +					readPluginGroupNames(xml); +				else if (tag=="group_map") +					readPluginGroupMap(xml); +				else +					xml.unknown("readPluginGroupConfiguration"); +				break; +				 +			case MusECore::Xml::TagEnd: +				if (tag == "plugin_groups") +					return; +				 +			default: +				break; +		} +	} +} +   +} // namespace MusEGlobal diff --git a/muse2/muse/plugin.h b/muse2/muse/plugin.h index 39da5edf..ee37c34f 100644 --- a/muse2/muse/plugin.h +++ b/muse2/muse/plugin.h @@ -27,8 +27,13 @@  #include <list>  #include <vector> +#include <QSet> +#include <QMap> +#include <QPair> +#include <QMouseEvent>  #include <QDialog> +#include <QTabBar>  #include <QFileInfo>  #include <QMainWindow>  #include <QUiLoader> @@ -71,6 +76,7 @@ class Xml;  class MidiController; +  //---------------------------------------------------------  //   Plugin  //--------------------------------------------------------- @@ -119,7 +125,7 @@ class Plugin {        unsigned long id() const                     { return _uniqueID; }        QString maker() const                        { return _maker; }        QString copyright() const                    { return _copyright; } -      QString lib(bool complete = true)            { return complete ? fi.completeBaseName() : fi.baseName(); } // ddskrjo const +      QString lib(bool complete = true) const      { return complete ? fi.completeBaseName() : fi.baseName(); } // ddskrjo const        QString dirPath(bool complete = true) const  { return complete ? fi.absolutePath() : fi.path(); }        QString filePath() const                     { return fi.filePath(); }        QString fileName() const                     { return fi.fileName(); } @@ -188,6 +194,22 @@ class Plugin {  typedef std::list<Plugin>::iterator iPlugin; + +class PluginGroups : public QMap< QPair<QString, QString>, QSet<int> > +{ +  public: +    QSet<int>& get(QString a, QString b) { return (*this)[(QPair<QString,QString>(a,b))]; } +    QSet<int>& get(const Plugin& p) { return (*this)[(QPair<QString,QString>(p.lib(),p.label()))]; } +     +    void shift_left(int first, int last); +    void shift_right(int first, int last); +    void erase(int index); +   +  private: +    void replace_group(int old, int now); +}; + +  //---------------------------------------------------------  //   PluginList  //--------------------------------------------------------- @@ -529,6 +551,10 @@ class PluginGui : public QMainWindow {        void updateValues();        }; + + + +  //---------------------------------------------------------  //   PluginDialog  //--------------------------------------------------------- @@ -538,14 +564,6 @@ enum { SEL_SM, SEL_S, SEL_M, SEL_ALL };  class PluginDialog : public QDialog {        Q_OBJECT -      QTreeWidget* pList; -      QRadioButton* allPlug; -      QRadioButton* onlyM; -      QRadioButton* onlyS; -      QRadioButton* onlySM; -      QPushButton *okB; -      void saveSettings(); -     public:        PluginDialog(QWidget* parent=0);        static MusECore::Plugin* getPlugin(QWidget* parent); @@ -554,25 +572,56 @@ class PluginDialog : public QDialog {     public slots:        void accept();        void reject(); -      void fillPlugs(QAbstractButton*); -      void fillPlugs();     private slots:        void enableOkB(); +      void pluginTypeSelectionChanged(QAbstractButton*); +      void tabChanged(int); +      void tabMoved(int,int); +      void fillPlugs(); +       +      void newGroup(); +      void delGroup(); +      void renameGroup(); +      void plistContextMenu(const QPoint&); +      void groupMenuEntryToggled(int i);     private: -      QComboBox *sortBox; +      QComboBox* sortBox; +      QTabBar* tabBar; +      QTreeWidget* pList; +      QRadioButton* allPlug; +      QRadioButton* onlyM; +      QRadioButton* onlyS; +      QRadioButton* onlySM; +      QPushButton *okB; +       +      QAction* newGroupAction; +      QAction* delGroupAction; +      QAction* renGroupAction; +       +       +      void saveSettings(); +        static int selectedPlugType; +      static int selectedGroup; // 0 means "show all"        static QStringList sortItems;        static QRect geometrySave;        static QByteArray listSave; -      }; +       +      QSet<int>* group_info; //holds the group-set of the plugin which shall be affected by the plistContextMenu. +};  }  namespace MusEGlobal {  extern MusECore::PluginList plugins; +extern MusECore::PluginGroups plugin_groups; +extern QList<QString> plugin_group_names; + +void writePluginGroupConfiguration(int level, MusECore::Xml& xml); +void readPluginGroupConfiguration(MusECore::Xml& xml);  }  #endif  | 
