1 /*
2  * Cantata
3  *
4  * Copyright (c) 2011-2020 Craig Drummond <craig.p.drummond@gmail.com>
5  *
6  * ----
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; see the file COPYING.  If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23 
24 #include "customactionssettings.h"
25 #include "customactions.h"
26 #include "support/messagebox.h"
27 #include "widgets/basicitemdelegate.h"
28 #include "widgets/icons.h"
29 #include "widgets/notelabel.h"
30 #include <QGridLayout>
31 #include <QFormLayout>
32 #include <QLabel>
33 #include <QSpacerItem>
34 #include <QPushButton>
35 #include <QHeaderView>
36 
CustomActionDialog(QWidget * p)37 CustomActionDialog::CustomActionDialog(QWidget *p)
38     : Dialog(p)
39 {
40     QWidget *widget=new QWidget(this);
41     QFormLayout *layout=new QFormLayout(widget);
42     nameEntry=new LineEdit(widget);
43     commandEntry=new LineEdit(widget);
44     nameEntry->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
45     commandEntry->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
46     layout->addRow(new QLabel(tr("Name:"), widget), nameEntry);
47     layout->addRow(new QLabel(tr("Command:"), widget), commandEntry);
48     layout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
49     NoteLabel *note=new NoteLabel(widget);
50     note->setText(tr("In the command line above, %f will be replaced with the file list and %d with the folder list. If neither are supplied, the the list of files will be appended to the command."));
51     layout->setWidget(2, QFormLayout::SpanningRole, note);
52     layout->setMargin(0);
53     setButtons(Dialog::Ok|Dialog::Cancel);
54     setMainWidget(widget);
55     setMinimumWidth(400);
56     ensurePolished();
57     adjustSize();
58 }
59 
create()60 bool CustomActionDialog::create()
61 {
62     setCaption(tr("Add New Command"));
63     nameEntry->setText(QString());
64     commandEntry->setText(QString());
65     return QDialog::Accepted==exec();
66 }
67 
edit(const QString & name,const QString & cmd)68 bool CustomActionDialog::edit(const QString &name, const QString &cmd)
69 {
70     setCaption(tr("Edit Command"));
71     nameEntry->setText(name);
72     commandEntry->setText(cmd);
73     return QDialog::Accepted==exec();
74 }
75 
setResizeMode(QHeaderView * hdr,int idx,QHeaderView::ResizeMode mode)76 static inline void setResizeMode(QHeaderView *hdr, int idx, QHeaderView::ResizeMode mode)
77 {
78     hdr->setSectionResizeMode(idx, mode);
79 }
80 
CustomActionsSettings(QWidget * parent)81 CustomActionsSettings::CustomActionsSettings(QWidget *parent)
82     : QWidget(parent)
83     , dlg(nullptr)
84 {
85     QGridLayout *layout=new QGridLayout(this);
86     layout->setMargin(0);
87     QLabel *label=new QLabel(tr("To have Cantata call external commands (e.g. to edit tags with another application), add an entry for the command below. When at least one command "
88                                   "command is defined, a 'Custom Actions' entry will be added to the context menus in the Library, Folders, and Playlists views."), this);
89     QFont f(Utils::smallFont(label->font()));
90     f.setItalic(true);
91     label->setFont(f);
92     label->setWordWrap(true);
93     layout->addWidget(label, 0, 0, 1, 2);
94     tree=new QTreeWidget(this);
95     add=new QPushButton(this);
96     edit=new QPushButton(this);
97     del=new QPushButton(this);
98     layout->addWidget(tree, 1, 0, 4, 1);
99     layout->addWidget(add, 1, 1, 1, 1);
100     layout->addWidget(edit, 2, 1, 1, 1);
101     layout->addWidget(del, 3, 1, 1, 1);
102     layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Fixed, QSizePolicy::MinimumExpanding), 4, 1);
103 
104     add->setText(tr("Add"));
105     edit->setText(tr("Edit"));
106     del->setText(tr("Remove"));
107     edit->setEnabled(false);
108     del->setEnabled(false);
109 
110     tree->setHeaderLabels(QStringList() << tr("Name") << tr("Command"));
111     tree->setAllColumnsShowFocus(true);
112     tree->setSelectionMode(QAbstractItemView::ExtendedSelection);
113     tree->setRootIsDecorated(false);
114     tree->setSortingEnabled(true);
115     setResizeMode(tree->header(), 0, QHeaderView::ResizeToContents);
116     tree->header()->setStretchLastSection(true);
117     tree->setAlternatingRowColors(false);
118     tree->setItemDelegate(new BasicItemDelegate(this));
119     connect(tree, SIGNAL(itemSelectionChanged()), this, SLOT(controlButtons()));
120     connect(add, SIGNAL(clicked()), SLOT(addCommand()));
121     connect(edit, SIGNAL(clicked()), SLOT(editCommand()));
122     connect(del, SIGNAL(clicked()), SLOT(delCommand()));
123 }
124 
~CustomActionsSettings()125 CustomActionsSettings::~CustomActionsSettings()
126 {
127 }
128 
controlButtons()129 void CustomActionsSettings::controlButtons()
130 {
131     int selCount=tree->selectedItems().count();
132     edit->setEnabled(1==selCount);
133     del->setEnabled(selCount>0);
134 }
135 
load()136 void CustomActionsSettings::load()
137 {
138     for (const CustomActions::Command &cmd: CustomActions::self()->commandList()) {
139         new QTreeWidgetItem(tree, QStringList() << cmd.name << cmd.cmd);
140     }
141 }
142 
save()143 void CustomActionsSettings::save()
144 {
145     QList<CustomActions::Command> commands;
146 
147     for (int i=0; i<tree->topLevelItemCount(); ++i) {
148         commands.append((CustomActions::Command(tree->topLevelItem(i)->text(0), tree->topLevelItem(i)->text(1))));
149     }
150     CustomActions::self()->set(commands);
151 }
152 
addCommand()153 void CustomActionsSettings::addCommand()
154 {
155     if (!dlg) {
156         dlg=new CustomActionDialog(this);
157     }
158     if (dlg->create() && !dlg->nameText().isEmpty() && !dlg->commandText().isEmpty()) {
159         new QTreeWidgetItem(tree, QStringList() << dlg->nameText() << dlg->commandText());
160     }
161 }
162 
editCommand()163 void CustomActionsSettings::editCommand()
164 {
165     QList<QTreeWidgetItem *> items=tree->selectedItems();
166 
167     if (1!=items.count()) {
168         return;
169     }
170     if (!dlg) {
171         dlg=new CustomActionDialog(this);
172     }
173     QTreeWidgetItem *item=items.at(0);
174     if (dlg->edit(item->text(0), item->text(1)) && !dlg->nameText().isEmpty() && !dlg->commandText().isEmpty()) {
175         item->setText(0, dlg->nameText());
176         item->setText(1, dlg->commandText());
177     }
178 }
179 
delCommand()180 void CustomActionsSettings::delCommand()
181 {
182     if (MessageBox::Yes==MessageBox::warningYesNo(this, tr("Remove the selected commands?"), QString(), GuiItem(tr("Remove")), StdGuiItem::cancel())) {
183         for (QTreeWidgetItem *i: tree->selectedItems()) {
184             delete i;
185         }
186     }
187 }
188 
189 #include "moc_customactionssettings.cpp"
190