diff --git a/src/plugins/GreaseMonkey/gm_downloader.cpp b/src/plugins/GreaseMonkey/gm_downloader.cpp index b202c8eaf..3bdbc7bfb 100644 --- a/src/plugins/GreaseMonkey/gm_downloader.cpp +++ b/src/plugins/GreaseMonkey/gm_downloader.cpp @@ -16,7 +16,6 @@ * along with this program. If not, see . * ============================================================ */ #include "gm_downloader.h" -#include "gm_addscriptdialog.h" #include "gm_manager.h" #include "gm_script.h" @@ -38,6 +37,11 @@ GM_Downloader::GM_Downloader(const QUrl &url, GM_Manager* manager) connect(m_reply, SIGNAL(finished()), this, SLOT(scriptDownloaded())); } +void GM_Downloader::updateScript(const QString &fileName) +{ + m_fileName = fileName; +} + void GM_Downloader::scriptDownloaded() { if (m_reply != qobject_cast(sender())) { @@ -52,13 +56,15 @@ void GM_Downloader::scriptDownloaded() const QByteArray response = QString::fromUtf8(m_reply->readAll()).toUtf8(); if (response.contains(QByteArray("// ==UserScript=="))) { - const QString filePath = QString("%1/%2").arg(m_manager->scriptsDirectory(), QzTools::getFileNameFromUrl(m_reply->url())); - m_fileName = QzTools::ensureUniqueFilename(filePath); - + if (m_fileName.isEmpty()) { + const QString filePath = QString("%1/%2").arg(m_manager->scriptsDirectory(), QzTools::getFileNameFromUrl(m_reply->url())); + m_fileName = QzTools::ensureUniqueFilename(filePath); + } QFile file(m_fileName); if (!file.open(QFile::WriteOnly)) { qWarning() << "GreaseMonkey: Cannot open file for writing" << m_fileName; + emit error(); deleteLater(); return; } @@ -91,6 +97,7 @@ void GM_Downloader::scriptDownloaded() void GM_Downloader::requireDownloaded() { if (m_reply != qobject_cast(sender())) { + emit error(); deleteLater(); return; } @@ -109,6 +116,7 @@ void GM_Downloader::requireDownloaded() if (!file.open(QFile::WriteOnly)) { qWarning() << "GreaseMonkey: Cannot open file for writing" << fileName; + emit error(); deleteLater(); return; } @@ -135,24 +143,7 @@ void GM_Downloader::downloadRequires() connect(m_reply, SIGNAL(finished()), this, SLOT(requireDownloaded())); } else { - bool deleteScript = true; - GM_Script* script = new GM_Script(m_manager, m_fileName); - - if (script->isValid()) { - if (!m_manager->containsScript(script->fullName())) { - GM_AddScriptDialog dialog(m_manager, script); - deleteScript = dialog.exec() != QDialog::Accepted; - } - else { - m_manager->showNotification(tr("'%1' is already installed").arg(script->name())); - } - } - - if (deleteScript) { - delete script; - QFile(m_fileName).remove(); - } - + emit finished(m_fileName); deleteLater(); } } diff --git a/src/plugins/GreaseMonkey/gm_downloader.h b/src/plugins/GreaseMonkey/gm_downloader.h index 31f79eed6..900f90072 100644 --- a/src/plugins/GreaseMonkey/gm_downloader.h +++ b/src/plugins/GreaseMonkey/gm_downloader.h @@ -32,6 +32,12 @@ class GM_Downloader : public QObject public: explicit GM_Downloader(const QUrl &url, GM_Manager* manager); + void updateScript(const QString& fileName); + +signals: + void finished(const QString& fileName); + void error(); + private slots: void scriptDownloaded(); void requireDownloaded(); diff --git a/src/plugins/GreaseMonkey/gm_manager.cpp b/src/plugins/GreaseMonkey/gm_manager.cpp index 1f0411b80..10117a861 100644 --- a/src/plugins/GreaseMonkey/gm_manager.cpp +++ b/src/plugins/GreaseMonkey/gm_manager.cpp @@ -20,6 +20,7 @@ #include "gm_downloader.h" #include "gm_icon.h" #include "gm_urlinterceptor.h" +#include "gm_addscriptdialog.h" #include "settings/gm_settings.h" #include "browserwindow.h" @@ -256,7 +257,25 @@ void GM_Manager::scriptChanged() void GM_Manager::doDownloadScript(const QUrl &url) { - new GM_Downloader(url, this); + GM_Downloader *downloader = new GM_Downloader(url, this); + connect(downloader, &GM_Downloader::finished, this, [=](const QString &fileName) { + bool deleteScript = true; + GM_Script *script = new GM_Script(this, fileName); + if (script->isValid()) { + if (!containsScript(script->fullName())) { + GM_AddScriptDialog dialog(this, script); + deleteScript = dialog.exec() != QDialog::Accepted; + } + else { + showNotification(tr("'%1' is already installed").arg(script->name())); + } + } + + if (deleteScript) { + delete script; + QFile(fileName).remove(); + } + }); } bool GM_Manager::canRunOnScheme(const QString &scheme) diff --git a/src/plugins/GreaseMonkey/gm_script.cpp b/src/plugins/GreaseMonkey/gm_script.cpp index d467babfc..1cd3b2bc3 100644 --- a/src/plugins/GreaseMonkey/gm_script.cpp +++ b/src/plugins/GreaseMonkey/gm_script.cpp @@ -17,9 +17,12 @@ * ============================================================ */ #include "gm_script.h" #include "gm_manager.h" +#include "gm_downloader.h" #include "qzregexp.h" #include "delayedfilewatcher.h" +#include "followredirectreply.h" +#include "mainapplication.h" #include #include @@ -36,6 +39,7 @@ GM_Script::GM_Script(GM_Manager* manager, const QString &filePath) , m_fileName(filePath) , m_enabled(true) , m_valid(false) + , m_updating(false) { parseScript(); @@ -148,6 +152,31 @@ QWebEngineScript GM_Script::webScript() const return script; } +bool GM_Script::isUpdating() +{ + return m_updating; +} + +void GM_Script::updateScript() +{ + if (!m_downloadUrl.isValid() || m_updating) + return; + + m_updating = true; + emit updatingChanged(m_updating); + + GM_Downloader *downloader = new GM_Downloader(m_downloadUrl, m_manager); + downloader->updateScript(m_fileName); + connect(downloader, &GM_Downloader::finished, this, [this]() { + m_updating = false; + emit updatingChanged(m_updating); + }); + connect(downloader, &GM_Downloader::error, this, [this]() { + m_updating = false; + emit updatingChanged(m_updating); + }); +} + void GM_Script::watchedFileChanged(const QString &file) { if (m_fileName == file) { @@ -254,6 +283,9 @@ void GM_Script::parseScript() m_version = value; } else if (key == QLatin1String("@updateURL")) { + m_updateUrl = QUrl(value); + } + else if (key == QLatin1String("@downloadURL")) { m_downloadUrl = QUrl(value); } else if (key == QLatin1String("@include") || key == QLatin1String("@match")) { @@ -276,12 +308,6 @@ void GM_Script::parseScript() m_startAt = DocumentIdle; } } - else if (key == QLatin1String("@downloadURL") && m_downloadUrl.isEmpty()) { - m_downloadUrl = QUrl(value); - } - else if (key == QLatin1String("@updateURL") && m_updateUrl.isEmpty()) { - m_updateUrl = QUrl(value); - } } if (m_include.isEmpty()) { diff --git a/src/plugins/GreaseMonkey/gm_script.h b/src/plugins/GreaseMonkey/gm_script.h index aa7ae2626..2075e1340 100644 --- a/src/plugins/GreaseMonkey/gm_script.h +++ b/src/plugins/GreaseMonkey/gm_script.h @@ -62,8 +62,12 @@ public: QWebEngineScript webScript() const; + bool isUpdating(); + void updateScript(); + signals: void scriptChanged(); + void updatingChanged(bool updating); private slots: void watchedFileChanged(const QString &file); @@ -91,6 +95,7 @@ private: QString m_fileName; bool m_enabled; bool m_valid; + bool m_updating; }; #endif // GM_SCRIPT_H diff --git a/src/plugins/GreaseMonkey/settings/gm_settings.cpp b/src/plugins/GreaseMonkey/settings/gm_settings.cpp index 09927eb32..63ac24bdd 100644 --- a/src/plugins/GreaseMonkey/settings/gm_settings.cpp +++ b/src/plugins/GreaseMonkey/settings/gm_settings.cpp @@ -38,6 +38,8 @@ GM_Settings::GM_Settings(GM_Manager* manager, QWidget* parent) connect(ui->listWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(showItemInfo(QListWidgetItem*))); + connect(ui->listWidget, SIGNAL(updateItemRequested(QListWidgetItem*)), + this, SLOT(updateItem(QListWidgetItem*))); connect(ui->listWidget, SIGNAL(removeItemRequested(QListWidgetItem*)), this, SLOT(removeItem(QListWidgetItem*))); connect(ui->openDirectory, SIGNAL(clicked()), @@ -69,6 +71,15 @@ void GM_Settings::showItemInfo(QListWidgetItem* item) dialog->open(); } +void GM_Settings::updateItem(QListWidgetItem* item) +{ + GM_Script *script = getScript(item); + if (!script) { + return; + } + script->updateScript(); +} + void GM_Settings::removeItem(QListWidgetItem* item) { GM_Script* script = getScript(item); @@ -148,6 +159,8 @@ void GM_Settings::loadScripts() item->setText(script->name()); item->setData(Qt::UserRole, script->version()); item->setData(Qt::UserRole + 1, script->description()); + item->setData(Qt::UserRole + 2, !script->downloadUrl().isEmpty()); + item->setData(Qt::UserRole + 3, script->isUpdating()); item->setFlags(item->flags() | Qt::ItemIsUserCheckable); item->setCheckState(script->isEnabled() ? Qt::Checked : Qt::Unchecked); diff --git a/src/plugins/GreaseMonkey/settings/gm_settings.h b/src/plugins/GreaseMonkey/settings/gm_settings.h index 519bc82b4..050ae5aab 100644 --- a/src/plugins/GreaseMonkey/settings/gm_settings.h +++ b/src/plugins/GreaseMonkey/settings/gm_settings.h @@ -40,6 +40,7 @@ public: private slots: void showItemInfo(QListWidgetItem* item); + void updateItem(QListWidgetItem* item); void removeItem(QListWidgetItem* item); void itemChanged(QListWidgetItem* item); diff --git a/src/plugins/GreaseMonkey/settings/gm_settingslistdelegate.cpp b/src/plugins/GreaseMonkey/settings/gm_settingslistdelegate.cpp index 5b1730f46..4d4f5fff2 100644 --- a/src/plugins/GreaseMonkey/settings/gm_settingslistdelegate.cpp +++ b/src/plugins/GreaseMonkey/settings/gm_settingslistdelegate.cpp @@ -29,6 +29,7 @@ GM_SettingsListDelegate::GM_SettingsListDelegate(QObject* parent) , m_padding(0) { m_removePixmap = IconProvider::standardIcon(QStyle::SP_DialogCloseButton).pixmap(16); + m_updateIcon = IconProvider::standardIcon(QStyle::SP_BrowserReload); } int GM_SettingsListDelegate::padding() const @@ -63,6 +64,8 @@ void GM_SettingsListDelegate::paint(QPainter* painter, const QStyleOptionViewIte int leftPosition = m_padding; int rightPosition = opt.rect.right() - m_padding - 16; // 16 for remove button + if (index.data(Qt::UserRole + 2).toBool()) + rightPosition -= m_padding + 16; // 16 for update button // Draw background style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, w); @@ -109,6 +112,16 @@ void GM_SettingsListDelegate::paint(QPainter* painter, const QStyleOptionViewIte painter->setFont(opt.font); style->drawItemText(painter, infoRect, Qt::TextSingleLine | Qt::AlignLeft, opt.palette, true, info, colorRole); + // Draw update button + if (index.data(Qt::UserRole + 2).toBool()) { + const int updateIconSize = 16; + const int updateIconYPos = center - (updateIconSize / 2); + const QPixmap updatePixmap = m_updateIcon.pixmap(16, index.data(Qt::UserRole + 3).toBool() ? QIcon::Disabled : QIcon::Normal); + QRect updateIconRect(rightPosition, updateIconYPos, updateIconSize, updateIconSize); + painter->drawPixmap(updateIconRect, updatePixmap); + rightPosition += m_padding + 16; + } + // Draw remove button const int removeIconSize = 16; const int removeIconYPos = center - (removeIconSize / 2); diff --git a/src/plugins/GreaseMonkey/settings/gm_settingslistdelegate.h b/src/plugins/GreaseMonkey/settings/gm_settingslistdelegate.h index 53f91be72..30668f408 100644 --- a/src/plugins/GreaseMonkey/settings/gm_settingslistdelegate.h +++ b/src/plugins/GreaseMonkey/settings/gm_settingslistdelegate.h @@ -32,6 +32,7 @@ public: private: QPixmap m_removePixmap; + QIcon m_updateIcon; mutable int m_rowHeight; mutable int m_padding; diff --git a/src/plugins/GreaseMonkey/settings/gm_settingslistwidget.cpp b/src/plugins/GreaseMonkey/settings/gm_settingslistwidget.cpp index 3baca0095..55a90ccaf 100644 --- a/src/plugins/GreaseMonkey/settings/gm_settingslistwidget.cpp +++ b/src/plugins/GreaseMonkey/settings/gm_settingslistwidget.cpp @@ -36,15 +36,18 @@ void GM_SettingsListWidget::mousePressEvent(QMouseEvent* event) return; } + if (containsUpdateIcon(event->pos())) { + emit updateItemRequested(itemAt(event->pos())); + return; + } + QListWidget::mousePressEvent(event); } void GM_SettingsListWidget::mouseDoubleClickEvent(QMouseEvent* event) { - if (containsRemoveIcon(event->pos())) { - emit removeItemRequested(itemAt(event->pos())); + if (containsRemoveIcon(event->pos()) || containsUpdateIcon(event->pos())) return; - } QListWidget::mouseDoubleClickEvent(event); } @@ -65,3 +68,19 @@ bool GM_SettingsListWidget::containsRemoveIcon(const QPoint &pos) const return removeIconRect.contains(pos); } + +bool GM_SettingsListWidget::containsUpdateIcon(const QPoint &pos) const +{ + QListWidgetItem *item = itemAt(pos); + if (!item || !item->data(Qt::UserRole + 2).toBool()) + return false; + + const QRect rect = visualItemRect(item); + const int updateIconPosition = rect.right() - m_delegate->padding() * 2 - 16 * 2; + const int center = rect.height() / 2 + rect.top(); + const int updateIconYPos = center - (16 / 2); + + QRect updateIconRect(updateIconPosition, updateIconYPos, 16, 16); + + return updateIconRect.contains(pos); +} diff --git a/src/plugins/GreaseMonkey/settings/gm_settingslistwidget.h b/src/plugins/GreaseMonkey/settings/gm_settingslistwidget.h index f70583408..d43598caa 100644 --- a/src/plugins/GreaseMonkey/settings/gm_settingslistwidget.h +++ b/src/plugins/GreaseMonkey/settings/gm_settingslistwidget.h @@ -30,11 +30,13 @@ public: signals: void removeItemRequested(QListWidgetItem* item); + void updateItemRequested(QListWidgetItem* item); public slots: private: bool containsRemoveIcon(const QPoint &pos) const; + bool containsUpdateIcon(const QPoint &pos) const; void mousePressEvent(QMouseEvent* event); void mouseDoubleClickEvent(QMouseEvent* event);