Add a Manager dialog for saved groupings

- Right now only allows removal
- Could also add support for adding/reordering, but it's not clear
  that's necessary
- Triggered from the Display options menu, could also be added to Tools
  toolbar menu
This commit is contained in:
Nick Lanham 2015-12-11 19:49:51 -08:00
parent 862b9a8635
commit 2ab1c2fe36
7 changed files with 374 additions and 3 deletions

View File

@ -211,6 +211,7 @@ set(SOURCES
library/libraryview.cpp
library/libraryviewcontainer.cpp
library/librarywatcher.cpp
library/savedgroupingmanager.cpp
library/sqlrow.cpp
musicbrainz/acoustidclient.cpp
@ -512,7 +513,8 @@ set(HEADERS
library/libraryview.h
library/libraryviewcontainer.h
library/librarywatcher.h
library/savedgroupingmanager.h
musicbrainz/acoustidclient.h
musicbrainz/musicbrainzclient.h
musicbrainz/tagfetcher.h
@ -699,6 +701,7 @@ set(UI
library/libraryfilterwidget.ui
library/librarysettingspage.ui
library/libraryviewcontainer.ui
library/savedgroupingmanager.ui
playlist/dynamicplaylistcontrols.ui
playlist/playlistcontainer.ui

View File

@ -102,6 +102,8 @@ LibraryFilterWidget::LibraryFilterWidget(QWidget* parent)
SLOT(GroupByClicked(QAction*)));
connect(ui_->save_grouping, SIGNAL(triggered()), this, SLOT(SaveGroupBy()));
connect(ui_->manage_groupings, SIGNAL(triggered()), this,
SLOT(ShowGroupingManager()));
// Library config menu
library_menu_ = new QMenu(tr("Display options"), this);
@ -109,6 +111,7 @@ LibraryFilterWidget::LibraryFilterWidget(QWidget* parent)
library_menu_->addMenu(filter_age_menu_);
library_menu_->addMenu(group_by_menu_);
library_menu_->addAction(ui_->save_grouping);
library_menu_->addAction(ui_->manage_groupings);
library_menu_->addSeparator();
ui_->options->setMenu(library_menu_);
@ -120,7 +123,7 @@ LibraryFilterWidget::~LibraryFilterWidget() { delete ui_; }
void LibraryFilterWidget::UpdateGroupByActions() {
if (group_by_group_) {
disconnect(group_by_group_,0,0,0);
disconnect(group_by_group_, 0, 0, 0);
delete group_by_group_;
}
@ -208,6 +211,15 @@ void LibraryFilterWidget::SaveGroupBy() {
}
}
void LibraryFilterWidget::ShowGroupingManager() {
if (!groupings_manager_) {
groupings_manager_.reset(new SavedGroupingManager);
}
groupings_manager_->SetFilter(this);
groupings_manager_->UpdateModel();
groupings_manager_->show();
}
void LibraryFilterWidget::FocusOnFilter(QKeyEvent* event) {
ui_->filter->setFocus();
QApplication::sendEvent(ui_->filter, event);
@ -273,7 +285,8 @@ void LibraryFilterWidget::GroupingChanged(const LibraryModel::Grouping& g) {
CheckCurrentGrouping(g);
}
void LibraryFilterWidget::CheckCurrentGrouping(const LibraryModel::Grouping& g) {
void LibraryFilterWidget::CheckCurrentGrouping(
const LibraryModel::Grouping& g) {
for (QAction* action : group_by_group_->actions()) {
if (action->property("group_by").isNull()) continue;

View File

@ -23,6 +23,7 @@
#include <QWidget>
#include "librarymodel.h"
#include "savedgroupingmanager.h"
class GroupByDialog;
class SettingsDialog;
@ -86,6 +87,7 @@ signals:
void GroupingChanged(const LibraryModel::Grouping& g);
void GroupByClicked(QAction* action);
void SaveGroupBy();
void ShowGroupingManager();
void FilterTextChanged(const QString& text);
void FilterDelayTimeout();
@ -100,6 +102,7 @@ signals:
LibraryModel* model_;
std::unique_ptr<GroupByDialog> group_by_dialog_;
std::unique_ptr<SavedGroupingManager> groupings_manager_;
SettingsDialog* settings_dialog_;
QMenu* filter_age_menu_;

View File

@ -103,6 +103,11 @@
<string>Save current grouping</string>
</property>
</action>
<action name="manage_groupings">
<property name="text">
<string>Manage saved groupings</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>

View File

@ -0,0 +1,152 @@
/* This file is part of Clementine.
Copyright 2010, David Sansome <me@davidsansome.com>
Clementine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Clementine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "libraryfilterwidget.h"
#include "librarymodel.h"
#include "savedgroupingmanager.h"
#include "ui_savedgroupingmanager.h"
#include "ui/iconloader.h"
#include <QKeySequence>
#include <QList>
#include <QSettings>
#include <QStandardItem>
SavedGroupingManager::SavedGroupingManager(QWidget* parent)
: QDialog(parent),
ui_(new Ui_SavedGroupingManager),
model_(new QStandardItemModel(0, 4, this)) {
ui_->setupUi(this);
model_->setHorizontalHeaderItem(0, new QStandardItem(tr("Name")));
model_->setHorizontalHeaderItem(1, new QStandardItem(tr("First level")));
model_->setHorizontalHeaderItem(2, new QStandardItem(tr("Second Level")));
model_->setHorizontalHeaderItem(3, new QStandardItem(tr("Third Level")));
ui_->list->setModel(model_);
ui_->remove->setIcon(IconLoader::Load("edit-delete", IconLoader::Base));
ui_->remove->setEnabled(false);
ui_->remove->setShortcut(QKeySequence::Delete);
connect(ui_->list->selectionModel(),
SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
SLOT(UpdateButtonState()));
connect(ui_->remove, SIGNAL(clicked()), SLOT(Remove()));
}
SavedGroupingManager::~SavedGroupingManager() {
delete ui_;
delete model_;
}
QString SavedGroupingManager::GroupByToString(const LibraryModel::GroupBy& g) {
switch (g) {
case LibraryModel::GroupBy_None: {
return tr("None");
}
case LibraryModel::GroupBy_Artist: {
return tr("Artist");
}
case LibraryModel::GroupBy_Album: {
return tr("Album");
}
case LibraryModel::GroupBy_YearAlbum: {
return tr("Year - Album");
}
case LibraryModel::GroupBy_Year: {
return tr("Year");
}
case LibraryModel::GroupBy_Composer: {
return tr("Composer");
}
case LibraryModel::GroupBy_Genre: {
return tr("Genre");
}
case LibraryModel::GroupBy_AlbumArtist: {
return tr("Album artist");
}
case LibraryModel::GroupBy_FileType: {
return tr("File type");
}
case LibraryModel::GroupBy_Performer: {
return tr("Performer");
}
case LibraryModel::GroupBy_Grouping: {
return tr("Grouping");
}
case LibraryModel::GroupBy_Bitrate: {
return tr("Bitrate");
}
case LibraryModel::GroupBy_Disc: {
return tr("Disc");
}
case LibraryModel::GroupBy_OriginalYearAlbum: {
return tr("Original year - Album");
}
case LibraryModel::GroupBy_OriginalYear: {
return tr("Original year");
}
default: { return tr("Unknown"); }
}
}
void SavedGroupingManager::UpdateModel() {
model_->setRowCount(0); // don't use clear, it deletes headers
QSettings s;
s.beginGroup(LibraryModel::kSavedGroupingsSettingsGroup);
QStringList saved = s.childKeys();
for (int i = 0; i < saved.size(); ++i) {
QByteArray bytes = s.value(saved.at(i)).toByteArray();
QDataStream ds(&bytes, QIODevice::ReadOnly);
LibraryModel::Grouping g;
ds >> g;
QList<QStandardItem*> list;
list << new QStandardItem(saved.at(i))
<< new QStandardItem(GroupByToString(g.first))
<< new QStandardItem(GroupByToString(g.second))
<< new QStandardItem(GroupByToString(g.third));
model_->appendRow(list);
}
}
void SavedGroupingManager::Remove() {
if (ui_->list->selectionModel()->hasSelection()) {
QSettings s;
s.beginGroup(LibraryModel::kSavedGroupingsSettingsGroup);
for (const QModelIndex& index :
ui_->list->selectionModel()->selectedRows()) {
if (index.isValid()) {
qLog(Debug) << "Remove saved grouping: "
<< model_->item(index.row(), 0)->text();
s.remove(model_->item(index.row(), 0)->text());
}
}
}
UpdateModel();
filter_->UpdateGroupByActions();
}
void SavedGroupingManager::UpdateButtonState() {
if (ui_->list->selectionModel()->hasSelection()) {
const QModelIndex current = ui_->list->selectionModel()->currentIndex();
ui_->remove->setEnabled(current.isValid());
} else {
ui_->remove->setEnabled(false);
}
}

View File

@ -0,0 +1,51 @@
/* This file is part of Clementine.
Copyright 2015, Nick Lanham <nick@afternight.org>
Clementine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Clementine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SAVEDGROUPINGMANAGER_H
#define SAVEDGROUPINGMANAGER_H
#include <QDialog>
#include <QStandardItemModel>
#include "librarymodel.h"
class Ui_SavedGroupingManager;
class LibraryFilterWidget;
class SavedGroupingManager : public QDialog {
Q_OBJECT
public:
SavedGroupingManager(QWidget* parent = nullptr);
~SavedGroupingManager();
void UpdateModel();
void SetFilter(LibraryFilterWidget* filter) { filter_ = filter; }
static QString GroupByToString(const LibraryModel::GroupBy& g);
private slots:
void UpdateButtonState();
void Remove();
private:
Ui_SavedGroupingManager* ui_;
QStandardItemModel* model_;
LibraryFilterWidget* filter_;
};
#endif // SAVEDGROUPINGMANAGER_H

View File

@ -0,0 +1,144 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SavedGroupingManager</class>
<widget class="QDialog" name="SavedGroupingManager">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>582</width>
<height>363</height>
</rect>
</property>
<property name="windowTitle">
<string>Saved Grouping Manager</string>
</property>
<property name="windowIcon">
<iconset resource="../../data/data.qrc">
<normaloff>:/icon.png</normaloff>:/icon.png</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QTreeView" name="list">
<property name="acceptDrops">
<bool>true</bool>
</property>
<property name="showDropIndicator" stdset="0">
<bool>true</bool>
</property>
<property name="dragEnabled">
<bool>true</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::DragDrop</enum>
</property>
<property name="defaultDropAction">
<enum>Qt::MoveAction</enum>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="rootIsDecorated">
<bool>false</bool>
</property>
<attribute name="headerVisible">
<bool>true</bool>
</attribute>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="remove">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Remove</string>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="shortcut">
<string>Ctrl+Up</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../../data/data.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>SavedGroupingManager</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>SavedGroupingManager</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>