First version of automatic updates for Mac

felipesanches-svg
Marius Kintel 2013-02-05 00:36:25 -05:00
parent 03be37d16b
commit fa00547507
21 changed files with 463 additions and 27 deletions

18
appcast-snapshots.xml.in Normal file
View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle">
<channel>
<title>OpenSCAD Development Snapshots</title>
<link>http://openscad.org/appcast-snapshots.xml</link>
<language>en</language>
<item>
<title>OpenSCAD @VERSION@</title>
<pubDate>@VERSIONDATE@</pubDate>
<sparkle:releaseNotesLink>https://raw.github.com/openscad/openscad/master/RELEASE_NOTES</sparkle:releaseNotesLink>
<enclosure url="https://openscad.googlecode.com/files/OpenSCAD-@VERSION@.dmg"
sparkle:version="@VERSIONDATE@"
sparkle:shortVersionString="@VERSION@"
length="@FILESIZE@"
type="application/octet-stream"/>
</item>
</channel>
</rss>

18
appcast.xml.in Normal file
View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle">
<channel>
<title>OpenSCAD Updates</title>
<link>http://openscad.org/appcast.xml</link>
<language>en</language>
<item>
<title>OpenSCAD @VERSION@</title>
<pubDate>@VERSIONDATE@</pubDate>
<sparkle:releaseNotesLink>https://raw.github.com/openscad/openscad/openscad-@VERSION@/RELEASE_NOTES</sparkle:releaseNotesLink>
<enclosure url="https://openscad.googlecode.com/files/OpenSCAD-@VERSION@.dmg"
sparkle:version="@VERSIONDATE@"
sparkle:shortVersionString="@VERSION@"
length="@FILESIZE@"
type="application/octet-stream"/>
</item>
</channel>
</rss>

View File

@ -44,7 +44,8 @@ o Notify package managers
Build and Upload Release Binaries
---------------------------------
$ export VERSION=<openscad version, e.g. 2013.01>
$ export VERSIONDATE=<date of release in YYYY.MM.DD format, e.g. 2013.01.17>
$ export VERSION=<openscad version, e.g. 2013.01> # If development snapshot, you don't need version is the same as VERSIONDATE
$ tar xzf openscad-$VERSION.src.tar.gz
$ cd openscad-$VERSION

BIN
icons/prefsUpdate.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -1 +1,2 @@
set environment DYLD_LIBRARY_PATH=/Users/kintel/code/OpenSCAD/libraries/install/lib
set environment DYLD_FRAMEWORK_PATH=/Users/kintel/code/OpenSCAD/libraries/install/lib

View File

@ -68,7 +68,7 @@ macx {
APP_RESOURCES.path = Contents/Resources
APP_RESOURCES.files = OpenSCAD.sdef
QMAKE_BUNDLE_DATA += APP_RESOURCES
LIBS += -framework Carbon
LIBS += -framework Cocoa -framework Sparkle
}
else {
TARGET = openscad
@ -320,8 +320,14 @@ SOURCES += src/cgalutils.cc \
macx {
HEADERS += src/AppleEvents.h \
src/EventFilter.h
SOURCES += src/AppleEvents.cc
src/EventFilter.h \
src/AutoUpdater.h \
src/SparkleAutoUpdater.h \
src/CocoaInitializer.h
SOURCES += src/AppleEvents.cc \
src/AutoUpdater.cc
OBJECTIVE_SOURCES += src/SparkleAutoUpdater.mm \
src/CocoaInitializer.mm
}
isEmpty(PREFIX):PREFIX = /usr/local

View File

@ -4,6 +4,7 @@
<file>icons/prefsAdvanced.png</file>
<file>icons/prefs3DView.png</file>
<file>icons/prefsEditor.png</file>
<file>icons/prefsUpdate.png</file>
<file>icons/flattr.png</file>
<file>src/AboutDialog.html</file>
</qresource>

View File

@ -1,10 +1,13 @@
#!/bin/sh
# NB! To build a release build, the VERSION environment variable needs to be set.
# NB! To build a release build, the VERSION and VERSIONDATE environment variables needs to be set.
# See doc/release-checklist.txt
if test -z "$VERSIONDATE"; then
VERSIONDATE=`date "+%Y.%m.%d"`
fi
if test -z "$VERSION"; then
VERSION=`date "+%Y.%m.%d"`
VERSION=$VERSIONDATE
COMMIT=-c
SNAPSHOT=true
fi
@ -18,21 +21,33 @@ export OPENSCAD_LIBRARIES=$PWD/../libraries/install
# Make sure that the correct Qt tools are used
export PATH=$OPENSCAD_LIBRARIES/bin:$PATH
`dirname $0`/release-common.sh -v $VERSION $COMMIT
if [[ $? != 0 ]]; then
exit 1
fi
#`dirname $0`/release-common.sh -v $VERSION $COMMIT
#if [[ $? != 0 ]]; then
# exit 1
#fi
echo "Sanity check of the app bundle..."
`dirname $0`/macosx-sanity-check.py OpenSCAD.app/Contents/MacOS/OpenSCAD
if [[ $? != 0 ]]; then
exit 1
#`dirname $0`/macosx-sanity-check.py OpenSCAD.app/Contents/MacOS/OpenSCAD
#if [[ $? != 0 ]]; then
# exit 1
#fi
if [[ $VERSION == $VERSIONDATE ]]; then
APPCASTFILE=appcast-snapshots.xml
else
APPCASTFILE=appcast.xml
fi
echo "Creating appcast $APPCASTFILE..."
sed -e "s,@VERSION@,$VERSION,g" -e "s,@VERSIONDATE@,$VERSIONDATE,g" -e "s,@FILESIZE@,$(stat -f "%z" OpenSCAD-$VERSION.dmg),g" $APPCASTFILE.in > $APPCASTFILE
cp $APPCASTFILE ../openscad.github.com
if [[ $VERSION == $VERSIONDATE ]]; then
cp $APPCASTFILE ../openscad.github.com/appcast-snapshots.xml
fi
echo "Uploading..."
LABELS=OpSys-OSX,Type-Executable
if ! $SNAPSHOT; then LABELS=$LABELS,Featured; fi
`dirname $0`/googlecode_upload.py -s 'Mac OS X Snapshot' -p openscad OpenSCAD-$VERSION.dmg -l $LABELS
#LABELS=OpSys-OSX,Type-Executable
#if ! $SNAPSHOT; then LABELS=$LABELS,Featured; fi
#`dirname $0`/googlecode_upload.py -s 'Mac OS X Snapshot' -p openscad OpenSCAD-$VERSION.dmg -l $LABELS
# Update snapshot filename on wab page
`dirname $0`/update-web.sh OpenSCAD-$VERSION.dmg
#`dirname $0`/update-web.sh OpenSCAD-$VERSION.dmg

View File

@ -9,10 +9,12 @@
#
# Usage: release-common.sh [-v <versionstring>] [-c] [-x32]
# -v Version string (e.g. -v 2010.01)
# -d Version date (e.g. -d 2010.01.23)
# -c Build with commit info
# -mingw32 Cross-compile for win32 using MXE
#
# If no version string is given, todays date will be used (YYYY-MM-DD)
# If no version string or version date is given, todays date will be used (YYYY-MM-DD)
# If only verion date is given, it will be used also as version string.
# If no make target is given, release will be used on Windows, none one Mac OS X
#
# The commit info will extracted from git and be passed to qmake as OPENSCAD_COMMIT
@ -23,7 +25,7 @@
printUsage()
{
echo "Usage: $0 -v <versionstring> -c -mingw32
echo "Usage: $0 -v <versionstring> -d <versiondate> -c -mingw32
echo
echo " Example: $0 -v 2010.01
}
@ -59,16 +61,20 @@ else
exit
fi
while getopts 'v:c' c
while getopts 'v:d:c' c
do
case $c in
v) VERSION=$OPTARG;;
d) VERSIONDATE=$OPTARG;;
c) OPENSCAD_COMMIT=`git log -1 --pretty=format:"%h"`
esac
done
if test -z "$VERSIONDATE"; then
VERSIONDATE=`date "+%Y.%m.%d"`
fi
if test -z "$VERSION"; then
VERSION=`date "+%Y.%m.%d"`
VERSION=$VERSIONDATE
fi
@ -102,7 +108,7 @@ if [ -d .git ]; then
git submodule update
fi
echo "Building openscad-$VERSION $CONFIGURATION..."
echo "Building openscad-$VERSION ($VERSIONDATE) $CONFIGURATION..."
case $OS in
LINUX|MACOSX)
@ -230,6 +236,7 @@ echo "Creating archive.."
case $OS in
MACOSX)
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $VERSIONDATE" OpenSCAD.app/Contents/Info.plist
macdeployqt OpenSCAD.app -dmg -no-strip
mv OpenSCAD.dmg OpenSCAD-$VERSION.dmg
hdiutil internet-enable -yes -quiet OpenSCAD-$VERSION.dmg

View File

@ -1,5 +1,6 @@
export OPENSCAD_LIBRARIES=$PWD/../libraries/install
export DYLD_LIBRARY_PATH=$OPENSCAD_LIBRARIES/lib
export DYLD_FRAMEWORK_PATH=$OPENSCAD_LIBRARIES/lib
export QMAKESPEC=macx-g++
#export OPENCSGDIR=$PWD/../OpenCSG-1.3.0

3
src/AutoUpdater.cc Normal file
View File

@ -0,0 +1,3 @@
#include "AutoUpdater.h"
AutoUpdater *AutoUpdater::updater_instance = NULL;

25
src/AutoUpdater.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef AUTOUPDATER_H_
#define AUTOUPDATER_H_
#include <QString>
class AutoUpdater
{
public:
virtual ~AutoUpdater() {}
virtual void checkForUpdates() = 0;
virtual void setAutomaticallyChecksForUpdates(bool on) = 0;
virtual bool automaticallyChecksForUpdates() = 0;
virtual void setEnableSnapshots(bool on) = 0;
virtual bool enableSnapshots() = 0;
virtual QString lastUpdateCheckDate() = 0;
static AutoUpdater *updater() { return updater_instance; }
static void setUpdater(AutoUpdater *updater) { updater_instance = updater; }
protected:
static AutoUpdater *updater_instance;
};
#endif

View File

@ -91,6 +91,7 @@ private:
class QMessageBox *openglbox;
private slots:
void actionUpdateCheck();
void actionNew();
void actionOpen();
void actionOpenRecent();

View File

@ -223,6 +223,7 @@
<addaction name="helpActionHomepage"/>
<addaction name="helpActionManual"/>
<addaction name="helpActionLibraryInfo"/>
<addaction name="appActionUpdateCheck"/>
</widget>
<addaction name="menu_File"/>
<addaction name="menu_Edit"/>
@ -611,6 +612,9 @@
</property>
</action>
<action name="helpActionAbout">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>About</string>
</property>
@ -676,6 +680,14 @@
<string>Library info</string>
</property>
</action>
<action name="appActionUpdateCheck">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Check for Update..</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>

View File

@ -29,7 +29,9 @@
#include <QFontDatabase>
#include <QKeyEvent>
#include <QSettings>
#include <QStatusBar>
#include "PolySetCache.h"
#include "AutoUpdater.h"
#ifdef ENABLE_CGAL
#include "CGALCache.h"
#endif
@ -88,6 +90,7 @@ Preferences::Preferences(QWidget *parent) : QMainWindow(parent)
QActionGroup *group = new QActionGroup(this);
group->addAction(prefsAction3DView);
group->addAction(prefsActionEditor);
group->addAction(prefsActionUpdate);
group->addAction(prefsActionAdvanced);
connect(group, SIGNAL(triggered(QAction*)), this, SLOT(actionTriggered(QAction*)));
@ -155,6 +158,9 @@ Preferences::actionTriggered(QAction *action)
else if (action == this->prefsActionEditor) {
this->stackedWidget->setCurrentWidget(this->pageEditor);
}
else if (action == this->prefsActionUpdate) {
this->stackedWidget->setCurrentWidget(this->pageUpdate);
}
else if (action == this->prefsActionAdvanced) {
this->stackedWidget->setCurrentWidget(this->pageAdvanced);
}
@ -186,6 +192,27 @@ void Preferences::on_fontSize_editTextChanged(const QString &size)
emit fontChanged(getValue("editor/fontfamily").toString(), intsize);
}
void Preferences::on_updateCheckBox_toggled(bool on)
{
if (AutoUpdater *updater =AutoUpdater::updater()) {
updater->setAutomaticallyChecksForUpdates(on);
}
}
void Preferences::on_snapshotCheckBox_toggled(bool on)
{
if (AutoUpdater *updater =AutoUpdater::updater()) {
updater->setEnableSnapshots(on);
}
}
void Preferences::on_checkNowButton_clicked()
{
if (AutoUpdater *updater =AutoUpdater::updater()) {
updater->checkForUpdates();
}
}
void
Preferences::on_openCSGWarningBox_toggled(bool state)
{
@ -289,6 +316,12 @@ void Preferences::updateGUI()
this->fontSize->setEditText(fontsize);
}
if (AutoUpdater *updater = AutoUpdater::updater()) {
this->updateCheckBox->setChecked(updater->automaticallyChecksForUpdates());
this->snapshotCheckBox->setChecked(updater->enableSnapshots());
this->lastCheckedLabel->setText(updater->lastUpdateCheckDate());
}
this->openCSGWarningBox->setChecked(getValue("advanced/opencsg_show_warning").toBool());
this->enableOpenCSGBox->setChecked(getValue("advanced/enable_opencsg_opengl1x").toBool());
this->cgalCacheSizeEdit->setText(getValue("advanced/cgalCacheSize").toString());

View File

@ -30,6 +30,9 @@ public slots:
void on_polysetCacheSizeEdit_textChanged(const QString &);
void on_opencsgLimitEdit_textChanged(const QString &);
void on_forceGoldfeatherBox_toggled(bool);
void on_updateCheckBox_toggled(bool);
void on_snapshotCheckBox_toggled(bool);
void on_checkNowButton_clicked();
signals:
void requestRedraw() const;

View File

@ -6,10 +6,16 @@
<rect>
<x>0</x>
<y>0</y>
<width>531</width>
<height>418</height>
<width>473</width>
<height>320</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Preferences</string>
</property>
@ -173,6 +179,150 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="pageUpdate">
<layout class="QVBoxLayout" name="verticalLayout_16">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<widget class="QCheckBox" name="updateCheckBox">
<property name="text">
<string>Automatically check for updates</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="snapshotCheckBox">
<property name="text">
<string>Include development snapshots</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_7">
<property name="spacing">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_11">
<item>
<spacer name="horizontalSpacer_10">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="checkNowButton">
<property name="text">
<string>Check Now</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_9">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<spacer name="horizontalSpacer_11">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="lastCheckedLabel">
<property name="enabled">
<bool>false</bool>
</property>
<property name="font">
<font>
<pointsize>11</pointsize>
</font>
</property>
<property name="text">
<string>Last checked: </string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_12">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_7">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>89</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="pageAdvanced">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
@ -227,9 +377,6 @@
</widget>
</item>
</layout>
<zorder>openCSGWarningBox</zorder>
<zorder>enableOpenCSGBox</zorder>
<zorder>forceGoldfeatherBox</zorder>
</widget>
</item>
<item>
@ -317,6 +464,7 @@
</attribute>
<addaction name="prefsAction3DView"/>
<addaction name="prefsActionEditor"/>
<addaction name="prefsActionUpdate"/>
<addaction name="prefsActionAdvanced"/>
</widget>
<action name="prefsAction3DView">
@ -355,6 +503,18 @@
<string>Editor</string>
</property>
</action>
<action name="prefsActionUpdate">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../openscad.qrc">
<normaloff>:/icons/prefsUpdate.png</normaloff>:/icons/prefsUpdate.png</iconset>
</property>
<property name="text">
<string>Update</string>
</property>
</action>
</widget>
<resources>
<include location="../openscad.qrc"/>

32
src/SparkleAutoUpdater.h Normal file
View File

@ -0,0 +1,32 @@
/*
* Copyright (C) 2008 Remko Troncon. BSD license
* Copyright (C) 2013 Marius Kintel. BSD license
*/
#ifndef SPARKLEAUTOUPDATER_H
#define SPARKLEAUTOUPDATER_H
#include <QString>
#include "AutoUpdater.h"
class SparkleAutoUpdater : public AutoUpdater
{
public:
SparkleAutoUpdater();
~SparkleAutoUpdater();
void checkForUpdates();
void setAutomaticallyChecksForUpdates(bool on);
bool automaticallyChecksForUpdates();
void setEnableSnapshots(bool on);
bool enableSnapshots();
QString lastUpdateCheckDate();
private:
void updateFeed();
class Private;
Private *d;
};
#endif

72
src/SparkleAutoUpdater.mm Normal file
View File

@ -0,0 +1,72 @@
/*
* Copyright (C) 2008 Remko Troncon. BSD license
* Copyright (C) 2013 Marius Kintel. BSD license
*/
#include "SparkleAutoUpdater.h"
#include <Cocoa/Cocoa.h>
#include <Sparkle/Sparkle.h>
NSString *const SUEnableSnapshotsKey = @"SUEnableSnapshots";
class SparkleAutoUpdater::Private
{
public:
SUUpdater* updater;
};
SparkleAutoUpdater::SparkleAutoUpdater()
{
d = new Private;
d->updater = [SUUpdater sharedUpdater];
[d->updater retain];
updateFeed();
}
SparkleAutoUpdater::~SparkleAutoUpdater()
{
[d->updater release];
delete d;
}
void SparkleAutoUpdater::checkForUpdates()
{
[d->updater checkForUpdatesInBackground];
}
void SparkleAutoUpdater::setAutomaticallyChecksForUpdates(bool on)
{
[d->updater setAutomaticallyChecksForUpdates:on];
}
bool SparkleAutoUpdater::automaticallyChecksForUpdates()
{
return [d->updater automaticallyChecksForUpdates];
}
void SparkleAutoUpdater::setEnableSnapshots(bool on)
{
[[NSUserDefaults standardUserDefaults] setBool:on forKey:SUEnableSnapshotsKey];
updateFeed();
}
bool SparkleAutoUpdater::enableSnapshots()
{
return [[NSUserDefaults standardUserDefaults] boolForKey:SUEnableSnapshotsKey];
}
QString SparkleAutoUpdater::lastUpdateCheckDate()
{
NSString *datestring = [NSString stringWithFormat:@"Last checked: %@",
[d->updater lastUpdateCheckDate]];
return QString::fromUtf8([datestring UTF8String]);
}
void SparkleAutoUpdater::updateFeed()
{
NSString *urlstring = [NSString stringWithFormat:@"http://openscad.org/appcast%@.xml", enableSnapshots() ? @"-snapshots" : @""];
[d->updater setFeedURL:[NSURL URLWithString:urlstring]];
}

View File

@ -48,6 +48,7 @@
#include "ProgressWidget.h"
#include "ThrownTogetherRenderer.h"
#include "csgtermnormalizer.h"
#include "AutoUpdater.h"
#include <QMenu>
#include <QTime>
@ -205,6 +206,16 @@ MainWindow::MainWindow(const QString &filename)
animate_panel->hide();
// Application menu
#ifdef DEBUG
this->appActionUpdateCheck->setEnabled(false);
#else
#ifdef Q_OS_MAC
this->appActionUpdateCheck->setMenuRole(QAction::ApplicationSpecificRole);
this->appActionUpdateCheck->setEnabled(true);
connect(this->appActionUpdateCheck, SIGNAL(triggered()), this, SLOT(actionUpdateCheck()));
#endif
#endif
// File menu
connect(this->fileActionNew, SIGNAL(triggered()), this, SLOT(actionNew()));
connect(this->fileActionOpen, SIGNAL(triggered()), this, SLOT(actionOpen()));
@ -781,6 +792,13 @@ void MainWindow::compileCSG(bool procevents)
}
}
void MainWindow::actionUpdateCheck()
{
if (AutoUpdater *updater =AutoUpdater::updater()) {
updater->checkForUpdates();
}
}
void MainWindow::actionNew()
{
#ifdef ENABLE_MDI

View File

@ -54,6 +54,7 @@
#ifdef Q_WS_MAC
#include "EventFilter.h"
#include "AppleEvents.h"
#include "SparkleAutoUpdater.h"
#endif
#include <boost/program_options.hpp>
@ -386,6 +387,14 @@ int main(int argc, char **argv)
installAppleEventHandlers();
#endif
#ifndef DEBUG
#ifdef Q_WS_MAC
AutoUpdater *updater = new SparkleAutoUpdater;
AutoUpdater::setUpdater(updater);
if (updater->automaticallyChecksForUpdates()) updater->checkForUpdates();
#endif
#endif
QString qfilename;
if (filename) qfilename = QString::fromStdString(boosty::stringy(boosty::absolute(filename)));