Skip to content

Commit

Permalink
Merge pull request #590 from GriffinRichards/update-promoter
Browse files Browse the repository at this point in the history
Add update promoter
  • Loading branch information
GriffinRichards authored Feb 12, 2024
2 parents a960456 + 73b5c05 commit b228c4e
Show file tree
Hide file tree
Showing 18 changed files with 782 additions and 50 deletions.
3 changes: 0 additions & 3 deletions forms/aboutporymap.ui
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,6 @@
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>Version 5.3.0 - January 15th, 2024</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
Expand Down
19 changes: 14 additions & 5 deletions forms/mainwindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -1715,7 +1715,7 @@
<x>0</x>
<y>0</y>
<width>100</width>
<height>30</height>
<height>16</height>
</rect>
</property>
<property name="sizePolicy">
Expand Down Expand Up @@ -1809,7 +1809,7 @@
<x>0</x>
<y>0</y>
<width>100</width>
<height>30</height>
<height>16</height>
</rect>
</property>
<property name="sizePolicy">
Expand Down Expand Up @@ -1903,7 +1903,7 @@
<x>0</x>
<y>0</y>
<width>100</width>
<height>30</height>
<height>16</height>
</rect>
</property>
<property name="sizePolicy">
Expand Down Expand Up @@ -2003,7 +2003,7 @@
<x>0</x>
<y>0</y>
<width>100</width>
<height>30</height>
<height>16</height>
</rect>
</property>
<property name="sizePolicy">
Expand Down Expand Up @@ -2097,7 +2097,7 @@
<x>0</x>
<y>0</y>
<width>100</width>
<height>30</height>
<height>16</height>
</rect>
</property>
<property name="sizePolicy">
Expand Down Expand Up @@ -3112,6 +3112,7 @@
<addaction name="actionAbout_Porymap"/>
<addaction name="actionOpen_Log_File"/>
<addaction name="actionOpen_Config_Folder"/>
<addaction name="actionCheck_for_Updates"/>
</widget>
<widget class="QMenu" name="menuOptions">
<property name="title">
Expand Down Expand Up @@ -3406,6 +3407,14 @@
<string>Custom Scripts...</string>
</property>
</action>
<action name="actionCheck_for_Updates">
<property name="text">
<string>Check for Updates...</string>
</property>
<property name="menuRole">
<enum>QAction::ApplicationSpecificRole</enum>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
Expand Down
16 changes: 16 additions & 0 deletions forms/preferenceeditor.ui
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,34 @@
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QCheckBox" name="checkBox_MonitorProjectFiles">
<property name="toolTip">
<string>If checked, a prompt to reload your project will appear if relevant project files are edited</string>
</property>
<property name="text">
<string>Monitor project files</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_OpenRecentProject">
<property name="toolTip">
<string>If checked, Porymap will automatically open your most recently opened project on startup</string>
</property>
<property name="text">
<string>Open recent project on launch</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_CheckForUpdates">
<property name="toolTip">
<string>If checked, Porymap will automatically alert you on startup if a new release is available</string>
</property>
<property name="text">
<string>Automatically check for updates</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
Expand Down
104 changes: 104 additions & 0 deletions forms/updatepromoter.ui
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>UpdatePromoter</class>
<widget class="QDialog" name="UpdatePromoter">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>592</width>
<height>484</height>
</rect>
</property>
<property name="windowTitle">
<string>Porymap Version Update</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label_Status">
<property name="text">
<string/>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_Warning">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:13pt; color:#d7000c;&quot;&gt;WARNING: &lt;/span&gt;&lt;span style=&quot; font-weight:400;&quot;&gt;Updating Porymap may require you to update your projects. See &quot;Breaking Changes&quot; in the Changelog for details.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_Changelog">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QTextBrowser" name="text_Changelog">
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_StopAlerts">
<property name="text">
<string>Do not alert me about new updates</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Close|QDialogButtonBox::Retry</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
21 changes: 21 additions & 0 deletions include/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,14 @@
#include <QSize>
#include <QKeySequence>
#include <QMultiMap>
#include <QDateTime>
#include <QUrl>
#include <QVersionNumber>

#include "events.h"

static const QVersionNumber porymapVersion = QVersionNumber::fromString(PORYMAP_VERSION);

// In both versions the default new map border is a generic tree
#define DEFAULT_BORDER_RSE (QList<uint16_t>{0x1D4, 0x1D5, 0x1DC, 0x1DD})
#define DEFAULT_BORDER_FRLG (QList<uint16_t>{0x14, 0x15, 0x1C, 0x1D})
Expand Down Expand Up @@ -74,6 +79,10 @@ class PorymapConfig: public KeyValueConfigBase
this->paletteEditorBitDepth = 24;
this->projectSettingsTab = 0;
this->warpBehaviorWarningDisabled = false;
this->checkForUpdates = true;
this->lastUpdateCheckTime = QDateTime();
this->lastUpdateCheckVersion = porymapVersion;
this->rateLimitTimes.clear();
}
void addRecentProject(QString project);
void setRecentProjects(QStringList projects);
Expand Down Expand Up @@ -105,6 +114,10 @@ class PorymapConfig: public KeyValueConfigBase
void setPaletteEditorBitDepth(int bitDepth);
void setProjectSettingsTab(int tab);
void setWarpBehaviorWarningDisabled(bool disabled);
void setCheckForUpdates(bool enabled);
void setLastUpdateCheckTime(QDateTime time);
void setLastUpdateCheckVersion(QVersionNumber version);
void setRateLimitTimes(QMap<QUrl, QDateTime> map);
QString getRecentProject();
QStringList getRecentProjects();
bool getReopenOnLaunch();
Expand Down Expand Up @@ -135,6 +148,10 @@ class PorymapConfig: public KeyValueConfigBase
int getPaletteEditorBitDepth();
int getProjectSettingsTab();
bool getWarpBehaviorWarningDisabled();
bool getCheckForUpdates();
QDateTime getLastUpdateCheckTime();
QVersionNumber getLastUpdateCheckVersion();
QMap<QUrl, QDateTime> getRateLimitTimes();
protected:
virtual QString getConfigFilepath() override;
virtual void parseConfigKeyValue(QString key, QString value) override;
Expand Down Expand Up @@ -183,6 +200,10 @@ class PorymapConfig: public KeyValueConfigBase
int paletteEditorBitDepth;
int projectSettingsTab;
bool warpBehaviorWarningDisabled;
bool checkForUpdates;
QDateTime lastUpdateCheckTime;
QVersionNumber lastUpdateCheckVersion;
QMap<QUrl, QDateTime> rateLimitTimes;
};

extern PorymapConfig porymapConfig;
Expand Down
87 changes: 87 additions & 0 deletions include/core/network.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#ifndef NETWORK_H
#define NETWORK_H

/*
The two classes defined here provide a simplified interface for Qt's network classes QNetworkAccessManager and QNetworkReply.
With the Qt classes, the workflow for a GET is roughly: generate a QNetworkRequest, give this request to QNetworkAccessManager::get,
connect the returned object to QNetworkReply::finished, and in the slot of that connection handle the various HTTP headers and attributes,
then manage errors or process the webpage's body.
These classes handle generating the QNetworkRequest with a given URL and manage the HTTP headers in the reply. They will automatically
respect rate limits and return cached data if the webpage hasn't changed since previous requests. Instead of interacting with a QNetworkReply,
callers interact with a simplified NetworkReplyData.
Example that logs Porymap's description on GitHub:
NetworkAccessManager * manager = new NetworkAccessManager(this);
NetworkReplyData * reply = manager->get("https://api.github.com/repos/huderlem/porymap");
connect(reply, &NetworkReplyData::finished, [reply] () {
if (!reply->errorString().isEmpty()) {
logError(QString("Failed to read description: %1").arg(reply->errorString()));
} else {
auto webpage = QJsonDocument::fromJson(reply->body());
logInfo(QString("Porymap: %1").arg(webpage["description"].toString()));
}
reply->deleteLater();
});
*/

#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QDateTime>

class NetworkReplyData : public QObject
{
Q_OBJECT

public:
QUrl url() const { return m_url; }
QUrl nextUrl() const { return m_nextUrl; }
QByteArray body() const { return m_body; }
QString errorString() const { return m_error; }
QDateTime retryAfter() const { return m_retryAfter; }
bool isFinished() const { return m_finished; }

friend class NetworkAccessManager;

private:
QUrl m_url;
QUrl m_nextUrl;
QByteArray m_body;
QString m_error;
QDateTime m_retryAfter;
bool m_finished;

void finish() {
m_finished = true;
emit finished();
};

signals:
void finished();
};

class NetworkAccessManager : public QNetworkAccessManager
{
Q_OBJECT

public:
NetworkAccessManager(QObject * parent = nullptr);
~NetworkAccessManager();
NetworkReplyData * get(const QString &url);
NetworkReplyData * get(const QUrl &url);

private:
// For a more complex cache we could implement a QAbstractCache for the manager
struct CacheEntry {
QString eTag;
QByteArray data;
};
QMap<QUrl, CacheEntry*> cache;
QMap<QUrl, QDateTime> rateLimitTimes;
void processReply(QNetworkReply * reply, NetworkReplyData * data);
const QNetworkRequest getRequest(const QUrl &url);
};

#endif // NETWORK_H
6 changes: 6 additions & 0 deletions include/mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "preferenceeditor.h"
#include "projectsettingseditor.h"
#include "customscriptseditor.h"
#include "updatepromoter.h"



Expand Down Expand Up @@ -288,6 +289,7 @@ private slots:
void on_spinBox_SelectedCollision_valueChanged(int collision);
void on_actionRegion_Map_Editor_triggered();
void on_actionPreferences_triggered();
void on_actionCheck_for_Updates_triggered();
void togglePreferenceSpecificUi();
void on_actionProject_Settings_triggered();
void on_actionCustom_Scripts_triggered();
Expand All @@ -307,6 +309,8 @@ private slots:
QPointer<PreferenceEditor> preferenceEditor = nullptr;
QPointer<ProjectSettingsEditor> projectSettingsEditor = nullptr;
QPointer<CustomScriptsEditor> customScriptsEditor = nullptr;
QPointer<UpdatePromoter> updatePromoter = nullptr;
QPointer<NetworkAccessManager> networkAccessManager = nullptr;
FilterChildrenProxyModel *mapListProxyModel;
QStandardItemModel *mapListModel;
QList<QStandardItem*> *mapGroupItemsList;
Expand Down Expand Up @@ -397,6 +401,8 @@ private slots:
QObjectList shortcutableObjects() const;
void addCustomHeaderValue(QString key, QJsonValue value, bool isNew = false);
int insertTilesetLabel(QStringList * list, QString label);

void checkForUpdates(bool requestedByUser);
};

enum MapListUserRoles {
Expand Down
Loading

0 comments on commit b228c4e

Please sign in to comment.