diff --git a/CMakeLists.txt b/CMakeLists.txt index 989b20296..c3d327af4 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,6 +39,12 @@ # Setup basic variables. project(rssguard) +if(WIN32 OR OS2) + project(rssguard_updater) + + set(UPDATER_EXE_NAME "rssguard_updater") +endif(WIN32 OR OS2) + set(APP_NAME "RSS Guard") set(APP_LOW_NAME "rssguard") set(APP_VERSION "1.9.9.8") @@ -141,6 +147,11 @@ configure_file ( ${CMAKE_CURRENT_BINARY_DIR}/src/definitions/definitions.h ) +configure_file ( + ${PROJECT_SOURCE_DIR}/src/updater/definitions.h.in + ${CMAKE_CURRENT_BINARY_DIR}/src/updater/definitions.h +) + # Define some useful DEBUG for, ehrm, debug build. if(CMAKE_BUILD_TYPE STREQUAL "release" OR CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RELEASE") message(STATUS "[${APP_LOW_NAME}] A release build (non-debug) is chosen. Debugging outputs are silently ignored.") @@ -452,6 +463,26 @@ set(APP_TEXT resources/text/AUTHORS ) +# Setup source & header files for "rssguard_updater". +if(WIN32 OR OS2) + set(UPDATER_SOURCES + # QTSINGLEAPPLICATION sources. + src/qtsingleapplication/qtlocalpeer.cpp + src/qtsingleapplication/qtsinglecoreapplication.cpp + + src/updater/detector.cpp + src/updater/main.cpp + ) + + set(UPDATER_HEADERS + # QTSINGLEAPPLICATION headers. + src/qtsingleapplication/qtlocalpeer.h + src/qtsingleapplication/qtsinglecoreapplication.h + + src/updater/detector.h + ) +endif(WIN32 OR OS2) + # Add custom icon on Mac OS X. if(APPLE) SET (APP_SOURCES ${APP_SOURCES} resources/graphics/rssguard.icns) @@ -474,6 +505,11 @@ else(${USE_QT_5}) # Load translations. qt4_add_translation(APP_QM ${APP_TRANSLATIONS}) + + # Setup Qt for "rssguard_updater". + if(WIN32 OR OS2) + qt4_wrap_cpp(UPDATER_MOC ${UPDATER_HEADERS}) + endif(WIN32 OR OS2) endif(${USE_QT_5}) # Include additional directory paths. @@ -487,53 +523,35 @@ include_directories ( ${CMAKE_CURRENT_BINARY_DIR}/src ) +# Compile "rssguard_updater" utility on supported platforms. if(WIN32 OR OS2) - project(updater) - - set(UPDATER_SOURCES - # QTSINGLEAPPLICATION sources. - src/qtsingleapplication/qtlocalpeer.cpp - src/qtsingleapplication/qtsinglecoreapplication.cpp - - src/updater/detector.cpp - src/updater/main.cpp - ) - - set(UPDATER_HEADERS - # QTSINGLEAPPLICATION headers. - src/qtsingleapplication/qtlocalpeer.h - src/qtsingleapplication/qtsinglecoreapplication.h - - src/updater/detector.h - ) + message(STATUS "[${APP_LOW_NAME}] RSS Guard updater will be compiled.") if(${USE_QT_5}) - add_executable("updater" + add_executable(${UPDATER_EXE_NAME} ${UPDATER_SOURCES} ) # Use modules from Qt. - qt5_use_modules(updater + qt5_use_modules(rssguard_updater Core Network ) else(${USE_QT_5}) - qt4_wrap_cpp(UPDATER_MOC ${UPDATER_HEADERS}) - - add_executable("updater" + add_executable(${UPDATER_EXE_NAME} ${UPDATER_SOURCES} ${UPDATER_MOC} ) # Link modules from Qt. - target_link_libraries("updater" + target_link_libraries(${UPDATER_EXE_NAME} ${QT_QTCORE_LIBRARY} ${QT_QTNETWORK_LIBRARY} ) endif(${USE_QT_5}) endif(WIN32 OR OS2) -# Setup compilation for Qt 5. +# Compile "rssguard" if(${USE_QT_5}) add_executable(${EXE_NAME} WIN32 MACOSX_BUNDLE ${APP_SOURCES} @@ -567,7 +585,7 @@ else(${USE_QT_5}) ) # Link modules from Qt. - target_link_libraries( ${EXE_NAME} + target_link_libraries(${EXE_NAME} ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTNETWORK_LIBRARY} @@ -605,6 +623,10 @@ if(WIN32 OR OS2) DESTINATION ./l10n) install(FILES ${APP_TEXT} DESTINATION ./) + + # Copy "7za" utility. + install(FILES resources/7za/7za.exe resources/7za/7za_license.txt + DESTINATION ./) elseif(APPLE) message(STATUS "[${APP_LOW_NAME}] You will probably install on Mac OS X.") diff --git a/src/definitions/definitions.h.in b/src/definitions/definitions.h.in index 1197a36b0..7a6a9a6c4 100644 --- a/src/definitions/definitions.h.in +++ b/src/definitions/definitions.h.in @@ -174,6 +174,7 @@ #define APP_ICON_PATH APP_PREFIX + QString("/share/pixmaps/@APP_LOW_NAME@.png") #define APP_ICON_PLAIN_PATH APP_PREFIX + QString("/share/rssguard/icons/@APP_LOW_NAME@_plain.png") #elif defined(Q_OS_WIN) || defined(Q_OS_OS2) +#define APP_UPDATER_EXECUTABLE "rssguard_updater.exe" #define APP_LANG_PATH QApplication::applicationDirPath() + QString("/l10n") #define APP_SKIN_PATH QApplication::applicationDirPath() + QString("/skins") #define APP_INFO_PATH QApplication::applicationDirPath() diff --git a/src/gui/formupdate.cpp b/src/gui/formupdate.cpp index c97768386..163b233f5 100755 --- a/src/gui/formupdate.cpp +++ b/src/gui/formupdate.cpp @@ -142,19 +142,18 @@ void FormUpdate::startUpdate() { // ze je otevreny modalni okno. close(); -#if defined(Q_OS_WIN32) + QProcess::startDetached(APP_UPDATER_EXECUTABLE, + QStringList() << temp_directory <applicationFilePath() << output_file.fileName()); + /* ShellExecute(0, 0, - (wchar_t *) QString("updater.exe").utf16(), + (wchar_t *) QString(APP_UPDATER_EXECUTABLE).utf16(), (wchar_t *) QString("\"%1\" \"%2\" \"%3\"").arg(temp_directory, qApp->applicationFilePath(), output_file.fileName()).utf16(), 0, SW_SHOWNORMAL); -#elif defined(Q_OS_OS2) - -#endif - // TODO: vetev pro osn + */ } else { // TODO: chyba - nelze zapisovat do souboru diff --git a/src/updater/definitions.h.in b/src/updater/definitions.h.in new file mode 100644 index 000000000..44ca5ad18 --- /dev/null +++ b/src/updater/definitions.h.in @@ -0,0 +1,10 @@ +#ifndef DEFINITIONS_H_IN +#define DEFINITIONS_H_IN + +#define RSSGUARD_LOW_NAME "@APP_LOW_NAME@" + +#define UPDATER_QUIT_INSTANCE "app_quit" +#define UPDATER_IS_RUNNING "app_is_running" +#define EXECUTABLE_7ZA "7za.exe" + +#endif // DEFINITIONS_H_IN diff --git a/src/updater/main.cpp b/src/updater/main.cpp index 6b73dd46c..6eb9bb639 100644 --- a/src/updater/main.cpp +++ b/src/updater/main.cpp @@ -17,6 +17,7 @@ #include "qtsingleapplication/qtsinglecoreapplication.h" #include "updater/detector.h" +#include "updater/definitions.h" #include #include @@ -52,10 +53,10 @@ bool removeDir(const QString & dirName) { return result; } -void copyPath(QString src, QString dst) { +bool copyPath(QString src, QString dst) { QDir dir(src); if (! dir.exists()) { - return; + return false; } foreach (QString d, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) { @@ -65,16 +66,35 @@ void copyPath(QString src, QString dst) { } foreach (QString f, dir.entryList(QDir::Files)) { - QFile::copy(src + QDir::separator() + f, dst + QDir::separator() + f); + QString original_file = src + QDir::separator() + f; + QString destination_file = dst + QDir::separator() + f; + + if (!QFile::exists(destination_file) || QFile::remove(destination_file)) { + if (QFile::copy(src + QDir::separator() + f, destination_file)) { + qDebug("Copied %s", qPrintable(f)); + } + else { + qDebug("Failed to copy file '%s'", qPrintable(original_file)); + } + } + else { + qDebug("Failed to remove file '%s'", qPrintable(original_file)); + } } + + return true; } int main(int argc, char *argv[]) { // Instantiate base application object. - QtSingleCoreApplication application("rssguard", argc, argv); + QtSingleCoreApplication application(RSSGUARD_LOW_NAME, argc, argv); if (argc != 4) { - qDebug("Insufficient arguments passed. Quitting RSS Guard updater..."); + qDebug("Insufficient arguments passed. Update process cannot proceed."); + qDebug("Press any key to exit updater..."); + + std::cin.ignore(std::numeric_limits::max(), '\n'); + return EXIT_FAILURE; } @@ -92,10 +112,19 @@ int main(int argc, char *argv[]) { qDebug("\n===== directories & files =====\n"); // Check if main RSS Guard instance is running. - if (application.sendMessage("app_quit")) { + if (application.sendMessage(UPDATER_QUIT_INSTANCE)) { qDebug("RSS Guard application is running. Quitting it."); } + if (!QFile::exists(update_archive)) { + qDebug("Update file '%s' does not exist.", qPrintable(update_archive)); + qDebug("Press any key to exit updater..."); + + std::cin.ignore(std::numeric_limits::max(), '\n'); + + return EXIT_FAILURE; + } + Detector detector; qDebug().nospace() << "Running updater in thread: \'" << @@ -105,15 +134,25 @@ int main(int argc, char *argv[]) { QObject::connect(&application, SIGNAL(messageReceived(QString)), &detector, SLOT(handleMessage(QString))); - QString extractor_program("7za.exe"); + QString extractor_program(EXECUTABLE_7ZA); QStringList arguments; - QString output_temp_directory = temp_directory + QDir::separator() + "rssguard"; + QString output_temp_directory = temp_directory + QDir::separator() + RSSGUARD_LOW_NAME; // Remove old folders. if (QDir(output_temp_directory).exists()) { - removeDir(output_temp_directory); + if (!removeDir(output_temp_directory)) { + qDebug("Cleanup of old temporary files failed. Press any key to exit updater..."); + + std::cin.ignore(std::numeric_limits::max(), '\n'); + + return EXIT_FAILURE; + } } + qDebug("Update files are ready. Press any key to proceed..."); + + std::cin.ignore(std::numeric_limits::max(), '\n'); + arguments << "x" << update_archive << "-r" << "-y" << QString("-o%1").arg(output_temp_directory); @@ -146,24 +185,38 @@ int main(int argc, char *argv[]) { qDebug("\n===== copying =====\n"); // Find "rssguard" subfolder path in + QFileInfoList rssguard_temp_root = QDir(output_temp_directory).entryInfoList(QDir::Dirs | + QDir::NoDotAndDotDot | + QDir::NoSymLinks); + + if (rssguard_temp_root.size() != 1) { + qDebug("Could not find root of downloaded application data."); + + return EXIT_FAILURE; + } + + QString rssguard_single_temp_root = rssguard_temp_root.at(0).absoluteFilePath(); + // TODO: upravit copyPath aby prepisoval soubory kdyz je kopiruje // a to udelat tak ze se ten cilovej soubor pokusi smazat // a az pak nakopiruje. - copyPath(output_temp_directory, rssguard_path); + if (!copyPath(rssguard_single_temp_root, rssguard_path)) { + qDebug("Critical error appeared during copying of application files."); + } qDebug("\n===== copying =====\n"); qDebug("\n===== cleanup =====\n"); removeDir(output_temp_directory); + QFile::remove(update_archive); - qDebug("\n===== cleanup =====\n\n\n"); - + qDebug("\n===== cleanup =====\n"); qDebug("Press any key to exit updater and start RSS Guard."); - std::cin.ignore(); + std::cin.ignore(std::numeric_limits::max(), '\n'); QProcess::startDetached(rssguard_executable);