249 lines
7.8 KiB
C++
249 lines
7.8 KiB
C++
/* 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 "config.h"
|
|
#include "installscriptdialog.h"
|
|
#include "scriptarchive.h"
|
|
#include "scriptdialog.h"
|
|
#include "scriptmanager.h"
|
|
#include "ui_scriptdialog.h"
|
|
#include "core/boundfuturewatcher.h"
|
|
#include "ui/iconloader.h"
|
|
|
|
#include <QFileDialog>
|
|
#include <QMessageBox>
|
|
#include <QPainter>
|
|
#include <QPushButton>
|
|
#include <QSettings>
|
|
#include <QtDebug>
|
|
|
|
const int ScriptDelegate::kIconSize = 64;
|
|
const int ScriptDelegate::kPadding = 6;
|
|
const int ScriptDelegate::kItemHeight = kIconSize + kPadding*2;
|
|
const int ScriptDelegate::kLinkSpacing = 10;
|
|
|
|
const char* ScriptDialog::kSettingsGroup = "ScriptDialog";
|
|
|
|
ScriptDelegate::ScriptDelegate(QObject* parent)
|
|
: QStyledItemDelegate(parent),
|
|
bold_metrics_(bold_)
|
|
{
|
|
bold_.setBold(true);
|
|
bold_metrics_ = QFontMetrics(bold_);
|
|
|
|
link_.setUnderline(true);
|
|
}
|
|
|
|
void ScriptDelegate::paint(
|
|
QPainter* p, const QStyleOptionViewItem& opt,
|
|
const QModelIndex& index) const {
|
|
// Draw the background
|
|
const QStyleOptionViewItemV3* vopt = qstyleoption_cast<const QStyleOptionViewItemV3*>(&opt);
|
|
const QWidget* widget = vopt->widget;
|
|
QStyle* style = widget->style() ? widget->style() : QApplication::style();
|
|
style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, p, widget);
|
|
|
|
// Get the data
|
|
QIcon icon = index.data(Qt::DecorationRole).value<QIcon>();
|
|
const QString title = index.data(Qt::DisplayRole).toString();
|
|
const QString description = index.data(ScriptManager::Role_Description).toString();
|
|
const bool is_enabled = index.data(ScriptManager::Role_IsEnabled).toBool();
|
|
|
|
// Calculate the geometry
|
|
QRect icon_rect(opt.rect.left() + kPadding, opt.rect.top() + kPadding,
|
|
kIconSize, kIconSize);
|
|
QRect title_rect(icon_rect.right() + kPadding, icon_rect.top(),
|
|
opt.rect.width() - icon_rect.width() - kPadding*3,
|
|
bold_metrics_.height());
|
|
QRect description_rect(title_rect.left(), title_rect.bottom(),
|
|
title_rect.width(), opt.rect.bottom() - kPadding - title_rect.bottom());
|
|
|
|
// Draw the icon
|
|
p->drawPixmap(icon_rect, icon.pixmap(kIconSize, is_enabled ? QIcon::Normal : QIcon::Disabled));
|
|
|
|
// Disabled items get greyed out
|
|
if (is_enabled) {
|
|
p->setPen(opt.palette.color(QPalette::Text));
|
|
} else {
|
|
const bool light = opt.palette.color(QPalette::Base).value() > 128;
|
|
const QColor color = opt.palette.color(QPalette::Dark);
|
|
p->setPen(light ? color.darker(150) : color.lighter(125));
|
|
}
|
|
|
|
// Draw the title
|
|
p->setFont(bold_);
|
|
p->drawText(title_rect, Qt::AlignLeft | Qt::AlignVCenter, title);
|
|
|
|
// Draw the description
|
|
p->setFont(opt.font);
|
|
p->drawText(description_rect, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, description);
|
|
}
|
|
|
|
QSize ScriptDelegate::sizeHint(const QStyleOptionViewItem&, const QModelIndex&) const {
|
|
return QSize(100, kItemHeight);
|
|
}
|
|
|
|
|
|
ScriptDialog::ScriptDialog(QWidget* parent)
|
|
: QDialog(parent),
|
|
ui_(new Ui_ScriptDialog),
|
|
manager_(NULL)
|
|
{
|
|
ui_->setupUi(this);
|
|
connect(ui_->enable, SIGNAL(clicked()), SLOT(Enable()));
|
|
connect(ui_->disable, SIGNAL(clicked()), SLOT(Disable()));
|
|
connect(ui_->settings, SIGNAL(clicked()), SLOT(Settings()));
|
|
connect(ui_->reload, SIGNAL(clicked()), SLOT(Reload()));
|
|
|
|
// Add a button to install a script from a file
|
|
QPushButton* install_button = new QPushButton(
|
|
IconLoader::Load("document-open"), tr("Install from file..."), this);
|
|
connect(install_button, SIGNAL(clicked()), SLOT(InstallFromFile()));
|
|
ui_->button_box->addButton(install_button, QDialogButtonBox::ActionRole);
|
|
|
|
// But disable it if we don't have libarchive
|
|
#ifndef HAVE_LIBARCHIVE
|
|
install_button->setEnabled(false);
|
|
#endif
|
|
|
|
// Start on the first tab
|
|
ui_->tab_widget->setCurrentIndex(0);
|
|
|
|
// Make the list pretty
|
|
ui_->list->setItemDelegate(new ScriptDelegate(this));
|
|
|
|
// Hide developer mode stuff by default
|
|
ui_->console->hide();
|
|
ui_->reload->hide();
|
|
|
|
// Make the dialog smaller
|
|
resize(width(), minimumSizeHint().height());
|
|
|
|
ui_->button_box->button(QDialogButtonBox::Close)->setShortcut(QKeySequence::Close);
|
|
|
|
ReloadSettings();
|
|
}
|
|
|
|
ScriptDialog::~ScriptDialog() {
|
|
delete ui_;
|
|
}
|
|
|
|
void ScriptDialog::SetManager(ScriptManager* manager) {
|
|
manager_ = manager;
|
|
ui_->list->setModel(manager);
|
|
|
|
connect(manager, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
|
|
SLOT(DataChanged(QModelIndex,QModelIndex)));
|
|
connect(manager, SIGNAL(LogLineAdded(QString)), SLOT(LogLineAdded(QString)));
|
|
connect(ui_->list->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
|
|
SLOT(CurrentChanged(QModelIndex)));
|
|
|
|
foreach (const QString& html, manager->log_lines()) {
|
|
LogLineAdded(html);
|
|
}
|
|
}
|
|
|
|
void ScriptDialog::CurrentChanged(const QModelIndex& index) {
|
|
if (!index.isValid()) {
|
|
ui_->enable->setEnabled(false);
|
|
ui_->disable->setEnabled(false);
|
|
ui_->settings->setEnabled(false);
|
|
ui_->reload->setEnabled(false);
|
|
return;
|
|
}
|
|
|
|
const bool is_enabled = index.data(ScriptManager::Role_IsEnabled).toBool();
|
|
ui_->enable->setEnabled(!is_enabled);
|
|
ui_->disable->setEnabled(is_enabled);
|
|
ui_->settings->setEnabled(is_enabled);
|
|
ui_->reload->setEnabled(is_enabled);
|
|
}
|
|
|
|
void ScriptDialog::DataChanged(const QModelIndex&, const QModelIndex&) {
|
|
CurrentChanged(ui_->list->currentIndex());
|
|
}
|
|
|
|
void ScriptDialog::Enable() {
|
|
manager_->Enable(ui_->list->currentIndex());
|
|
}
|
|
|
|
void ScriptDialog::Disable() {
|
|
manager_->Disable(ui_->list->currentIndex());
|
|
}
|
|
|
|
void ScriptDialog::Settings() {
|
|
manager_->ShowSettingsDialog(ui_->list->currentIndex());
|
|
}
|
|
|
|
void ScriptDialog::Reload() {
|
|
Disable();
|
|
Enable();
|
|
}
|
|
|
|
void ScriptDialog::LogLineAdded(const QString& html) {
|
|
ui_->console->append(html);
|
|
}
|
|
|
|
void ScriptDialog::ReloadSettings() {
|
|
QSettings s;
|
|
s.beginGroup(kSettingsGroup);
|
|
last_open_dir_ = s.value("last_open_dir", QDir::homePath()).toString();
|
|
}
|
|
|
|
void ScriptDialog::InstallFromFile() {
|
|
QString filename = QFileDialog::getOpenFileName(
|
|
this, tr("Install script file"), last_open_dir_,
|
|
tr("Clementine scripts") + " (*.tar.gz *.clem)");
|
|
if (filename.isEmpty())
|
|
return;
|
|
|
|
// Save this directory
|
|
last_open_dir_ = filename;
|
|
QSettings s;
|
|
s.beginGroup(kSettingsGroup);
|
|
s.setValue("last_open_dir", last_open_dir_);
|
|
|
|
// Try opening the archive. We do this in the background.
|
|
ScriptArchive* archive = new ScriptArchive(manager_);
|
|
QFuture<bool> future = archive->LoadFromFileAsync(filename);
|
|
|
|
BoundFutureWatcher<bool, ScriptArchive*>* watcher =
|
|
new BoundFutureWatcher<bool, ScriptArchive*>(archive);
|
|
watcher->setFuture(future);
|
|
|
|
connect(watcher, SIGNAL(finished()), SLOT(InstallFromFileLoaded()));
|
|
}
|
|
|
|
void ScriptDialog::InstallFromFileLoaded() {
|
|
BoundFutureWatcher<bool, ScriptArchive*>* watcher =
|
|
reinterpret_cast<BoundFutureWatcher<bool, ScriptArchive*>*>(sender());
|
|
watcher->deleteLater();
|
|
|
|
ScriptArchive* archive = watcher->data();
|
|
const bool success = watcher->result();
|
|
|
|
if (success) {
|
|
// The dialog will delete itself and the archive when it's done.
|
|
InstallScriptDialog* dialog = new InstallScriptDialog(archive, this);
|
|
dialog->show();
|
|
} else {
|
|
QMessageBox::warning(this, tr("Error opening script archive"),
|
|
tr("This is not a valid Clementine script file."), QMessageBox::Close);
|
|
delete archive;
|
|
}
|
|
}
|