aheinecke@404: /* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik aheinecke@404: * Software engineering by Intevation GmbH aheinecke@404: * aheinecke@404: * This file is Free Software under the GNU GPL (v>=2) aheinecke@404: * and comes with ABSOLUTELY NO WARRANTY! aheinecke@404: * See LICENSE.txt for details. aheinecke@404: */ aheinecke@0: #ifndef MAINWINDOW_H aheinecke@0: #define MAINWINDOW_H aheinecke@0: aheinecke@71: /** aheinecke@71: * @file mainwindow.h aheinecke@71: * @brief Main UI controller aheinecke@71: */ aheinecke@71: rrenkert@153: #include aheinecke@16: #include rrenkert@155: #include rrenkert@189: #include rrenkert@189: #include rrenkert@271: #include rrenkert@432: #include rrenkert@432: #include rrenkert@584: #include andre@1252: #include andre@1371: #include aheinecke@16: aheinecke@16: #include "downloader.h" aheinecke@71: #include "certificatelist.h" rrenkert@584: #include "certificatelistwidget.h" andre@722: #include "textoverlaybutton.h" andre@871: #include "trayicon.h" aheinecke@0: class QMenu; aheinecke@0: class QAction; aheinecke@19: class QTimer; andre@693: class QPushButton; aheinecke@0: rrenkert@432: andre@1255: /** @brief Main UI controller andre@1255: * andre@1255: * The MainWindow controls the logic of the Application andre@1255: * it is the central piece that controls the state and starts andre@1255: * updates / certificate installation. andre@1255: * It also controls the UI widgets for the various certificate lists. andre@1255: */ rrenkert@153: class MainWindow : public QMainWindow aheinecke@0: { aheinecke@0: Q_OBJECT aheinecke@0: aheinecke@0: public: aheinecke@365: /**@brief create a new Main Window object aheinecke@365: * aheinecke@365: * In tray mode this window is not shown and only shows aheinecke@365: * notification messages if there is some actionable state aheinecke@365: * reached. If tray mode is true it also exits after aheinecke@365: * an update check. aheinecke@365: * andre@1371: * The sigDt parameter is used to determine if a software andre@1371: * update should be installed. andre@1371: * aheinecke@365: * @param[in] trayMode set the tray mode andre@1371: * @param[in] sigDt the datetime when the binary was signed. aheinecke@365: * */ andre@1371: MainWindow(bool trayMode, const QDateTime& sigDt = QDateTime()); aheinecke@0: andre@1228: /**@brief set the current message to be shown andre@1228: * andre@1228: * The message will be shown at intervals in the system tray andre@1228: * or as a messagebox if no stystemtray is available. andre@1228: * andre@1228: * @param [in] message The message to show. andre@1228: */ aheinecke@0: void setMessage(const QString message) {mCurMessage = message;} andre@1228: /**@brief accessor for the current message. andre@1228: * andre@1228: * @returns the currently shown message.*/ aheinecke@0: QString getMessage() {return mCurMessage;} aheinecke@0: andre@1228: /** andre@1228: * @enum CurrentState andre@1228: * @brief The internal state of the application andre@1228: */ aheinecke@16: enum CurrentState { andre@1255: /*! A new certificate list is available. */ andre@1255: NewListAvailable, andre@1255: /*! A new Software is avaialable. */ andre@1255: NewSoftwareAvailable, andre@1255: /*! Download in progress. */ andre@1255: DownloadingSW, andre@1255: /*! An error happened on the last connection. */ andre@1255: TransferError, andre@1255: /*! Update was susccessfull but nothing new is available. */ andre@1255: NothingChanged aheinecke@16: }; andre@1227: andre@1227: /** andre@1227: * @enum LongTimeErrors andre@1227: * @brief Errors that should be stored and only shown after some time has elapsed. andre@1227: */ andre@1227: enum LongTimeErrors { andre@1255: /*! The downloaded Software was invalid. */ andre@1255: lteInvalidSoftware, andre@1255: /*! The SSL certificate of the download server was wrong. */ andre@1255: lteInvalidCertificate, andre@1255: /*! The downloaded Certificate List was invalid. */ andre@1255: lteInvalidList, andre@1255: /*! No connection to the server could be established. */ andre@1227: lteNoConnection andre@1227: }; andre@1227: andre@1227: /** @brief accessor for the current state. */ aheinecke@16: CurrentState getState() {return mCurState;} andre@1228: /** @brief set the current state. */ aheinecke@16: void setState(CurrentState state) {mCurState = state;} aheinecke@16: aheinecke@0: private slots: andre@1228: /** @brief Shows the current message to the user. */ aheinecke@0: void showMessage(); andre@1228: /** @brief User has clicked on the message notification. */ aheinecke@0: void iconActivated(QSystemTrayIcon::ActivationReason reason); andre@1228: /** @brief Check if new updates are available. andre@1228: * andre@1373: * Wether the software should be downloaded or not is determined by andre@1373: * the mDownloadSWAccepted value. andre@1228: */ andre@1373: void checkUpdates(); andre@1228: /**@brief parse a new certificate list and update the UI*/ aheinecke@16: void handleNewList(const QString& fileName, const QDateTime& modDate); andre@1228: /**@brief handle a Software update, update state and inform the user */ aheinecke@16: void handleNewSW(const QString& fileName, const QDateTime& modDate); andre@1228: /**@brief an error occured while downloading.*/ aheinecke@45: void downloaderError(const QString &message, SSLConnection::ErrorCode error); aheinecke@71: /** @brief Trigger the appropiate action depending on the state */ aheinecke@71: void messageClicked(); andre@1228: /** @brief An error occured during certificate installation .*/ aheinecke@365: void installerError(const QString& errMsg); andre@1228: /** @brief Certificate installation was successful. */ andre@389: void installerSuccess(); andre@1228: /** @brief Install the currently selected certificates */ aheinecke@365: void installCerts(); andre@1228: /** @brief Handle a toggle action in the manual certificate list */ rrenkert@640: void toggleInManual(bool state, const Certificate &cert); andre@1228: /** @brief Remove a certificate from the manual list. */ rrenkert@640: void removeFromManual(bool state, const Certificate &cert); andre@1252: /** @brief Restart the application */ andre@1252: void updaterFinished(int exitCode, QProcess::ExitStatus status); aheinecke@551: rrenkert@584: void togglePages(int button); rrenkert@584: void toggleUpdatesNew(); rrenkert@584: void toggleUpdatesRemove(); rrenkert@584: void toggleUpdatesManual(); andre@716: andre@716: /** Reflect change list states in the UI andre@716: * andre@716: * This slot should be called each time the contents or selection andre@716: * state of one of the certificate lists change to update the andre@716: * UI elements accordingly. andre@716: * andre@716: * @param[in] selected unused. */ rrenkert@628: void listChanged(int selected); rrenkert@584: andre@609: /** @brief check for running software that needs to close before installing andre@609: * andre@609: * This function calls installCerts if no software is running otherwise andre@609: * it informs the user about the software that still needs to be closed. andre@609: */ andre@609: void checkAndInstallCerts(); andre@609: aheinecke@551: /** @brief get the last modified date on the download server for aheinecke@551: * the current version. aheinecke@551: * aheinecke@551: * After the initial installation this function can be used to aheinecke@551: * determine the DateTime that corresponds to the currently installed aheinecke@551: * version on the download server. aheinecke@551: * aheinecke@551: * Calls setLastModifiedSWDate on success. Otherwise downloaderError aheinecke@551: * is triggered. */ aheinecke@551: void getLastModForCurrentVersion(); aheinecke@551: aheinecke@551: /** @brief set the last modified software date/time aheinecke@551: * aheinecke@551: * The last modifiedSWDate is the corresponding last modified aheinecke@551: * timestamp from the download server vor the currently installed version. aheinecke@551: */ aheinecke@551: void setLastModifiedSWDate(const QDateTime &date); rrenkert@486: andre@372: /** @brief saves the currently unselected certificates andre@372: * andre@372: * This creates / updates a qsettings section that andre@372: * [unselected] that contains the certificates that andre@372: * were unselected previously. andre@372: * andre@372: * Unselected are certificates that are unchecked andre@372: * in the certListWidget andre@372: * andre@372: * Returns false on error. andre@372: */ rrenkert@640: bool saveUnselectedCertificates(QStringList unselected); andre@372: andre@372: /** @brief loads previously unselected certificates from settings andre@372: * andre@372: * The certificates are strored in the list mPreviouslyUnselected. andre@372: * andre@372: * On error mPreviouslyUnselected is empty after this call. andre@372: */ andre@372: void loadUnselectedCertificates(); andre@372: andre@708: /** @brief log / store a successful downloader run andre@708: * andre@708: * A downloader run is successful if the finished signal andre@708: * is emited and the state is not TransferError andre@708: */ andre@708: void updateCheckSuccess(); andre@708: andre@940: /** @brief open the manual in an external browser window andre@940: */ andre@940: void showHelp(); andre@940: andre@956: /** @brief open the proxy settings dialog */ andre@956: void showProxySettings(); andre@956: andre@686: protected: andre@690: virtual void closeEvent(QCloseEvent *event); andre@686: aheinecke@559: protected slots: aheinecke@559: /** @brief cleanup and close the main window aheinecke@559: * aheinecke@559: * Perform a clean exit (saving state etc.) and close aheinecke@559: * the application */ aheinecke@563: virtual void closeApp(); rrenkert@447: aheinecke@559: /* @brief Execute the file fileName to install the softwareupdate. aheinecke@559: * aheinecke@559: * Once the installer process is started this function terminates aheinecke@559: * the application. */ aheinecke@559: void installNewSW(const QString& fileName, const QDateTime& modDate); aheinecke@559: andre@1061: /** @brief show an error message andre@1061: * andre@1061: * This is a wrapper around QMessageBox to allow for central andre@1061: * styling of error messages. andre@1061: */ andre@1061: void showErrorMessage(const QString &msg); andre@1061: andre@722: signals: andre@722: /** @brief emits the changecount as a string when it changes */ andre@722: void changesChanged(const QString& cnt); andre@722: aheinecke@0: private: andre@1227: /** @brief Get a installer file name that can be shown to a user. andre@1227: * andre@1227: * This copys the real file to a temporary location with a user andre@1227: * visible localized file name. Does error Handling. andre@1227: * andre@1227: * @param [in] realFileName The original file name. andre@1227: * andre@1227: * @returns a null string in case on errors. The new filename andre@1227: * otherwise. andre@1227: */ andre@1227: QString getPrettyInstallerName(QString realFileName); andre@1227: andre@716: /** @brief the combined number of changes made in all lists */ andre@716: int changeCount(); andre@716: andre@722: /** @brief use this to set the change count */ andre@722: void setChangeCount(int cnt); andre@722: aheinecke@587: /** @brief check the integrity of available certificate lists. aheinecke@71: * aheinecke@594: * Note: Do not use this as a local trust check as this only works on aheinecke@71: * FileNames where the underlying files can change. This aheinecke@71: * is just meant to check if the downloaded data was somehow andre@389: * removed or corrupted. It also initializes mListToInstall andre@389: * and mInstalledList. aheinecke@71: */ aheinecke@587: void verifyListData(); aheinecke@587: aheinecke@587: /** @brief check the integrity of available software updates. aheinecke@587: * aheinecke@594: * Note: Do not use this as a local trust check as this only works on aheinecke@587: * FileNames where the underlying files can change. This aheinecke@587: * is just meant to check if the downloaded data was somehow aheinecke@587: * removed or corrupted. aheinecke@587: */ aheinecke@587: void verifySWData(); aheinecke@587: andre@1227: /** @brief note an long time error in the settings and show a message. andre@1227: * andre@1227: * Saves a software verify error in the settings and notifies the andre@1227: * user if necessary. andre@1227: * andre@1227: * @param [in] lte The error to handle. andre@1227: * @param [in] reset weather or not the error count should be reset. andre@1227: * andre@1227: **/ andre@1227: void handleLTE(LongTimeErrors lte, bool reset = false); andre@1227: andre@1373: /** @brief schedule an update check retry or close the application. andre@1373: * andre@1373: * An update check retry is scheduled base on getNextUpdateInterval. andre@1373: * If getNextUpdateInterval returns a negative value the application andre@1373: * is closed if the parameter close is true. andre@1373: * andre@1373: * This function also increases the failed connection count. andre@1373: */ andre@1373: void scheduleFailureRetryOrClose(bool close); andre@1373: andre@1227: /** @brief note a verify error in the settings and show a message andre@1227: * andre@1227: * Saves a software verify error in the settings and notifies the andre@1227: * user if necessary.*/ andre@1227: void swVerifyError(); andre@1227: aheinecke@0: void createTrayIcon(); aheinecke@0: void createActions(); andre@743: void loadCertificateList(); andre@743: andre@743: /** @brief UI setup */ andre@739: void setupGUI(); andre@743: andre@743: /** @brief create and set up the info widget (accessible via button panel) */ andre@743: QWidget *createInfoWidget(); andre@743: /** @brief create and set up the updates widget (accessible via button panel) */ andre@743: QWidget *createUpdatesWidget(); andre@743: /** @brief create and set up the certifcates to install widget andre@743: * (accessible via button panel) */ andre@743: QWidget *createInstallWidget(); andre@743: /** @brief create and set up the certifcates to remove widget andre@743: * (accessible via button panel) */ andre@743: QWidget *createRemoveWidget(); aheinecke@2: andre@1061: /** @brief true if the software is running in tray mode*/ aheinecke@365: const bool mTrayMode; andre@1061: andre@1061: /** @brief The currently shown message */ aheinecke@0: QString mCurMessage; andre@1061: /** @brief The version the Software thinks is installed */ aheinecke@16: QString mInstalledSWVersion; andre@1061: /** @brief The certificate list the Software thinks is installed */ aheinecke@16: QString mInstalledListVersion; aheinecke@16: aheinecke@17: QSettings mSettings; aheinecke@0: andre@871: TrayIcon *mTrayIcon; aheinecke@19: QTimer *mMessageTimer; aheinecke@0: QMenu *mTrayMenu; aheinecke@0: QAction *mCheckUpdates; aheinecke@2: QAction *mQuitAction; aheinecke@16: CurrentState mCurState; rrenkert@155: QMenuBar *mMenuBar; andre@693: QPushButton *mQuitButton; aheinecke@71: andre@372: /* The current list that should be installed */ aheinecke@71: CertificateList mListToInstall; andre@389: /* The last list that we installed */ andre@389: CertificateList mInstalledList; andre@372: /* Previously made "unselect" choices in the form of andre@372: * base64lines with I:/R: prefix */ andre@372: QStringList mPreviouslyUnselected; rrenkert@189: rrenkert@456: QLabel *mCurrentListDate; rrenkert@456: QLabel *mNewListDate; rrenkert@456: rrenkert@584: QButtonGroup *mButtonGroup; rrenkert@584: QWidget *mUpdatesWidget; andre@743: QWidget *mInstallWidget; andre@743: QWidget *mRemoveWidget; andre@743: QWidget *mInfoWidget; rrenkert@584: rrenkert@628: QLabel *mUpdatesHeader; andre@1098: QLabel *mUpdatesDetailsHeader; andre@1098: QLabel *mCertListVersion; andre@1098: QLabel *mCertListVersionContents; andre@708: QLabel *mLastUpdateCheck; andre@754: QLabel *mLastUpdateCheckContents; rrenkert@628: QLabel *mUpdatesNewCertificates; rrenkert@628: QLabel *mUpdatesRemoveCertificates; rrenkert@628: QLabel *mUpdatesManualCertificates; andre@718: QLabel *mUpdatesTip; rrenkert@628: andre@743: /* These are a bit of a pattern break, they should andre@743: * be accessed over the according page widgets. andre@743: * andre@743: * They are initialized in the create*widget functions.*/ rrenkert@584: CertificateListWidget *mUpdatesNew; rrenkert@584: CertificateListWidget *mUpdatesRemove; rrenkert@584: CertificateListWidget *mUpdatesManual; rrenkert@584: CertificateListWidget *mInstallList; rrenkert@628: CertificateListWidget *mRemoveList; rrenkert@652: rrenkert@652: QPushButton *mUpdatesDetailsNew; rrenkert@652: QPushButton *mUpdatesDetailsRemove; rrenkert@652: QPushButton *mUpdatesDetailsManual; andre@716: andre@718: QPushButton *mInstallButton; andre@716: int mChangeCount; andre@1109: bool mManualDetailsShown; andre@1339: int mFailedConnections; andre@1371: QDateTime mSigDt; andre@1373: bool mDownloadSWAccepted; aheinecke@0: }; aheinecke@0: aheinecke@0: #endif // MAINWINDOW_H