New Updater for Windows, passive notification on Linux, Sparkle on Mac

This commit is contained in:
Daniel Molkentin 2014-01-15 11:08:42 +01:00
Родитель 93239cbdca
Коммит dc9f145a24
25 изменённых файлов: 900 добавлений и 327 удалений

Просмотреть файл

@ -10,7 +10,6 @@ endif( NOT DEFINED MIRALL_VERSION_SUFFIX )
if( NOT DEFINED MIRALL_VERSION_BUILD )
set( MIRALL_VERSION_BUILD "0" ) # Integer ID. Generated by the build system
endif( NOT DEFINED MIRALL_VERSION_BUILD )
# Composite defines
# Used e.g. for libraries Keep at x.y.z.
set( MIRALL_VERSION "${MIRALL_VERSION_MAJOR}.${MIRALL_VERSION_MINOR}.${MIRALL_VERSION_PATCH}" )

Просмотреть файл

@ -1,5 +1,3 @@
#add_subdirectory(integration)
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
qt_add_resources(MIRALL_RC_SRC ../mirall.qrc)
@ -13,6 +11,20 @@ endif()
set(synclib_NAME ${APPLICATION_EXECUTABLE}sync)
if ( APPLE )
list(APPEND OS_SPECIFIC_LINK_LIBRARIES
/System/Library/Frameworks/CoreServices.framework
/System/Library/Frameworks/Foundation.framework
/System/Library/Frameworks/AppKit.framework
)
endif()
if( ENABLE_SPARKLE AND SPARKLE )
set( HAVE_SPARKLE ON )
list (APPEND OS_SPECIFIC_LINK_LIBRARIES ${SPARKLE})
endif( ENABLE_SPARKLE AND SPARKLE )
set(3rdparty_SRC
3rdparty/qtsingleapplication/qtsingleapplication.cpp
3rdparty/qtsingleapplication/qtlocalpeer.cpp
@ -121,10 +133,9 @@ IF( WIN32 )
set(libsync_HEADERS ${libsync_HEADERS} mirall/folderwatcher_win.h)
ENDIF()
IF( APPLE )
set(libsync_SRCS ${libsync_SRCS} mirall/folderwatcher_mac.cpp)
list(APPEND libsync_SRCS mirall/folderwatcher_mac.cpp)
ENDIF()
qt_wrap_cpp(syncMoc ${libsync_HEADERS})
# These headers are installed for libowncloudsync to be used by 3rd party apps
@ -164,11 +175,17 @@ ELSE()
FIND_LIBRARY(HTTPBF_LIBRARY NAMES httpbf HINTS $ENV{CSYNC_DIR})
ENDIF()
IF( DEFINED CSYNC_BUILD_PATH )
SET(HTTPBF_LIBRARY ${CSYNC_BUILD_PATH}/src/httpbf/libhttpbf.a)
ELSE()
FIND_LIBRARY(HTTPBF_LIBRARY NAMES httpbflib HINTS $ENV{CSYNC_DIR})
ENDIF()
list(APPEND libsync_LINK_TARGETS
${QT_LIBRARIES}
${CSYNC_LIBRARY}
${HTTPBF_LIBRARY}
${OS_SPECIFIC_LINK_LIBRARIES}
)
if(QTKEYCHAIN_FOUND)
@ -197,10 +214,6 @@ set_target_properties( ${synclib_NAME} PROPERTIES
target_link_libraries(${synclib_NAME} ${libsync_LINK_TARGETS} )
if ( APPLE )
target_link_libraries(${synclib_NAME} /System/Library/Frameworks/CoreServices.framework)
endif()
if(NOT BUILD_OWNCLOUD_OSX_BUNDLE)
install(TARGETS ${synclib_NAME}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
@ -248,8 +261,7 @@ set(mirall_SRCS
wizard/owncloudshibbolethcredspage.cpp
wizard/owncloudadvancedsetuppage.cpp
mirall/owncloudsetupwizard.cpp
mirall/updatedetector.cpp
mirall/occinfo.cpp
mirall/updateinfo.cpp
mirall/sslerrordialog.cpp
mirall/logbrowser.cpp
mirall/settingsdialog.cpp
@ -259,6 +271,8 @@ set(mirall_SRCS
mirall/ignorelisteditor.cpp
mirall/owncloudgui.cpp
mirall/socketapi.cpp
mirall/updater.cpp
mirall/genericupdater.cpp
)
set(mirall_HEADERS
@ -274,7 +288,6 @@ set(mirall_HEADERS
wizard/owncloudshibbolethcredspage.h
wizard/owncloudadvancedsetuppage.h
mirall/folderstatusmodel.h
mirall/updatedetector.h
mirall/sslerrordialog.h
mirall/logbrowser.h
mirall/settingsdialog.h
@ -285,8 +298,19 @@ set(mirall_HEADERS
mirall/protocolwidget.h
mirall/owncloudgui.h
mirall/socketapi.h
mirall/updater.h
mirall/genericupdater.h
)
IF( APPLE )
list(APPEND mirall_SRCS
mirall/cocoainitializer_mac.mm
mirall/sparkleupdater_mac.mm)
list(APPEND mirall_HEADERS
mirall/cocoainitializer.h
mirall/sparkleupdater.h)
ENDIF()
# csync is required.
include_directories(${CSYNC_INCLUDE_DIR}/csync ${CSYNC_INCLUDE_DIR} ${CSYNC_INCLUDE_DIR}/httpbf/src ${CSYNC_BUILD_PATH}/src)
include_directories(${3rdparty_INC})
@ -350,6 +374,9 @@ else()
set(BIN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
include(DeployQt4)
option(ENABLE_SPARKLE "Sparkle updating" ON)
find_library(SPARKLE Sparkle)
set(CMAKE_INSTALL_PREFIX ".") # Examples use /Applications. hurmpf.
set(MACOSX_BUNDLE_ICON_FILE "ownCloud.icns")
@ -372,6 +399,7 @@ set_target_properties( ${APPLICATION_EXECUTABLE} PROPERTIES
target_link_libraries( ${APPLICATION_EXECUTABLE} ${QT_LIBRARIES} )
target_link_libraries( ${APPLICATION_EXECUTABLE} ${synclib_NAME} )
target_link_libraries( ${APPLICATION_EXECUTABLE} ${CSYNC_LIBRARY} )
target_link_libraries( ${APPLICATION_EXECUTABLE} ${OS_SPECIFIC_LINK_LIBRARIES} )
install(TARGETS ${APPLICATION_EXECUTABLE}
RUNTIME DESTINATION bin

Просмотреть файл

@ -16,9 +16,13 @@
#include "mirall/application.h"
#include "mirall/theme.h"
#include "mirall/utility.h"
#include "mirall/cocoainitializer.h"
#include "mirall/updater.h"
#include <QMessageBox>
#include <QTimer>
#include <QMessageBox>
using namespace Mirall;
void warnSystray()
{
@ -27,13 +31,16 @@ void warnSystray()
"If you are running XFCE, please follow "
"<a href=\"http://docs.xfce.org/xfce/xfce4-panel/systray\">these instructions</a>. "
"Otherwise, please install a system tray application such as 'trayer' and try again.")
.arg(Mirall::Theme::instance()->appNameGUI()));
.arg(Theme::instance()->appNameGUI()));
}
int main(int argc, char **argv)
{
Q_INIT_RESOURCE(mirall);
#ifdef Q_OS_MAC
Mac::CocoaInitializer cocoaInit; // RIIA
#endif
Mirall::Application app(argc, argv);
#ifndef Q_OS_WIN
signal(SIGPIPE, SIG_IGN);
@ -43,6 +50,19 @@ int main(int argc, char **argv)
return 0;
}
Updater *updater = Updater::instance();
switch (updater->updateState()) {
case Updater::UpdateAvailable:
updater->performUpdate();
return true;
case Updater::UpdateFailed:
updater->showFallbackMessage();
break;
case Updater::NoUpdate:
default:
break;
}
// if the application is already running, notify it.
if( app.isRunning() ) {
QStringList args = app.arguments();
@ -56,7 +76,7 @@ int main(int argc, char **argv)
int attempts = 0;
forever {
if (!QSystemTrayIcon::isSystemTrayAvailable() && qgetenv("DESKTOP_SESSION") != "ubuntu") {
Mirall::Utility::sleep(1);
Utility::sleep(1);
attempts++;
if (attempts < 30) continue;
} else {

Просмотреть файл

@ -18,19 +18,19 @@
#include "config.h"
#include "mirall/account.h"
#include "mirall/application.h"
#include "mirall/connectionvalidator.h"
#include "mirall/folder.h"
#include "mirall/folderman.h"
#include "mirall/folder.h"
#include "mirall/logger.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/socketapi.h"
#include "mirall/sslerrordialog.h"
#include "mirall/theme.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/updatedetector.h"
#include "mirall/logger.h"
#include "mirall/updater.h"
#include "mirall/utility.h"
#include "mirall/connectionvalidator.h"
#include "mirall/socketapi.h"
#include "mirall/account.h"
#include "creds/abstractcredentials.h"
@ -139,7 +139,7 @@ Application::Application(int &argc, char **argv) :
// startup procedure.
QTimer::singleShot( 0, this, SLOT( slotCheckConnection() ));
if( !cfg.ownCloudSkipUpdateCheck() ) {
if( !cfg.skipUpdateCheck() ) {
QTimer::singleShot( 3000, this, SLOT( slotStartUpdateDetector() ));
}
@ -202,8 +202,8 @@ void Application::slotCleanup()
void Application::slotStartUpdateDetector()
{
UpdateDetector *updateDetector = new UpdateDetector(this);
updateDetector->versionCheck(_theme);
Updater *updater = Updater::instance();
updater->backgroundCheckForUpdate();
}
void Application::slotCheckConnection()

Просмотреть файл

@ -0,0 +1,28 @@
/*
* Copyright (C) by Daniel Molkentin <danimo@owncloud.com>
*
* This program 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; version 2 of the License.
*
* This program 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.
*/
namespace Mirall {
namespace Mac {
/** CocoaInitializer provides an AutoRelease Pool via RIIA for use in main() */
class CocoaInitializer {
public:
CocoaInitializer();
~CocoaInitializer();
private:
class Private;
Private *d;
};
} // namespace Mac
} // namespace Mirall

Просмотреть файл

@ -0,0 +1,39 @@
/*
* Copyright (C) by Daniel Molkentin <danimo@owncloud.com>
*
* This program 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; version 2 of the License.
*
* This program 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.
*/
#include "mirall/cocoainitializer.h"
#import <Foundation/NSAutoreleasePool.h>
#import <AppKit/NSApplication.h>
namespace Mirall {
namespace Mac {
class CocoaInitializer::Private {
public:
NSAutoreleasePool* autoReleasePool;
};
CocoaInitializer::CocoaInitializer() {
d = new CocoaInitializer::Private();
NSApplicationLoad();
d->autoReleasePool = [[NSAutoreleasePool alloc] init];
}
CocoaInitializer::~CocoaInitializer() {
[d->autoReleasePool release];
delete d;
}
} // namespace Mac
} // namespace Mirall

Просмотреть файл

@ -19,6 +19,8 @@
#include "mirall/application.h"
#include "mirall/utility.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/updater.h"
#include "mirall/genericupdater.h"
#include <QNetworkProxy>
#include <QDir>
@ -47,6 +49,7 @@ GeneralSettings::GeneralSettings(QWidget *parent) :
}
loadMiscSettings();
slotUpdateInfo();
// misc
connect(_ui->monoIconsCheckBox, SIGNAL(toggled(bool)), SLOT(saveMiscSettings()));
@ -56,7 +59,6 @@ GeneralSettings::GeneralSettings(QWidget *parent) :
QString themeDir = QString::fromLatin1(":/mirall/theme/%1/")
.arg(Theme::instance()->systrayIconFlavor(true));
_ui->monoIconsCheckBox->setVisible(QDir(themeDir).exists());
}
GeneralSettings::~GeneralSettings()
@ -71,6 +73,20 @@ void GeneralSettings::loadMiscSettings()
_ui->desktopNotificationsCheckBox->setChecked(cfgFile.optionalDesktopNotifications());
}
void GeneralSettings::slotUpdateInfo()
{
if (GenericUpdater *updater = dynamic_cast<GenericUpdater*>(Updater::instance()))
{
connect(updater, SIGNAL(stateChanged()), SLOT(slotUpdateInfo()), Qt::UniqueConnection);
connect(_ui->restartButton, SIGNAL(clicked()), updater, SLOT(slotStartInstaller()), Qt::UniqueConnection);
_ui->updateStateLabel->setText(updater->statusString());
_ui->restartButton->setVisible(updater->state() == GenericUpdater::UpdateAvailable);
} else {
// can't have those infos from sparkle currently
_ui->updatesGroupBox->setVisible(false);
}
}
void GeneralSettings::saveMiscSettings()
{
MirallConfigFile cfgFile;

Просмотреть файл

@ -38,6 +38,7 @@ private slots:
void saveMiscSettings();
void slotToggleLaunchOnStartup(bool);
void slotToggleOptionalDesktopNotifications(bool);
void slotUpdateInfo();
private:
void loadMiscSettings();

Просмотреть файл

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>468</width>
<height>169</height>
<height>249</height>
</rect>
</property>
<property name="windowTitle">
@ -60,6 +60,54 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="updatesGroupBox">
<property name="title">
<string>Updates</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="updateStateLabel">
<property name="text">
<string/>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="restartButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&amp;Restart &amp;&amp; Update</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">

Просмотреть файл

@ -0,0 +1,355 @@
/*
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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.
*/
#include "mirall/genericupdater.h"
#include "mirall/theme.h"
#include "mirall/version.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/utility.h"
#include "mirall/mirallaccessmanager.h"
#include <QtCore>
#include <QtNetwork>
#include <QtGui>
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
#include <QtWidgets>
#endif
#include <stdio.h>
namespace Mirall {
static const char updateAvailableC[] = "Updater/updateAvailable";
static const char lastVersionC[] = "Updater/lastVersion";
static const char ranUpdateC[] = "Updater/ranUpdate";
GenericUpdater::GenericUpdater(const QUrl &url, QObject *parent) :
QObject(parent)
, _updateUrl(url)
, _accessManager(new MirallAccessManager(this))
, _state(Unknown)
, _showFallbackMessage(false)
{
}
Updater::UpdateState GenericUpdater::updateState() const
{
MirallConfigFile cfg;
QSettings settings(cfg.configFile(), QSettings::IniFormat);
QString updateFile = settings.value(updateAvailableC).toString();
bool exists = QFile(updateFile).exists();
if (!updateFile.isEmpty() && exists) {
// we have an update, did we succeed running it?
bool ranUpdate = settings.value(ranUpdateC, false).toBool();
if (ranUpdate) {
if (updateSucceeded()) {
settings.remove(ranUpdateC);
return NoUpdate;
} else {
return UpdateFailed;
}
} else {
return UpdateAvailable;
}
} else {
return NoUpdate;
}
}
void GenericUpdater::performUpdate()
{
MirallConfigFile cfg;
QSettings settings(cfg.configFile(), QSettings::IniFormat);
QString updateFile = settings.value(updateAvailableC).toString();
if (!updateFile.isEmpty() && QFile(updateFile).exists()) {
if (QMessageBox::information(0, tr("New Update Ready"),
tr("A new update is about to be installed. The updater may ask\n"
"for additional privileges during the process."), QMessageBox::Ok)) {
slotStartInstaller();
}
}
}
void GenericUpdater::backgroundCheckForUpdate()
{
// FIXME
checkForUpdate();
}
void GenericUpdater::showFallbackMessage()
{
_showFallbackMessage = true;
}
QString GenericUpdater::statusString() const
{
QString updateVersion = _updateInfo.version();
switch (state()) {
case DownloadingUpdate:
return tr("Downloading version %1. Please wait...").arg(updateVersion);
case DownloadedUpdate:
return tr("Version %1 available. Restart application to start the update.").arg(updateVersion);
case DownloadFailed:
return tr("Could not download update. Please click <a href='%1'>here</a> %2 to download the update manually").arg(_updateInfo.web(), updateVersion);
case UpdateButNoDownloadAvailable:
return tr("New version %1 available. Please use the systems update tool to install it.").arg(updateVersion);
case Unknown:
return tr("Checking update server...");
case UpToDate:
// fall through
default:
return tr("Your installation is at the latest version");
}
}
int GenericUpdater::state() const
{
return _state;
}
void GenericUpdater::setState(int state)
{
_state = state;
emit stateChanged();
}
void GenericUpdater::slotStartInstaller()
{
MirallConfigFile cfg;
QSettings settings(cfg.configFile(), QSettings::IniFormat);
QString updateFile = settings.value(updateAvailableC).toString();
settings.setValue(ranUpdateC, true);
qDebug() << "Running updater" << updateFile;
QProcess::startDetached(updateFile, QStringList() << "/S");
qApp->quit();
}
void GenericUpdater::checkForUpdate()
{
Theme *theme = Theme::instance();
QUrl url(_updateUrl);
QString platform = QLatin1String("stranger");
if (Utility::isLinux()) {
platform = QLatin1String("linux");
} else if (Utility::isWindows()) {
platform = QLatin1String("win32");
} else if (Utility::isMac()) {
platform = QLatin1String("macos");
}
qDebug() << "00 client update check to " << url.toString();
QString sysInfo = getSystemInfo();
if( !sysInfo.isEmpty() ) {
url.addQueryItem(QLatin1String("client"), sysInfo );
}
url.addQueryItem( QLatin1String("version"), clientVersion() );
url.addQueryItem( QLatin1String("platform"), platform );
url.addQueryItem( QLatin1String("oem"), theme->appName() );
QNetworkReply *reply = _accessManager->get( QNetworkRequest(url) );
connect(reply, SIGNAL(finished()), this,
SLOT(slotVersionInfoArrived()) );
}
void GenericUpdater::slotOpenUpdateUrl()
{
QDesktopServices::openUrl(_updateInfo.web());
}
void GenericUpdater::slotSetVersionSeen()
{
MirallConfigFile cfg;
cfg.setSeenVersion(_updateInfo.version());
}
QString GenericUpdater::getSystemInfo()
{
#ifdef Q_OS_LINUX
QProcess process;
process.start( QLatin1String("lsb_release -a") );
process.waitForFinished();
QByteArray output = process.readAllStandardOutput();
qDebug() << "Sys Info size: " << output.length();
if( output.length() > 1024 ) output.clear(); // don't send too much.
return QString::fromLocal8Bit( output.toBase64() );
#else
return QString::null;
#endif
}
void GenericUpdater::showDialog()
{
// if the version tag is set, there is a newer version.
QDialog *msgBox = new QDialog;
msgBox->setAttribute(Qt::WA_DeleteOnClose);
QIcon info = msgBox->style()->standardIcon(QStyle::SP_MessageBoxInformation, 0, 0);
int iconSize = msgBox->style()->pixelMetric(QStyle::PM_MessageBoxIconSize, 0, 0);
msgBox->setWindowIcon(info);
QVBoxLayout *layout = new QVBoxLayout(msgBox);
QHBoxLayout *hlayout = new QHBoxLayout;
layout->addLayout(hlayout);
msgBox->setWindowTitle(tr("New Version Available"));
QLabel *ico = new QLabel;
ico->setFixedSize(iconSize, iconSize);
ico->setPixmap(info.pixmap(iconSize));
QLabel *lbl = new QLabel;
QString txt = tr("<p>A new version of the %1 Client is available.</p>"
"<p><b>%2</b> is available for download. The installed version is %3.<p>")
.arg(Theme::instance()->appNameGUI()).arg(_updateInfo.versionString()).arg(clientVersion());
lbl->setText(txt);
lbl->setTextFormat(Qt::RichText);
lbl->setWordWrap(true);
hlayout->addWidget(ico);
hlayout->addWidget(lbl);
QDialogButtonBox *bb = new QDialogButtonBox;
bb->setWindowFlags(bb->windowFlags() & ~Qt::WindowContextHelpButtonHint);
QPushButton *skip = bb->addButton(tr("Skip this version"), QDialogButtonBox::ResetRole);
QPushButton *reject = bb->addButton(tr("Skip this time"), QDialogButtonBox::AcceptRole);
QPushButton *getupdate = bb->addButton(tr("Get update"), QDialogButtonBox::AcceptRole);
connect(skip, SIGNAL(clicked()), msgBox, SLOT(reject()));
connect(reject, SIGNAL(clicked()), msgBox, SLOT(reject()));
connect(getupdate, SIGNAL(clicked()), msgBox, SLOT(accept()));
connect(skip, SIGNAL(clicked()), SLOT(slotSetVersionSeen()));
connect(getupdate, SIGNAL(clicked()), SLOT(slotOpenUpdateUrl()));
layout->addWidget(bb);
msgBox->open();
}
void GenericUpdater::slotVersionInfoArrived()
{
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
if( reply->error() != QNetworkReply::NoError ) {
qDebug() << "Failed to reach version check url: " << reply->errorString();
return;
}
QString xml = QString::fromUtf8(reply->readAll());
bool ok;
_updateInfo = UpdateInfo::parseString( xml, &ok );
if( ok ) {
// Thats how it looks like if a new version is available:
// <?xml version="1.0"?>
// <owncloudclient>
// <version>1.0.0</version>
// <versionstring>ownCloud Client 1.0.0</versionstring>
// <web>http://ownCloud.org/client/update</web>
// </owncloudclient>
//
// and thats if no new version available:
// <?xml version="1.0"?>
// <owncloudclient>
// <version></version>
// <versionstring></versionstring>
// <web></web>
// </owncloudclient>
MirallConfigFile cfg;
if( _updateInfo.version().isEmpty() || _updateInfo.version() == cfg.seenVersion() ) {
qDebug() << "Client is on latest version!";
setState(UpToDate);
} else {
QString url = _updateInfo.downloadUrl();
if (url.isEmpty() || _showFallbackMessage) {
if (Utility::isWindows()) {
showDialog();
}
setState(UpdateButNoDownloadAvailable);
} else {
_targetFile = cfg.configPath() + url.mid(url.lastIndexOf('/'));
if (QFile(_targetFile).exists()) {
setState(DownloadedUpdate);
} else {
QNetworkReply *reply = _accessManager->get(QNetworkRequest(QUrl(url)));
connect(reply, SIGNAL(readyRead()), SLOT(slotWriteFile()));
connect(reply, SIGNAL(finished()), SLOT(slotDownloadFinished()));
setState(DownloadingUpdate);
_file.reset(new QTemporaryFile);
_file->setAutoRemove(true);
_file->open();
}
}
}
} else {
qDebug() << "Could not parse update information.";
}
}
void GenericUpdater::slotWriteFile()
{
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
if(_file->isOpen()) {
_file->write(reply->readAll());
}
}
void GenericUpdater::slotDownloadFinished()
{
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
if (reply->error() != QNetworkReply::NoError) {
setState(DownloadFailed);
return;
}
QUrl url(reply->url());
_file->close();
QFile::copy(_file->fileName(), _targetFile);
setState(DownloadedUpdate);
qDebug() << "Downloaded" << url.toString() << "to" << _targetFile;
MirallConfigFile cfg;
QSettings settings(cfg.configFile(), QSettings::IniFormat);
settings.setValue(lastVersionC, clientVersion());
settings.setValue(updateAvailableC, _targetFile);
}
static qint64 versionToInt(qint64 major, qint64 minor, qint64 patch, qint64 build)
{
return major << 56 | minor << 48 | patch << 40 | build;
}
bool GenericUpdater::updateSucceeded() const
{
MirallConfigFile cfg;
QSettings settings(cfg.configFile(), QSettings::IniFormat);
QByteArray lastVersion = settings.value(lastVersionC).toString().toLatin1();
int major = 0, minor = 0, patch = 0, build = 0;
sscanf(lastVersion, "%d.%d.%d.%d", &major, &minor, &patch, &build);
qint64 oldVersionInt = versionToInt(major, minor, patch, build);
qint64 versionInt = versionToInt(MIRALL_VERSION_MAJOR, MIRALL_VERSION_MINOR,
MIRALL_VERSION_PATCH, MIRALL_VERSION_BUILD);
return versionInt > oldVersionInt;
}
QString GenericUpdater::clientVersion() const
{
return QString::fromLatin1(MIRALL_STRINGIFY(MIRALL_VERSION_FULL));
}
}

Просмотреть файл

@ -0,0 +1,80 @@
/*
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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.
*/
#ifndef UPDATEDETECTOR_H
#define UPDATEDETECTOR_H
#include <QObject>
#include <QUrl>
#include <QTemporaryFile>
#include "mirall/updateinfo.h"
#include "mirall/updater.h"
class QNetworkAccessManager;
class QNetworkReply;
namespace Mirall {
class GenericUpdater : public QObject, public Updater
{
Q_OBJECT
public:
enum DownloadState { Unknown = 0, UpToDate, DownloadingUpdate, DownloadedUpdate,
DownloadFailed, UpdateButNoDownloadAvailable };
explicit GenericUpdater(const QUrl &url, QObject *parent = 0);
UpdateState updateState() const;
void performUpdate();
void checkForUpdate();
void backgroundCheckForUpdate();
void showFallbackMessage();
QString statusString() const;
int state() const;
void setState(int state);
signals:
void stateChanged();
public slots:
void slotStartInstaller();
private slots:
void slotOpenUpdateUrl();
void slotSetVersionSeen();
void slotVersionInfoArrived();
void slotWriteFile();
void slotDownloadFinished();
private:
bool updateSucceeded() const;
QString clientVersion() const;
QString getSystemInfo();
void showDialog();
QString _targetFile;
QUrl _updateUrl;
QNetworkAccessManager *_accessManager;
UpdateInfo _updateInfo;
QScopedPointer<QTemporaryFile> _file;
int _state;
bool _showFallbackMessage;
};
}
#endif // UPDATEDETECTOR_H

Просмотреть файл

@ -60,7 +60,6 @@ static const char downloadLimitC[] = "BWLimit/downloadLimit";
static const char seenVersionC[] = "Updater/seenVersion";
static const char maxLogLinesC[] = "Logging/maxLogLines";
QString MirallConfigFile::_oCVersion;
QString MirallConfigFile::_confDir = QString::null;
bool MirallConfigFile::_askedUser = false;
@ -334,19 +333,7 @@ quint64 MirallConfigFile::forceSyncInterval(const QString& connection) const
return interval;
}
QString MirallConfigFile::ownCloudVersion() const
{
return _oCVersion;
}
void MirallConfigFile::setOwnCloudVersion( const QString& ver)
{
qDebug() << "** Setting ownCloud Server version to " << ver;
_oCVersion = ver;
}
bool MirallConfigFile::ownCloudSkipUpdateCheck( const QString& connection ) const
bool MirallConfigFile::skipUpdateCheck( const QString& connection ) const
{
QString con( connection );
if( connection.isEmpty() ) con = defaultConnection();
@ -359,7 +346,7 @@ bool MirallConfigFile::ownCloudSkipUpdateCheck( const QString& connection ) cons
return skipIt;
}
void MirallConfigFile::setOwnCloudSkipUpdateCheck( bool skip, const QString& connection )
void MirallConfigFile::setSkipUpdateCheck( bool skip, const QString& connection )
{
QString con( connection );
if( connection.isEmpty() ) con = defaultConnection();

Просмотреть файл

@ -55,9 +55,6 @@ public:
int maxLogLines() const;
void setMaxLogLines(int);
bool ownCloudSkipUpdateCheck( const QString& connection = QString() ) const;
void setOwnCloudSkipUpdateCheck( bool, const QString& );
/* Server poll interval in milliseconds */
int remotePollInterval( const QString& connection = QString() ) const;
/* Set poll interval. Value in microseconds has to be larger than 5000 */
@ -99,12 +96,19 @@ public:
bool optionalDesktopNotifications() const;
void setOptionalDesktopNotifications(bool show);
QString seenVersion() const;
void setSeenVersion(const QString &version);
void saveGeometry(QWidget *w);
void restoreGeometry(QWidget *w);
// installer
bool skipUpdateCheck( const QString& connection = QString() ) const;
void setSkipUpdateCheck( bool, const QString& );
QString lastVersion() const;
void setLastVersion(const QString &version);
QString seenVersion() const;
void setSeenVersion(const QString &version);
void saveGeometryHeader(QHeaderView *header);
void restoreGeometryHeader(QHeaderView *header);
protected:

Просмотреть файл

@ -135,6 +135,8 @@ QNetworkReply *AbstractNetworkJob::headRequest(const QUrl &url)
void AbstractNetworkJob::slotFinished()
{
qDebug() << _reply->error() << _reply->errorString();
static QMutex mutex;
AbstractCredentials *creds = _account->credentials();
if (creds->stillValid(_reply) || _ignoreCredentialFailure) {

Просмотреть файл

@ -0,0 +1,37 @@
/*
* Copyright (C) by Daniel Molkentin <danimo@owncloud.com>
*
* This program 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; version 2 of the License.
*
* This program 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.
*/
#ifndef SPARKLEUPDATER_H
#define SPARKLEUPDATER_H
#include "mirall/updater.h"
#include <QObject>
namespace Mirall {
class SparkleUpdater : public Updater {
public:
SparkleUpdater(const QString& appCastUrl, QObject *parent = 0);
~SparkleUpdater();
void checkForUpdate();
void backgroundCheckForUpdate();
private:
class Private;
Private *d;
};
} // namespace Mirall
#endif // SPARKLEUPDATER_H

Просмотреть файл

@ -0,0 +1,63 @@
/*
* Copyright (C) by Daniel Molkentin <danimo@owncloud.com>
*
* This program 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; version 2 of the License.
*
* This program 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.
*/
#include <Cocoa/Cocoa.h>
#include <Sparkle/Sparkle.h>
#include <AppKit/NSApplication.h>
#include "mirall/sparkleupdater.h"
#include "mirall/utility.h"
namespace Mirall {
class SparkleUpdater::Private
{
public:
SUUpdater* updater;
};
SparkleUpdater::SparkleUpdater(const QString& appCastUrl, QObject *parent)
: Updater(parent)
{
d = new Private;
d->updater = [SUUpdater sharedUpdater];
[d->updater retain];
NSURL* url = [NSURL URLWithString:
[NSString stringWithUTF8String: appCastUrl.toUtf8().data()]];
[d->updater setFeedURL: url];
// requires a more recent version
// NSString *userAgent = [NSString stringWithUTF8String: Utility::userAgentString().data()];
// [d->updater setUserAgentString: userAgent];
}
SparkleUpdater::~SparkleUpdater()
{
[d->updater release];
delete d;
}
void SparkleUpdater::checkForUpdates()
{
[d->updater checkForUpdates: NSApp];
}
void SparkleUpdater::backgroundCheckForUpdates()
{
[d->updater checkForUpdatesInBackground];
}
} // namespace Mirall

Просмотреть файл

@ -1,189 +0,0 @@
/*
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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.
*/
#include "mirall/updatedetector.h"
#include "mirall/theme.h"
#include "mirall/version.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/occinfo.h"
#include "mirall/utility.h"
#include "mirall/mirallaccessmanager.h"
#include <QtCore>
#include <QtNetwork>
#include <QtGui>
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
#include <QtWidgets>
#endif
namespace Mirall {
UpdateDetector::UpdateDetector(QObject *parent) :
QObject(parent)
, _accessManager(new MirallAccessManager(this))
{
}
void UpdateDetector::versionCheck( Theme *theme )
{
connect(_accessManager, SIGNAL(finished(QNetworkReply*)), this,
SLOT(slotVersionInfoArrived(QNetworkReply*)) );
QUrl url(Theme::instance()->updateCheckUrl());
QString platform = QLatin1String("stranger");
#ifdef Q_OS_LINUX
platform = QLatin1String("linux");
#endif
#ifdef Q_OS_WIN
platform = QLatin1String( "win32" );
#endif
#ifdef Q_OS_MAC
platform = QLatin1String( "macos" );
#endif
qDebug() << "00 client update check to " << url.toString();
QString sysInfo = getSystemInfo();
if( !sysInfo.isEmpty() ) {
url.addQueryItem(QLatin1String("client"), sysInfo );
}
url.addQueryItem( QLatin1String("version"),
QLatin1String(MIRALL_STRINGIFY(MIRALL_VERSION_FULL)) );
url.addQueryItem( QLatin1String("platform"), platform );
url.addQueryItem( QLatin1String("oem"), theme->appName() );
QNetworkRequest req( url );
req.setRawHeader( QByteArray("User-Agent"), Utility::userAgentString() );
_accessManager->get( req );
}
void UpdateDetector::slotOpenUpdateUrl()
{
QDesktopServices::openUrl(ocClient.web());
}
void UpdateDetector::slotSetVersionSeen()
{
MirallConfigFile cfg;
cfg.setSeenVersion(ocClient.version());
}
QString UpdateDetector::getSystemInfo()
{
#ifdef Q_OS_LINUX
QProcess process;
process.start( QLatin1String("lsb_release -a") );
process.waitForFinished();
QByteArray output = process.readAllStandardOutput();
qDebug() << "Sys Info size: " << output.length();
if( output.length() > 1024 ) output.clear(); // don't send too much.
return QString::fromLocal8Bit( output.toBase64() );
#else
return QString::null;
#endif
}
void UpdateDetector::showDialog()
{
QDialog *msgBox = new QDialog;
QIcon info = msgBox->style()->standardIcon(QStyle::SP_MessageBoxInformation, 0, 0);
int iconSize = msgBox->style()->pixelMetric(QStyle::PM_MessageBoxIconSize, 0, 0);
msgBox->setWindowIcon(info);
QVBoxLayout *layout = new QVBoxLayout(msgBox);
QHBoxLayout *hlayout = new QHBoxLayout;
layout->addLayout(hlayout);
msgBox->setWindowTitle(tr("New Version Available"));
QLabel *ico = new QLabel;
ico->setFixedSize(iconSize, iconSize);
ico->setPixmap(info.pixmap(iconSize));
QLabel *lbl = new QLabel;
QString txt = tr("<p>A new version of the %1 Client is available.</p>"
"<p><b>%2</b> is available for download. The installed version is %3.<p>")
.arg(Theme::instance()->appNameGUI()).arg(ocClient.versionstring())
.arg(QLatin1String(MIRALL_STRINGIFY(MIRALL_VERSION_FULL)));
lbl->setText(txt);
lbl->setTextFormat(Qt::RichText);
lbl->setWordWrap(true);
hlayout->addWidget(ico);
hlayout->addWidget(lbl);
QDialogButtonBox *bb = new QDialogButtonBox;
bb->setWindowFlags(bb->windowFlags() & ~Qt::WindowContextHelpButtonHint);
QPushButton *skip = bb->addButton(tr("Skip update"), QDialogButtonBox::ResetRole);
QPushButton *reject = bb->addButton(tr("Skip this time"), QDialogButtonBox::AcceptRole);
QPushButton *getupdate = bb->addButton(tr("Get update"), QDialogButtonBox::AcceptRole);
connect(skip, SIGNAL(clicked()), msgBox, SLOT(reject()));
connect(reject, SIGNAL(clicked()), msgBox, SLOT(reject()));
connect(getupdate, SIGNAL(clicked()), msgBox, SLOT(accept()));
connect(skip, SIGNAL(clicked()), SLOT(slotSetVersionSeen()));
connect(getupdate, SIGNAL(clicked()), SLOT(slotOpenUpdateUrl()));
layout->addWidget(bb);
msgBox->open();
msgBox->resize(400, msgBox->sizeHint().height());
}
void UpdateDetector::slotVersionInfoArrived( QNetworkReply* reply )
{
if( reply->error() != QNetworkReply::NoError ) {
qDebug() << "Failed to reach version check url: " << reply->errorString();
return;
}
QString xml = QString::fromUtf8(reply->readAll());
bool ok;
ocClient = Owncloudclient::parseString( xml, &ok );
if( ok ) {
// Thats how it looks like if a new version is available:
// <?xml version="1.0"?>
// <owncloudclient>
// <version>1.0.0</version>
// <versionstring>ownCloud Client 1.0.0</versionstring>
// <web>http://ownCloud.org/client/update</web>
// </owncloudclient>
//
// and thats if no new version available:
// <?xml version="1.0"?>
// <owncloudclient>
// <version></version>
// <versionstring></versionstring>
// <web></web>
// </owncloudclient>
MirallConfigFile cfg;
if( ocClient.version().isEmpty() || ocClient.version() == cfg.seenVersion() ) {
qDebug() << "Client is on latest version!";
} else {
showDialog();
}
} else {
qDebug() << "Could not parse update information.";
}
}
}

Просмотреть файл

@ -1,55 +0,0 @@
/*
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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.
*/
#ifndef UPDATEDETECTOR_H
#define UPDATEDETECTOR_H
#include <QObject>
#include "mirall/occinfo.h"
class QNetworkAccessManager;
class QNetworkReply;
namespace Mirall {
class Theme;
class UpdateDetector : public QObject
{
Q_OBJECT
public:
explicit UpdateDetector(QObject *parent = 0);
void versionCheck( Theme * );
signals:
public slots:
private slots:
void slotOpenUpdateUrl();
void slotSetVersionSeen();
void slotVersionInfoArrived( QNetworkReply* );
private:
QString getSystemInfo();
void showDialog();
QNetworkAccessManager *_accessManager;
Owncloudclient ocClient;
};
}
#endif // UPDATEDETECTOR_H

Просмотреть файл

@ -1,7 +1,7 @@
// This file is generated by kxml_compiler from occinfo.xml.
// All changes you do to this file will be lost.
#include "occinfo.h"
#include "updateinfo.h"
#include <QtDebug>
#include <QFile>
@ -11,45 +11,55 @@
namespace Mirall {
void Owncloudclient::setVersion( const QString &v )
void UpdateInfo::setVersion( const QString &v )
{
mVersion = v;
}
QString Owncloudclient::version() const
QString UpdateInfo::version() const
{
return mVersion;
}
void Owncloudclient::setVersionstring( const QString &v )
void UpdateInfo::setVersionString( const QString &v )
{
mVersionstring = v;
mVersionString = v;
}
QString Owncloudclient::versionstring() const
QString UpdateInfo::versionString() const
{
return mVersionstring;
return mVersionString;
}
void Owncloudclient::setWeb( const QString &v )
void UpdateInfo::setWeb( const QString &v )
{
mWeb = v;
}
QString Owncloudclient::web() const
QString UpdateInfo::web() const
{
return mWeb;
}
Owncloudclient Owncloudclient::parseElement( const QDomElement &element, bool *ok )
void UpdateInfo::setDownloadUrl( const QString &v )
{
mDownloadUrl = v;
}
QString UpdateInfo::downloadUrl() const
{
return mDownloadUrl;
}
UpdateInfo UpdateInfo::parseElement( const QDomElement &element, bool *ok )
{
if ( element.tagName() != QLatin1String("owncloudclient") ) {
qCritical() << "Expected 'owncloudclient', got '" << element.tagName() << "'.";
if ( ok ) *ok = false;
return Owncloudclient();
return UpdateInfo();
}
Owncloudclient result = Owncloudclient();
UpdateInfo result = UpdateInfo();
QDomNode n;
for( n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) {
@ -58,11 +68,14 @@ Owncloudclient Owncloudclient::parseElement( const QDomElement &element, bool *o
result.setVersion( e.text() );
}
else if ( e.tagName() == QLatin1String("versionstring") ) {
result.setVersionstring( e.text() );
result.setVersionString( e.text() );
}
else if ( e.tagName() == QLatin1String("web") ) {
result.setWeb( e.text() );
}
else if ( e.tagName() == QLatin1String("downloadurl") ) {
result.setDownloadUrl( e.text() );
}
}
@ -70,28 +83,31 @@ Owncloudclient Owncloudclient::parseElement( const QDomElement &element, bool *o
return result;
}
void Owncloudclient::writeElement( QXmlStreamWriter &xml )
void UpdateInfo::writeElement( QXmlStreamWriter &xml )
{
xml.writeStartElement( QLatin1String("owncloudclient") );
if ( !version().isEmpty() ) {
xml.writeTextElement( QLatin1String("version"), version() );
}
if ( !versionstring().isEmpty() ) {
xml.writeTextElement( QLatin1String("versionstring"), versionstring() );
if ( !versionString().isEmpty() ) {
xml.writeTextElement( QLatin1String("versionstring"), versionString() );
}
if ( !web().isEmpty() ) {
xml.writeTextElement( QLatin1String("web"), web() );
}
if ( !downloadUrl().isEmpty() ) {
xml.writeTextElement( QLatin1String("downloadurl"), web() );
}
xml.writeEndElement();
}
Owncloudclient Owncloudclient::parseFile( const QString &filename, bool *ok )
UpdateInfo UpdateInfo::parseFile( const QString &filename, bool *ok )
{
QFile file( filename );
if ( !file.open( QIODevice::ReadOnly ) ) {
qCritical() << "Unable to open file '" << filename << "'";
if ( ok ) *ok = false;
return Owncloudclient();
return UpdateInfo();
}
QString errorMsg;
@ -100,18 +116,18 @@ Owncloudclient Owncloudclient::parseFile( const QString &filename, bool *ok )
if ( !doc.setContent( &file, false, &errorMsg, &errorLine, &errorCol ) ) {
qCritical() << errorMsg << " at " << errorLine << "," << errorCol;
if ( ok ) *ok = false;
return Owncloudclient();
return UpdateInfo();
}
bool documentOk;
Owncloudclient c = parseElement( doc.documentElement(), &documentOk );
UpdateInfo c = parseElement( doc.documentElement(), &documentOk );
if ( ok ) {
*ok = documentOk;
}
return c;
}
Owncloudclient Owncloudclient::parseString( const QString &xml, bool *ok )
UpdateInfo UpdateInfo::parseString( const QString &xml, bool *ok )
{
QString errorMsg;
int errorLine, errorCol;
@ -119,18 +135,18 @@ Owncloudclient Owncloudclient::parseString( const QString &xml, bool *ok )
if ( !doc.setContent( xml, false, &errorMsg, &errorLine, &errorCol ) ) {
qCritical() << errorMsg << " at " << errorLine << "," << errorCol;
if ( ok ) *ok = false;
return Owncloudclient();
return UpdateInfo();
}
bool documentOk;
Owncloudclient c = parseElement( doc.documentElement(), &documentOk );
UpdateInfo c = parseElement( doc.documentElement(), &documentOk );
if ( ok ) {
*ok = documentOk;
}
return c;
}
bool Owncloudclient::writeFile( const QString &filename )
bool UpdateInfo::writeFile( const QString &filename )
{
QFile file( filename );
if ( !file.open( QIODevice::WriteOnly ) ) {

Просмотреть файл

@ -1,7 +1,7 @@
// This file is generated by kxml_compiler from occinfo.xml.
// All changes you do to this file will be lost.
#ifndef OCCINFO_H
#define OCCINFO_H
#ifndef UPDATEINFO_H
#define UPDATEINFO_H
#include <QString>
#include <QDomElement>
@ -9,30 +9,33 @@
namespace Mirall {
class Owncloudclient
class UpdateInfo
{
public:
void setVersion( const QString &v );
QString version() const;
void setVersionstring( const QString &v );
QString versionstring() const;
void setVersionString( const QString &v );
QString versionString() const;
void setWeb( const QString &v );
QString web() const;
void setDownloadUrl( const QString &v );
QString downloadUrl() const;
/**
Parse XML object from DOM element.
*/
static Owncloudclient parseElement( const QDomElement &element, bool *ok );
static UpdateInfo parseElement( const QDomElement &element, bool *ok );
void writeElement( QXmlStreamWriter &xml );
static Owncloudclient parseFile( const QString &filename, bool *ok );
static Owncloudclient parseString( const QString &xml, bool *ok );
static UpdateInfo parseFile( const QString &filename, bool *ok );
static UpdateInfo parseString( const QString &xml, bool *ok );
bool writeFile( const QString &filename );
private:
QString mVersion;
QString mVersionstring;
QString mVersionString;
QString mWeb;
QString mDownloadUrl;
};
} // namespace Mirall
#endif
#endif // UPDATEINFO_H

40
src/mirall/updater.cpp Normal file
Просмотреть файл

@ -0,0 +1,40 @@
/*
* Copyright (C) by Daniel Molkentin <danimo@owncloud.com>
*
* This program 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; version 2 of the License.
*
* This program 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.
*/
#include "mirall/updater.h"
#include "mirall/sparkleupdater.h"
#include "mirall/genericupdater.h"
namespace Mirall {
Updater *Updater::_instance = 0;
Updater * Updater::instance()
{
if(!_instance) {
_instance = create();
}
return _instance;
}
Updater *Updater::create()
{
#ifdef Q_OS_MAC
return new SparkleUpdater(QLatin1String("https://updates.owncloud.com/testing/feed.rss"));
#else
// the best we can do is notify about updates
return new GenericUpdater(QUrl("https://updates.owncloud.com/testing/"));
#endif
}
} // namespace Mirall

42
src/mirall/updater.h Normal file
Просмотреть файл

@ -0,0 +1,42 @@
/*
* Copyright (C) by Daniel Molkentin <danimo@owncloud.com>
*
* This program 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; version 2 of the License.
*
* This program 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.
*/
#ifndef UPDATER_H
#define UPDATER_H
#include <QObject>
namespace Mirall {
class Updater {
public:
enum UpdateState { NoUpdate = 0, UpdateAvailable, UpdateFailed };
static Updater *instance();
virtual void checkForUpdate() = 0;
virtual void backgroundCheckForUpdate() = 0;
virtual UpdateState updateState() const = 0;
virtual void performUpdate() {}
virtual void showFallbackMessage() {}
private:
static Updater *create();
static Updater *_instance;
};
} // namespace Mirall
#endif // UPDATER_H

Просмотреть файл

@ -462,5 +462,14 @@ bool Utility::isUnix()
#endif
}
bool Utility::isLinux()
{
#ifdef Q_OS_LINUX
return true;
#else
return false;
#endif
}
} // namespace Mirall

Просмотреть файл

@ -58,6 +58,7 @@ namespace Utility
bool isWindows();
bool isMac();
bool isUnix();
bool isLinux(); // use with care
}
}

Просмотреть файл

@ -29,5 +29,4 @@
#define MIRALL_VERSION_STRING "@MIRALL_VERSION_STRING@"
#endif // VERSION_H