External tools now support parameters.

This commit is contained in:
Martin Rotter 2017-09-11 11:51:23 +02:00
parent 659dd7d05b
commit 5b97260104
9 changed files with 237 additions and 30 deletions

View File

@ -188,8 +188,7 @@ win32 {
} }
DISTFILES += resources/scripts/astyle/.astylerc \ DISTFILES += resources/scripts/astyle/.astylerc \
resources/scripts/uncrustify/uncrustify.cfg \ resources/scripts/uncrustify/uncrustify.cfg
resources/scripts/uncrustify/uncrustify.cfg
MOC_DIR = $$OUT_PWD/moc MOC_DIR = $$OUT_PWD/moc
RCC_DIR = $$OUT_PWD/rcc RCC_DIR = $$OUT_PWD/rcc
@ -340,7 +339,8 @@ HEADERS += src/core/feeddownloader.h \
src/core/messagesmodelsqllayer.h \ src/core/messagesmodelsqllayer.h \
src/gui/treeviewcolumnsmenu.h \ src/gui/treeviewcolumnsmenu.h \
src/services/abstract/labelsrootitem.h \ src/services/abstract/labelsrootitem.h \
src/services/abstract/label.h src/services/abstract/label.h \
src/miscellaneous/externaltool.h
SOURCES += src/core/feeddownloader.cpp \ SOURCES += src/core/feeddownloader.cpp \
src/core/feedsmodel.cpp \ src/core/feedsmodel.cpp \
@ -466,7 +466,8 @@ SOURCES += src/core/feeddownloader.cpp \
src/core/messagesmodelsqllayer.cpp \ src/core/messagesmodelsqllayer.cpp \
src/gui/treeviewcolumnsmenu.cpp \ src/gui/treeviewcolumnsmenu.cpp \
src/services/abstract/labelsrootitem.cpp \ src/services/abstract/labelsrootitem.cpp \
src/services/abstract/label.cpp src/services/abstract/label.cpp \
src/miscellaneous/externaltool.cpp
OBJECTIVE_SOURCES += src/miscellaneous/disablewindowtabbing.mm OBJECTIVE_SOURCES += src/miscellaneous/disablewindowtabbing.mm

View File

@ -84,6 +84,8 @@
#define GOOGLE_SUGGEST_URL "http://suggestqueries.google.com/complete/search?output=toolbar&hl=en&q=%1" #define GOOGLE_SUGGEST_URL "http://suggestqueries.google.com/complete/search?output=toolbar&hl=en&q=%1"
#define ENCRYPTION_FILE_NAME "key.private" #define ENCRYPTION_FILE_NAME "key.private"
#define RELOAD_MODEL_BORDER_NUM 10 #define RELOAD_MODEL_BORDER_NUM 10
#define EXTERNAL_TOOL_SEPARATOR "###"
#define EXTERNAL_TOOL_PARAM_SEPARATOR "|||"
#define MAX_ZOOM_FACTOR 5.0f #define MAX_ZOOM_FACTOR 5.0f
#define MIN_ZOOM_FACTOR 0.25f #define MIN_ZOOM_FACTOR 0.25f

View File

@ -24,6 +24,7 @@
#include "network-web/networkfactory.h" #include "network-web/networkfactory.h"
#include "network-web/webfactory.h" #include "network-web/webfactory.h"
#include "gui/dialogs/formmain.h" #include "gui/dialogs/formmain.h"
#include "miscellaneous/externaltool.h"
#include "gui/messagebox.h" #include "gui/messagebox.h"
#include "gui/treeviewcolumnsmenu.h" #include "gui/treeviewcolumnsmenu.h"
#include "gui/styleditemdelegatewithoutfocus.h" #include "gui/styleditemdelegatewithoutfocus.h"
@ -187,11 +188,12 @@ void MessagesView::initializeContextMenu() {
QMenu* menu = new QMenu(tr("Open with external tool"), m_contextMenu); QMenu* menu = new QMenu(tr("Open with external tool"), m_contextMenu);
menu->setIcon(qApp->icons()->fromTheme(QSL("document-open"))); menu->setIcon(qApp->icons()->fromTheme(QSL("document-open")));
foreach (const QString& tool, qApp->settings()->value(GROUP(Browser), SETTING(Browser::ExternalTools)).toStringList()) { foreach (const ExternalTool& tool, ExternalTool::toolsFromSettings()) {
QAction* act_tool = new QAction(QFileInfo(tool).fileName(), menu); QAction* act_tool = new QAction(QFileInfo(tool.executable()).fileName(), menu);
act_tool->setIcon(icon_provider.icon(tool)); act_tool->setIcon(icon_provider.icon(tool.executable()));
act_tool->setToolTip(tool); act_tool->setToolTip(tool.executable());
act_tool->setData(QVariant::fromValue(tool));
menu->addAction(act_tool); menu->addAction(act_tool);
connect(act_tool, &QAction::triggered, this, &MessagesView::openSelectedMessagesWithExternalTool); connect(act_tool, &QAction::triggered, this, &MessagesView::openSelectedMessagesWithExternalTool);
@ -510,13 +512,13 @@ void MessagesView::openSelectedMessagesWithExternalTool() {
QAction* sndr = qobject_cast<QAction*>(sender()); QAction* sndr = qobject_cast<QAction*>(sender());
if (sndr != nullptr) { if (sndr != nullptr) {
const QString& tool = sndr->toolTip(); auto tool = sndr->data().value<ExternalTool>();
foreach (const QModelIndex& index, selectionModel()->selectedRows()) { foreach (const QModelIndex& index, selectionModel()->selectedRows()) {
const QString& link = m_sourceModel->messageAt(m_proxyModel->mapToSource(index).row()).m_url; const QString& link = m_sourceModel->messageAt(m_proxyModel->mapToSource(index).row()).m_url;
if (!link.isEmpty()) { if (!link.isEmpty()) {
if (!QProcess::startDetached(tool, QStringList() << link)) { if (!QProcess::startDetached(tool.executable(), QStringList() << tool.parameters() << link)) {
qApp->showGuiMessage(tr("Cannot run external tool"), tr("External tool '%1' could not be started."), qApp->showGuiMessage(tr("Cannot run external tool"), tr("External tool '%1' could not be started."),
QSystemTrayIcon::Critical); QSystemTrayIcon::Critical);
} }

View File

@ -21,13 +21,15 @@
#include "miscellaneous/application.h" #include "miscellaneous/application.h"
#include "miscellaneous/textfactory.h" #include "miscellaneous/textfactory.h"
#include "gui/guiutilities.h" #include "gui/guiutilities.h"
#include "miscellaneous/externaltool.h"
#include <QNetworkProxy> #include <QNetworkProxy>
#include <QFileDialog> #include <QFileDialog>
#include <QInputDialog>
SettingsBrowserMail::SettingsBrowserMail(Settings* settings, QWidget* parent) SettingsBrowserMail::SettingsBrowserMail(Settings* settings, QWidget* parent)
: SettingsPanel(settings, parent), m_ui(new Ui::SettingsBrowserMail) { : SettingsPanel(settings, parent), m_ui(new Ui::SettingsBrowserMail) {
m_ui->setupUi(this); m_ui->setupUi(this);
GuiUtilities::setLabelAsNotice(*m_ui->label, false); GuiUtilities::setLabelAsNotice(*m_ui->label, false);
@ -41,6 +43,9 @@ SettingsBrowserMail::SettingsBrowserMail(Settings* settings, QWidget* parent)
connect(m_ui->m_checkOpenLinksInExternal, &QCheckBox::stateChanged, this, &SettingsBrowserMail::dirtifySettings); connect(m_ui->m_checkOpenLinksInExternal, &QCheckBox::stateChanged, this, &SettingsBrowserMail::dirtifySettings);
#endif #endif
m_ui->m_listTools->setHeaderLabels(QStringList() << tr("Executable") << tr("Parameters"));
m_ui->m_listTools->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
connect(m_ui->m_cmbProxyType, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, connect(m_ui->m_cmbProxyType, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
&SettingsBrowserMail::dirtifySettings); &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_txtProxyHost, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings); connect(m_ui->m_txtProxyHost, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings);
@ -66,8 +71,10 @@ SettingsBrowserMail::SettingsBrowserMail(Settings* settings, QWidget* parent)
connect(m_ui->m_btnDeleteTool, &QPushButton::clicked, this, &SettingsBrowserMail::dirtifySettings); connect(m_ui->m_btnDeleteTool, &QPushButton::clicked, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_btnAddTool, &QPushButton::clicked, this, &SettingsBrowserMail::addExternalTool); connect(m_ui->m_btnAddTool, &QPushButton::clicked, this, &SettingsBrowserMail::addExternalTool);
connect(m_ui->m_btnDeleteTool, &QPushButton::clicked, this, &SettingsBrowserMail::deleteSelectedExternalTool); connect(m_ui->m_btnDeleteTool, &QPushButton::clicked, this, &SettingsBrowserMail::deleteSelectedExternalTool);
connect(m_ui->m_listTools, &QListWidget::currentTextChanged, [this](const QString & current_text) { connect(m_ui->m_listTools, &QTreeWidget::currentItemChanged, [this](QTreeWidgetItem * current, QTreeWidgetItem * previous) {
m_ui->m_btnDeleteTool->setEnabled(!current_text.isEmpty()); Q_UNUSED(previous)
m_ui->m_btnDeleteTool->setEnabled(current != nullptr);
}); });
} }
@ -121,19 +128,23 @@ void SettingsBrowserMail::onProxyTypeChanged(int index) {
m_ui->m_lblProxyUsername->setEnabled(is_proxy_selected); m_ui->m_lblProxyUsername->setEnabled(is_proxy_selected);
} }
QStringList SettingsBrowserMail::externalTools() const { QList<ExternalTool> SettingsBrowserMail::externalTools() const {
QStringList list; QList<ExternalTool> list;
for (int i = 0; i < m_ui->m_listTools->count(); i++) { for (int i = 0; i < m_ui->m_listTools->topLevelItemCount(); i++) {
list.append(m_ui->m_listTools->item(i)->text()); list.append(m_ui->m_listTools->topLevelItem(i)->data(0, Qt::UserRole).value<ExternalTool>());
} }
return list; return list;
} }
void SettingsBrowserMail::setExternalTools(const QStringList& list) { void SettingsBrowserMail::setExternalTools(const QList<ExternalTool>& list) {
foreach (const QString& tool, list) { foreach (const ExternalTool& tool, list) {
m_ui->m_listTools->addItem(tool); QTreeWidgetItem* item = new QTreeWidgetItem(m_ui->m_listTools,
QStringList() << tool.executable() << tool.parameters());
item->setData(0, Qt::UserRole, QVariant::fromValue(tool));
m_ui->m_listTools->addTopLevelItem(item);
} }
} }
@ -194,7 +205,7 @@ void SettingsBrowserMail::loadSettings() {
m_ui->m_txtProxyPassword->setText(TextFactory::decrypt(settings()->value(GROUP(Proxy), SETTING(Proxy::Password)).toString())); m_ui->m_txtProxyPassword->setText(TextFactory::decrypt(settings()->value(GROUP(Proxy), SETTING(Proxy::Password)).toString()));
m_ui->m_spinProxyPort->setValue(settings()->value(GROUP(Proxy), SETTING(Proxy::Port)).toInt()); m_ui->m_spinProxyPort->setValue(settings()->value(GROUP(Proxy), SETTING(Proxy::Port)).toInt());
setExternalTools(settings()->value(GROUP(Browser), SETTING(Browser::ExternalTools)).toStringList()); setExternalTools(ExternalTool::toolsFromSettings());
onEndLoadSettings(); onEndLoadSettings();
} }
@ -220,7 +231,9 @@ void SettingsBrowserMail::saveSettings() {
settings()->setValue(GROUP(Proxy), Proxy::Password, TextFactory::encrypt(m_ui->m_txtProxyPassword->text())); settings()->setValue(GROUP(Proxy), Proxy::Password, TextFactory::encrypt(m_ui->m_txtProxyPassword->text()));
settings()->setValue(GROUP(Proxy), Proxy::Port, m_ui->m_spinProxyPort->value()); settings()->setValue(GROUP(Proxy), Proxy::Port, m_ui->m_spinProxyPort->value());
settings()->setValue(GROUP(Browser), Browser::ExternalTools, externalTools()); auto tools = externalTools();
ExternalTool::setToolsToSettings(tools);
// Reload settings for all network access managers. // Reload settings for all network access managers.
SilentNetworkAccessManager::instance()->loadSettings(); SilentNetworkAccessManager::instance()->loadSettings();
@ -239,12 +252,23 @@ void SettingsBrowserMail::addExternalTool() {
#endif #endif
if (!executable_file.isEmpty()) { if (!executable_file.isEmpty()) {
m_ui->m_listTools->addItem(QDir::toNativeSeparators(executable_file)); executable_file = QDir::toNativeSeparators(executable_file);
bool ok;
QString parameters = QInputDialog::getText(this, tr("Enter parameters"),
tr("Enter (optional) parameters separated by single space to send to executable when opening URLs."),
QLineEdit::Normal, QString(), &ok);
if (ok) {
QTreeWidgetItem* item = new QTreeWidgetItem(m_ui->m_listTools,
QStringList() << QDir::toNativeSeparators(executable_file) << parameters);
item->setData(0, Qt::UserRole, QVariant::fromValue(ExternalTool(executable_file, parameters.split(QSL(" ")))));
m_ui->m_listTools->addTopLevelItem(item);
}
} }
} }
void SettingsBrowserMail::deleteSelectedExternalTool() { void SettingsBrowserMail::deleteSelectedExternalTool() {
if (m_ui->m_listTools->currentRow() >= 0) { if (!m_ui->m_listTools->selectedItems().isEmpty()) {
m_ui->m_listTools->takeItem(m_ui->m_listTools->currentRow()); m_ui->m_listTools->takeTopLevelItem(m_ui->m_listTools->indexOfTopLevelItem(m_ui->m_listTools->selectedItems().first()));
} }
} }

View File

@ -20,6 +20,7 @@
#include "gui/settings/settingspanel.h" #include "gui/settings/settingspanel.h"
#include "miscellaneous/externaltool.h"
#include "ui_settingsbrowsermail.h" #include "ui_settingsbrowsermail.h"
@ -34,7 +35,7 @@ class SettingsBrowserMail : public SettingsPanel {
return tr("Web browser & e-mail & proxy"); return tr("Web browser & e-mail & proxy");
} }
void loadSettings(); void loadSettings();
void saveSettings(); void saveSettings();
private slots: private slots:
@ -48,8 +49,8 @@ class SettingsBrowserMail : public SettingsPanel {
void onProxyTypeChanged(int index); void onProxyTypeChanged(int index);
private: private:
QStringList externalTools() const; QList<ExternalTool> externalTools() const;
void setExternalTools(const QStringList& list); void setExternalTools(const QList<ExternalTool>& list);
Ui::SettingsBrowserMail* m_ui; Ui::SettingsBrowserMail* m_ui;
}; };

View File

@ -262,16 +262,30 @@
</widget> </widget>
</item> </item>
<item row="1" column="0" colspan="2"> <item row="1" column="0" colspan="2">
<widget class="QListWidget" name="m_listTools"> <widget class="QTreeWidget" name="m_listTools">
<property name="showDropIndicator" stdset="0"> <property name="showDropIndicator" stdset="0">
<bool>false</bool> <bool>false</bool>
</property> </property>
<property name="alternatingRowColors"> <property name="alternatingRowColors">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="uniformItemSizes"> <property name="indentation">
<number>0</number>
</property>
<property name="uniformRowHeights">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="itemsExpandable">
<bool>false</bool>
</property>
<property name="allColumnsShowFocus">
<bool>true</bool>
</property>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget> </widget>
</item> </item>
</layout> </layout>
@ -428,6 +442,29 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<tabstops>
<tabstop>m_txtProxyPassword</tabstop>
<tabstop>m_checkShowPassword</tabstop>
<tabstop>m_tabBrowserProxy</tabstop>
<tabstop>m_checkOpenLinksInExternal</tabstop>
<tabstop>m_grpCustomExternalBrowser</tabstop>
<tabstop>m_txtExternalBrowserExecutable</tabstop>
<tabstop>m_btnExternalBrowserExecutable</tabstop>
<tabstop>m_txtExternalBrowserArguments</tabstop>
<tabstop>m_cmbExternalBrowserPreset</tabstop>
<tabstop>m_grpCustomExternalEmail</tabstop>
<tabstop>m_txtExternalEmailExecutable</tabstop>
<tabstop>m_btnExternalEmailExecutable</tabstop>
<tabstop>m_txtExternalEmailArguments</tabstop>
<tabstop>m_cmbExternalEmailPreset</tabstop>
<tabstop>m_listTools</tabstop>
<tabstop>m_btnAddTool</tabstop>
<tabstop>m_btnDeleteTool</tabstop>
<tabstop>m_cmbProxyType</tabstop>
<tabstop>m_txtProxyHost</tabstop>
<tabstop>m_spinProxyPort</tabstop>
<tabstop>m_txtProxyUsername</tabstop>
</tabstops>
<resources/> <resources/>
<connections/> <connections/>
</ui> </ui>

View File

@ -26,6 +26,7 @@
ToolBarEditor::ToolBarEditor(QWidget* parent) ToolBarEditor::ToolBarEditor(QWidget* parent)
: QWidget(parent), m_ui(new Ui::ToolBarEditor) { : QWidget(parent), m_ui(new Ui::ToolBarEditor) {
m_ui->setupUi(this); m_ui->setupUi(this);
// Create connections. // Create connections.
connect(m_ui->m_btnInsertSeparator, &QToolButton::clicked, this, &ToolBarEditor::insertSeparator); connect(m_ui->m_btnInsertSeparator, &QToolButton::clicked, this, &ToolBarEditor::insertSeparator);
connect(m_ui->m_btnInsertSpacer, &QToolButton::clicked, this, &ToolBarEditor::insertSpacer); connect(m_ui->m_btnInsertSpacer, &QToolButton::clicked, this, &ToolBarEditor::insertSpacer);
@ -56,6 +57,7 @@ ToolBarEditor::~ToolBarEditor() {
void ToolBarEditor::loadFromToolBar(BaseBar* tool_bar) { void ToolBarEditor::loadFromToolBar(BaseBar* tool_bar) {
m_toolBar = tool_bar; m_toolBar = tool_bar;
QList<QAction*> activated_actions = m_toolBar->changeableActions(); QList<QAction*> activated_actions = m_toolBar->changeableActions();
QList<QAction*> available_actions = m_toolBar->availableActions(); QList<QAction*> available_actions = m_toolBar->availableActions();
loadEditor(activated_actions, available_actions); loadEditor(activated_actions, available_actions);

View File

@ -0,0 +1,91 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
// RSS Guard 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.
//
// RSS Guard 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 RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "miscellaneous/externaltool.h"
#include "definitions/definitions.h"
#include "miscellaneous/application.h"
#include "exceptions/applicationexception.h"
#include <QObject>
#include <QDir>
void ExternalTool::sanitizeParameters() {
m_executable = QDir::toNativeSeparators(m_executable);
m_parameters.removeDuplicates();
m_parameters.removeAll(QString());
}
ExternalTool::ExternalTool() {
}
ExternalTool::ExternalTool(const ExternalTool& other) : ExternalTool(other.executable(), other.parameters()) {
}
ExternalTool::ExternalTool(const QString& executable, const QStringList& parameters)
: m_executable(executable), m_parameters(parameters) {
sanitizeParameters();
}
QString ExternalTool::toString() {
sanitizeParameters();
return m_executable + EXTERNAL_TOOL_SEPARATOR + m_parameters.join(EXTERNAL_TOOL_PARAM_SEPARATOR);
}
QString ExternalTool::executable() const {
return m_executable;
}
QStringList ExternalTool::parameters() const {
return m_parameters;
}
ExternalTool ExternalTool::fromString(const QString& str) {
QStringList outer = str.split(EXTERNAL_TOOL_SEPARATOR);
if (outer.size() != 2) {
throw ApplicationException(QObject::tr("Passed external tool representation is not valid."));
}
else {
const QString executable = outer.at(0);
const QStringList parameters = outer.at(1).split(EXTERNAL_TOOL_PARAM_SEPARATOR);
return ExternalTool(executable, parameters);
}
}
QList<ExternalTool> ExternalTool::toolsFromSettings() {
QStringList tools_encoded = qApp->settings()->value(GROUP(Browser), SETTING(Browser::ExternalTools)).toStringList();
QList<ExternalTool> tools;
foreach (const QString& tool_encoded, tools_encoded) {
tools.append(ExternalTool::fromString(tool_encoded));
}
return tools;
}
void ExternalTool::setToolsToSettings(QList<ExternalTool>& tools) {
QStringList encode;
foreach (ExternalTool tool, tools) {
encode.append(tool.toString());
}
qApp->settings()->setValue(GROUP(Browser), Browser::ExternalTools, encode);
}

View File

@ -0,0 +1,47 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
// RSS Guard 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.
//
// RSS Guard 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 RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef EXTERNALTOOL_H
#define EXTERNALTOOL_H
#include <QStringList>
#include <QMetaType>
class ExternalTool {
public:
explicit ExternalTool();
ExternalTool(const ExternalTool& other);
explicit ExternalTool(const QString& executable, const QStringList& parameters);
QString toString();
QString executable() const;
QStringList parameters() const;
static ExternalTool fromString(const QString& str);
static QList<ExternalTool> toolsFromSettings();
static void setToolsToSettings(QList<ExternalTool>& tools);
private:
QString m_executable;
QStringList m_parameters;
void sanitizeParameters();
};
Q_DECLARE_METATYPE(ExternalTool)
#endif // EXTERNALTOOL_H