зеркало из https://github.com/nextcloud/desktop.git
New Updater for Windows, passive notification on Linux, Sparkle on Mac
This commit is contained in:
Родитель
93239cbdca
Коммит
dc9f145a24
|
@ -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
|
||||
|
|
26
src/main.cpp
26
src/main.cpp
|
@ -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>&Restart && 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
|
|
@ -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
|
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче