diff --git a/.krazy b/.krazy index 88df6034..d9436c32 100644 --- a/.krazy +++ b/.krazy @@ -1,7 +1,7 @@ CHECKSETS qt4,c++,foss #exclude intrusive checks to investigate later -EXCLUDE foreach,nullstrassign +EXCLUDE nullstrassign #KDAB-specific checks EXTRA kdabcopyright diff --git a/CMakeLists.txt b/CMakeLists.txt index 73ff10a2..d3ed99a1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ -PROJECT( Charm ) CMAKE_MINIMUM_REQUIRED( VERSION 2.8.12 ) +PROJECT( Charm CXX ) include(FeatureSummary) @@ -117,7 +117,7 @@ ADD_SUBDIRECTORY( Tests ) CONFIGURE_FILE( CharmCMake.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/CharmCMake.h ) SET( LICENSE_FILE "License.txt" ) -SET( README_FILE "ReadMe.txt" ) +SET( README_FILE "ReadMe.md" ) IF( NOT APPLE ) INSTALL( FILES "${LICENSE_FILE}" "${README_FILE}" DESTINATION ${DOC_INSTALL_DIR} ) ENDIF() @@ -130,6 +130,8 @@ IF (WIN32) IF(PYTHONINTERP_FOUND) + OPTION(CHARM_SIGN_INSTALLER "Sign the installer and the contained files" ON) + SET(EXTRA_PACKAGE_COMMANDS ) FIND_PACKAGE( OpenSSL QUIET) set_package_properties(OpenSSL PROPERTIES @@ -149,6 +151,11 @@ IF (WIN32) set(EXTRA_PACKAGE_COMMANDS ${EXTRA_PACKAGE_COMMANDS} --architecture x86) ENDIF() + IF(CHARM_SIGN_INSTALLER) + set(EXTRA_PACKAGE_COMMANDS ${EXTRA_PACKAGE_COMMANDS} --sign) + ENDIF() + + ADD_CUSTOM_TARGET(package COMMAND ${PYTHON_EXECUTABLE} @@ -162,7 +169,6 @@ IF (WIN32) --applicationIcon "${CMAKE_CURRENT_SOURCE_DIR}/Charm/Icons/Charm.ico" --productLicence "${CMAKE_CURRENT_SOURCE_DIR}/License.txt" ${EXTRA_PACKAGE_COMMANDS} - --sign DEPENDS ${Charm_EXECUTABLE} VERBATIM) diff --git a/Charm/ApplicationCore.cpp b/Charm/ApplicationCore.cpp index f5a3be1d..a1ef3918 100644 --- a/Charm/ApplicationCore.cpp +++ b/Charm/ApplicationCore.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld @@ -31,8 +31,8 @@ #include "Core/CharmExceptions.h" #include "Core/SqLiteStorage.h" -#include "HttpClient/HttpJob.h" #include "Idle/IdleDetector.h" +#include "Lotsofcake/Configuration.h" #include "Widgets/ConfigurationDialog.h" #include "Widgets/NotificationPopup.h" #include "Widgets/TasksView.h" @@ -70,11 +70,12 @@ namespace { static const QByteArray StartTaskCommand = QByteArrayLiteral("start-task: "); +static const QByteArray RaiseWindowCommand = QByteArrayLiteral("raise-window"); } ApplicationCore *ApplicationCore::m_instance = nullptr; -ApplicationCore::ApplicationCore(TaskId startupTask, QObject *parent) +ApplicationCore::ApplicationCore(TaskId startupTask, bool hideAtStart, QObject *parent) : QObject(parent) , m_actionStopAllTasks(this) , m_actionQuit(this) @@ -95,6 +96,8 @@ ApplicationCore::ApplicationCore(TaskId startupTask, QObject *parent) &m_timeTracker, &m_tasksView, &m_eventView }), m_startupTask(startupTask) + , m_hideAtStart(hideAtStart) + #ifdef Q_OS_WIN , m_windowsJumpList(new QWinJumpList(this)) #endif @@ -107,7 +110,7 @@ ApplicationCore::ApplicationCore(TaskId startupTask, QObject *parent) QCoreApplication::setOrganizationName(QStringLiteral("KDAB")); QCoreApplication::setOrganizationDomain(QStringLiteral("kdab.com")); QCoreApplication::setApplicationName(QStringLiteral("Charm")); - QCoreApplication::setApplicationVersion(QStringLiteral(CHARM_VERSION)); + QCoreApplication::setApplicationVersion(CharmVersion()); QLocalSocket uniqueApplicationSocket; QString serverName(QStringLiteral("com.kdab.charm")); @@ -122,16 +125,20 @@ ApplicationCore::ApplicationCore(TaskId startupTask, QObject *parent) #endif uniqueApplicationSocket.connectToServer(serverName, QIODevice::ReadWrite); if (uniqueApplicationSocket.waitForConnected(1000)) { + QByteArray command; if (startupTask != -1) { - QByteArray data(StartTaskCommand + QByteArray::number(startupTask) + '\n'); - qint64 written = uniqueApplicationSocket.write(data); - if (written == -1 || written != data.length()) { - qWarning() << "Failed to pass " << data << " to running charm instance, error: " - << uniqueApplicationSocket.errorString(); - } - uniqueApplicationSocket.flush(); - uniqueApplicationSocket.waitForBytesWritten(); + command = StartTaskCommand + QByteArray::number(startupTask); + } else { + command = RaiseWindowCommand; } + command += '\n'; + qint64 written = uniqueApplicationSocket.write(command); + if (written == -1 || written != command.length()) { + qWarning() << "Failed to pass " << command << " to running charm instance, error: " + << uniqueApplicationSocket.errorString(); + } + uniqueApplicationSocket.flush(); + uniqueApplicationSocket.waitForBytesWritten(); throw AlreadyRunningException(); } @@ -152,21 +159,24 @@ ApplicationCore::ApplicationCore(TaskId startupTask, QObject *parent) qRegisterMetaType("Event"); // exit process (app will only exit once controller says it is ready) - connect(&m_controller, SIGNAL(readyToQuit()), SLOT( - slotControllerReadyToQuit())); + connect(&m_controller, &Controller::readyToQuit, + this, &ApplicationCore::slotControllerReadyToQuit); connectControllerAndModel(&m_controller, m_model.charmDataModel()); Charm::connectControllerAndView(&m_controller, &m_timeTracker); // save the configuration (configuration is managed by the application) - connect(&m_timeTracker, SIGNAL(saveConfiguration()), - SLOT(slotSaveConfiguration())); - connect(&m_timeTracker, SIGNAL(showNotification(QString,QString)), - SLOT(slotShowNotification(QString,QString))); + connect(&m_timeTracker, &CharmWindow::saveConfiguration, + this, &ApplicationCore::slotSaveConfiguration); + connect(&m_timeTracker, &TimeTrackingWindow::showNotification, + this, &ApplicationCore::slotShowNotification); + connect(&m_timeTracker, &TimeTrackingWindow::taskMenuChanged, + this, &ApplicationCore::slotPopulateTrayIconMenu); // save the configuration (configuration is managed by the application) - connect(&m_tasksView, SIGNAL(saveConfiguration()), - SLOT(slotSaveConfiguration())); + connect(&m_tasksView, &TasksView::saveConfiguration, + this, &ApplicationCore::slotSaveConfiguration); + // due to multiple inheritence we can't use the new style connects here connect(&m_tasksView, SIGNAL(emitCommand(CharmCommand*)), &m_timeTracker, SLOT(sendCommand(CharmCommand*))); connect(&m_tasksView, SIGNAL(emitCommandRollback(CharmCommand*)), @@ -177,18 +187,15 @@ ApplicationCore::ApplicationCore(TaskId startupTask, QObject *parent) &m_timeTracker, SLOT(sendCommandRollback(CharmCommand*))); // my own signals: - connect(this, SIGNAL(goToState(State)), SLOT(setState(State)), - Qt::QueuedConnection); - - connect(&m_systrayContextMenu, &QMenu::aboutToShow, this, - &ApplicationCore::slotStartTaskMenuAboutToShow); + connect(this, &ApplicationCore::goToState, + this, &ApplicationCore::setState, Qt::QueuedConnection); // system tray icon: m_actionStopAllTasks.setText(tr("Stop Current Task")); m_actionStopAllTasks.setShortcut(Qt::Key_Escape); m_actionStopAllTasks.setShortcutContext(Qt::ApplicationShortcut); mainView().addAction(&m_actionStopAllTasks); // for the shortcut to work - connect(&m_actionStopAllTasks, SIGNAL(triggered()), SLOT(slotStopAllTasks())); + connect(&m_actionStopAllTasks, &QAction::triggered, this, &ApplicationCore::slotStopAllTasks); m_systrayContextMenu.addAction(&m_actionStopAllTasks); m_systrayContextMenu.addSeparator(); @@ -207,34 +214,35 @@ ApplicationCore::ApplicationCore(TaskId startupTask, QObject *parent) m_actionQuit.setShortcut(Qt::CTRL + Qt::Key_Q); m_actionQuit.setText(tr("Quit")); m_actionQuit.setIcon(Data::quitCharmIcon()); - connect(&m_actionQuit, SIGNAL(triggered(bool)), - SLOT(slotQuitApplication())); + connect(&m_actionQuit, &QAction::triggered, + this, &ApplicationCore::slotQuitApplication); m_actionAboutDialog.setText(tr("About Charm")); - connect(&m_actionAboutDialog, SIGNAL(triggered()), - &mainView(), SLOT(slotAboutDialog())); + connect(&m_actionAboutDialog, &QAction::triggered, + &m_timeTracker, &TimeTrackingWindow::slotAboutDialog); m_actionPreferences.setText(tr("Preferences")); m_actionPreferences.setIcon(Data::configureIcon()); - connect(&m_actionPreferences, SIGNAL(triggered(bool)), - &mainView(), SLOT(slotEditPreferences(bool))); + connect(&m_actionPreferences, &QAction::triggered, + &m_timeTracker, &TimeTrackingWindow::slotEditPreferences); m_actionPreferences.setEnabled(true); m_actionImportFromXml.setText(tr("Import Database from Previous Export...")); - connect(&m_actionImportFromXml, SIGNAL(triggered()), - &mainView(), SLOT(slotImportFromXml())); + connect(&m_actionImportFromXml, &QAction::triggered, + &m_timeTracker, &TimeTrackingWindow::slotImportFromXml); m_actionExportToXml.setText(tr("Export Database...")); - connect(&m_actionExportToXml, SIGNAL(triggered()), - &mainView(), SLOT(slotExportToXml())); + connect(&m_actionExportToXml, &QAction::triggered, + &m_timeTracker, &TimeTrackingWindow::slotExportToXml); m_actionSyncTasks.setText(tr("Update Task Definitions...")); - connect(&m_actionSyncTasks, SIGNAL(triggered()), - &mainView(), SLOT(slotSyncTasks())); + //the signature of QAction::triggered does not match slotSyncTasks + connect(&m_actionSyncTasks,&QAction::triggered, + &m_timeTracker, &TimeTrackingWindow::slotSyncTasksVerbose); m_actionImportTasks.setText(tr("Import and Merge Task Definitions...")); - connect(&m_actionImportTasks, SIGNAL(triggered()), - &mainView(), SLOT(slotImportTasks())); + connect(&m_actionImportTasks, &QAction::triggered, + &m_timeTracker, &TimeTrackingWindow::slotImportTasks); m_actionExportTasks.setText(tr("Export Task Definitions...")); - connect(&m_actionExportTasks, SIGNAL(triggered()), - &mainView(), SLOT(slotExportTasks())); + connect(&m_actionExportTasks, &QAction::triggered, + &m_timeTracker, &TimeTrackingWindow::slotExportTasks); m_actionCheckForUpdates.setText(tr("Check for Updates...")); #if 0 // TODO this role should be set to have the action in the app menu, but that @@ -242,30 +250,30 @@ ApplicationCore::ApplicationCore(TaskId startupTask, QObject *parent) // and Qt doesn't prevent duplicates (#222) m_actionCheckForUpdates.setMenuRole(QAction::ApplicationSpecificRole); #endif - connect(&m_actionCheckForUpdates, SIGNAL(triggered()), - &mainView(), SLOT(slotCheckForUpdatesManual())); + connect(&m_actionCheckForUpdates, &QAction::triggered, + &m_timeTracker, &TimeTrackingWindow::slotCheckForUpdatesManual); m_actionEnterVacation.setText(tr("Enter Vacation...")); - connect(&m_actionEnterVacation, SIGNAL(triggered()), - &mainView(), SLOT(slotEnterVacation())); + connect(&m_actionEnterVacation, &QAction::triggered, + &m_timeTracker, &TimeTrackingWindow::slotEnterVacation); m_actionActivityReport.setText(tr("Activity Report...")); m_actionActivityReport.setShortcut(Qt::CTRL + Qt::Key_A); - connect(&m_actionActivityReport, SIGNAL(triggered()), - &mainView(), SLOT(slotActivityReport())); + connect(&m_actionActivityReport, &QAction::triggered, + &m_timeTracker, &TimeTrackingWindow::slotActivityReport); m_actionWeeklyTimesheetReport.setText(tr("Weekly Timesheet...")); m_actionWeeklyTimesheetReport.setShortcut(Qt::CTRL + Qt::Key_R); - connect(&m_actionWeeklyTimesheetReport, SIGNAL(triggered()), - &mainView(), SLOT(slotWeeklyTimesheetReport())); + connect(&m_actionWeeklyTimesheetReport, &QAction::triggered, + &m_timeTracker, &TimeTrackingWindow::slotWeeklyTimesheetReport); m_actionMonthlyTimesheetReport.setText(tr("Monthly Timesheet...")); m_actionMonthlyTimesheetReport.setShortcut(Qt::CTRL + Qt::Key_M); - connect(&m_actionMonthlyTimesheetReport, SIGNAL(triggered()), - &mainView(), SLOT(slotMonthlyTimesheetReport())); + connect(&m_actionMonthlyTimesheetReport, &QAction::triggered, + &m_timeTracker, &TimeTrackingWindow::slotMonthlyTimesheetReport); // set up idle detection m_idleDetector = IdleDetector::createIdleDetector(this); Q_ASSERT(m_idleDetector); connect(m_idleDetector, SIGNAL(maybeIdle()), SLOT(slotMaybeIdle())); - setHttpActionsVisible(HttpJob::credentialsAvailable()); + setHttpActionsVisible(Lotsofcake::Configuration().isConfigured()); // add default plugin path for deployment QCoreApplication::addLibraryPath(QCoreApplication::applicationDirPath() + QStringLiteral("/plugins")); @@ -289,7 +297,7 @@ ApplicationCore::~ApplicationCore() m_instance = nullptr; } -void ApplicationCore::slotStartTaskMenuAboutToShow() +void ApplicationCore::slotPopulateTrayIconMenu() { const auto newActions = m_timeTracker.menu()->actions(); if (m_taskActions == newActions) @@ -307,15 +315,17 @@ void ApplicationCore::slotHandleUniqueApplicationConnection() if (!socket->canReadLine()) return; while (socket->canReadLine()) { - QByteArray data = socket->readLine().trimmed(); + const QByteArray data = socket->readLine().trimmed(); if (data.startsWith(StartTaskCommand)) { bool ok = true; - TaskId id = data.mid(StartTaskCommand.length()).toInt(&ok); + const TaskId id = data.mid(StartTaskCommand.length()).toInt(&ok); if (ok) { m_timeTracker.slotStartEvent(id); } else { qWarning() << "Received invalid argument:" << data; } + } else if (data.startsWith(RaiseWindowCommand)) { + // nothing to do, see below } } socket->deleteLater(); @@ -326,8 +336,10 @@ void ApplicationCore::slotHandleUniqueApplicationConnection() void ApplicationCore::showMainWindow(ShowMode mode) { m_timeTracker.show(); + m_timeTracker.setWindowState(m_timeTracker.windowState() & ~Qt::WindowMinimized); if (mode == ShowMode::ShowAndRaise) { m_timeTracker.raise(); + m_timeTracker.activateWindow(); #ifdef Q_OS_WIN //krazy:cond=captruefalse,null int idActive = GetWindowThreadProcessId(GetForegroundWindow(), NULL); @@ -376,7 +388,7 @@ void ApplicationCore::createFileMenu(QMenuBar *menuBar) menu->addAction(&m_actionExportTasks); #ifdef Q_OS_OSX - if (!QString::fromLatin1(UPDATE_CHECK_URL).isEmpty()) { + if (!CharmUpdateCheckUrl().isEmpty()) { menu->addSeparator(); menu->addAction(&m_actionCheckForUpdates); } @@ -394,7 +406,7 @@ void ApplicationCore::createHelpMenu(QMenuBar *menuBar) menu->setTitle(tr("Help")); menu->addAction(&m_actionAboutDialog); #ifdef Q_OS_WIN - if (!QString::fromLatin1(UPDATE_CHECK_URL).isEmpty()) + if (!CharmUpdateCheckUrl().isEmpty()) menu->addAction(&m_actionCheckForUpdates); #endif @@ -403,6 +415,7 @@ void ApplicationCore::createHelpMenu(QMenuBar *menuBar) CharmWindow &ApplicationCore::mainView() { + m_timeTracker.setHideAtStartup(m_hideAtStart); return m_timeTracker; } @@ -857,14 +870,10 @@ void ApplicationCore::slotShowNotification(const QString &title, const QString & void ApplicationCore::slotShowTasksEditor() { - m_tasksView.show(); - m_tasksView.raise(); - m_tasksView.activateWindow(); + CharmWindow::showView(&m_tasksView); } void ApplicationCore::slotShowEventEditor() { - m_eventView.show(); - m_eventView.raise(); - m_eventView.activateWindow(); + CharmWindow::showView(&m_eventView); } diff --git a/Charm/ApplicationCore.h b/Charm/ApplicationCore.h index b16e753e..463ed065 100644 --- a/Charm/ApplicationCore.h +++ b/Charm/ApplicationCore.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld @@ -62,7 +62,7 @@ class ApplicationCore : public QObject Show, ShowAndRaise }; - explicit ApplicationCore(TaskId startupTask, QObject *parent = nullptr); + explicit ApplicationCore(TaskId startupTask, bool hideAtStart, QObject *parent = nullptr); ~ApplicationCore() override; static ApplicationCore &instance(); @@ -114,7 +114,7 @@ private Q_SLOTS: void slotCurrentBackendStatusChanged(const QString &text); void slotMaybeIdle(); void slotHandleUniqueApplicationConnection(); - void slotStartTaskMenuAboutToShow(); + void slotPopulateTrayIconMenu(); void slotShowNotification(const QString &title, const QString &message); void slotShowTasksEditor(); void slotShowEventEditor(); @@ -170,6 +170,7 @@ private Q_SLOTS: CharmCommandInterface *m_cmdInterface = nullptr; QLocalServer m_uniqueApplicationServer; TaskId m_startupTask; + bool m_hideAtStart; #ifdef Q_OS_WIN QWinJumpList *m_windowsJumpList = nullptr; #endif diff --git a/Charm/CI/CharmCommandInterface.cpp b/Charm/CI/CharmCommandInterface.cpp index 0a60b48c..147c5e28 100644 --- a/Charm/CI/CharmCommandInterface.cpp +++ b/Charm/CI/CharmCommandInterface.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2015-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2015-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Guillermo A. Amaral diff --git a/Charm/CI/CharmCommandInterface.h b/Charm/CI/CharmCommandInterface.h index fe642445..f952fb77 100644 --- a/Charm/CI/CharmCommandInterface.h +++ b/Charm/CI/CharmCommandInterface.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2015-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2015-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Guillermo A. Amaral @@ -39,7 +39,7 @@ class CharmCommandInterface : public QObject void start(); void stop(); -public slots: +public Q_SLOTS: void configurationChanged(); private: diff --git a/Charm/CI/CharmCommandProtocol.h b/Charm/CI/CharmCommandProtocol.h index 25880942..5f6642a3 100644 --- a/Charm/CI/CharmCommandProtocol.h +++ b/Charm/CI/CharmCommandProtocol.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2015-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2015-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Guillermo A. Amaral diff --git a/Charm/CI/CharmCommandServer.cpp b/Charm/CI/CharmCommandServer.cpp index 94ab989e..49f42d12 100644 --- a/Charm/CI/CharmCommandServer.cpp +++ b/Charm/CI/CharmCommandServer.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2015-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2015-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Guillermo A. Amaral diff --git a/Charm/CI/CharmCommandServer.h b/Charm/CI/CharmCommandServer.h index 75727ad0..25505887 100644 --- a/Charm/CI/CharmCommandServer.h +++ b/Charm/CI/CharmCommandServer.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2015-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2015-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Guillermo A. Amaral diff --git a/Charm/CI/CharmCommandSession.cpp b/Charm/CI/CharmCommandSession.cpp index 89ad59bf..fffc8787 100644 --- a/Charm/CI/CharmCommandSession.cpp +++ b/Charm/CI/CharmCommandSession.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2015-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2015-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Guillermo A. Amaral @@ -87,8 +87,8 @@ void CharmCommandSession::taskAdded(TaskId id) if (!m_device) return; - m_device->write(QString("%1 %2\n") - .arg(CHARM_CI_EVENT_TASK_ADDED) + m_device->write(QStringLiteral("%1 %2\n") + .arg(QStringLiteral(CHARM_CI_EVENT_TASK_ADDED)) .arg(DATAMODEL->taskIdAndSmartNameString(id)) .toLatin1()); } @@ -98,8 +98,8 @@ void CharmCommandSession::taskModified(TaskId id) if (!m_device) return; - m_device->write(QString("%1 %2\n") - .arg(CHARM_CI_EVENT_TASK_MODIFIED) + m_device->write(QStringLiteral("%1 %2\n") + .arg(QStringLiteral(CHARM_CI_EVENT_TASK_MODIFIED)) .arg(DATAMODEL->taskIdAndSmartNameString(id)) .toLatin1()); } @@ -110,8 +110,8 @@ void CharmCommandSession::eventActivated(EventId id) return; const Event &event = DATAMODEL->eventForId(id); - m_device->write(QString("%1 %2\n") - .arg(CHARM_CI_EVENT_TASK_ACTIVATED) + m_device->write(QStringLiteral("%1 %2\n") + .arg(QStringLiteral(CHARM_CI_EVENT_TASK_ACTIVATED)) .arg(DATAMODEL->taskIdAndSmartNameString(event.taskId())) .toLatin1()); } @@ -122,8 +122,8 @@ void CharmCommandSession::eventDeactivated(EventId id) return; const Event &event = DATAMODEL->eventForId(id); - m_device->write(QString("%1 %2\n") - .arg(CHARM_CI_EVENT_TASK_DEACTIVATED) + m_device->write(QStringLiteral("%1 %2\n") + .arg(QStringLiteral(CHARM_CI_EVENT_TASK_DEACTIVATED)) .arg(DATAMODEL->taskIdAndSmartNameString(event.taskId())) .toLatin1()); } @@ -153,34 +153,34 @@ void CharmCommandSession::onReadyRead() void CharmCommandSession::sendAck(const QString &comment) { - m_device->write(QString("%1 %2\n") - .arg(CHARM_CI_SERVER_ACK) + m_device->write(QStringLiteral("%1 %2\n") + .arg(QStringLiteral(CHARM_CI_SERVER_ACK)) .arg(comment) .toLatin1()); } void CharmCommandSession::sendNak(const QString &comment) { - m_device->write(QString("%1 %2\n") - .arg(CHARM_CI_SERVER_NAK) + m_device->write(QStringLiteral("%1 %2\n") + .arg(QStringLiteral(CHARM_CI_SERVER_NAK)) .arg(comment) .toLatin1()); } void CharmCommandSession::sendComment(const QString &comment) { - m_device->write(QString("%1 %2\n") - .arg(CHARM_CI_SERVER_COMMENT) + m_device->write(QStringLiteral("%1 %2\n") + .arg(QStringLiteral(CHARM_CI_SERVER_COMMENT)) .arg(comment) .toLatin1()); } void CharmCommandSession::startHandshake() { - sendComment("Charm Command Line Interface"); + sendComment(QStringLiteral("Charm Command Line Interface")); - m_device->write(QString("%1 %2\n") - .arg(CHARM_CI_HANDSHAKE_SEND) + m_device->write(QStringLiteral("%1 %2\n") + .arg(QStringLiteral(CHARM_CI_HANDSHAKE_SEND)) .arg(QString::number(CHARM_CI_VERSION)) .toLatin1()); @@ -209,12 +209,12 @@ void CharmCommandSession::handleHandshare(QByteArray payload) return; } - QString reply = buffer.readLine(); + QString reply = QLatin1String(buffer.readLine()); - if (reply.startsWith(CHARM_CI_HANDSHAKE_RECV, Qt::CaseInsensitive)) { - sendAck("Entering Command Mode"); + if (reply.startsWith(QStringLiteral(CHARM_CI_HANDSHAKE_RECV), Qt::CaseInsensitive)) { + sendAck(QStringLiteral("Entering Command Mode")); startCommand(); - } else if (reply.startsWith(CHARM_CI_COMMAND_DISCONNECT, Qt::CaseInsensitive)) { + } else if (reply.startsWith(QStringLiteral(CHARM_CI_COMMAND_DISCONNECT), Qt::CaseInsensitive)) { qDebug("BYE command received. Closing connection."); m_device->close(); } @@ -230,17 +230,17 @@ void CharmCommandSession::handleCommand(QByteArray payload) return; } - const QString command = buffer.readLine().trimmed(); + const QString command = QLatin1String(buffer.readLine().trimmed()); const QStringList segment - = command.split(' ', QString::SkipEmptyParts); + = command.split(QChar::Space, QString::SkipEmptyParts); if (segment.isEmpty()) { qDebug("Received empty command..."); return; } - if (segment[0].compare(CHARM_CI_COMMAND_START, Qt::CaseInsensitive) == 0) { + if (segment[0].compare(QStringLiteral(CHARM_CI_COMMAND_START), Qt::CaseInsensitive) == 0) { bool tid_ok; TaskId tid; @@ -258,9 +258,9 @@ void CharmCommandSession::handleCommand(QByteArray payload) DATAMODEL->startEventRequested(DATAMODEL->getTask(tid)); } } else { - sendNak("UNKNOWN TASK"); + sendNak(QStringLiteral("UNKNOWN TASK")); } - } else if (segment[0].compare(CHARM_CI_COMMAND_STOP, Qt::CaseInsensitive) == 0) { + } else if (segment[0].compare(QStringLiteral(CHARM_CI_COMMAND_STOP), Qt::CaseInsensitive) == 0) { bool tid_ok; TaskId tid; @@ -276,9 +276,9 @@ void CharmCommandSession::handleCommand(QByteArray payload) qDebug("STOP command received. Stopping task %d", tid); DATAMODEL->endEventRequested(DATAMODEL->getTask(tid)); } else { - sendNak("UNKNOWN TASK"); + sendNak(QStringLiteral("UNKNOWN TASK")); } - } else if (segment[0].compare(CHARM_CI_COMMAND_TASK, Qt::CaseInsensitive) == 0) { + } else if (segment[0].compare(QStringLiteral(CHARM_CI_COMMAND_TASK), Qt::CaseInsensitive) == 0) { bool tid_ok; TaskId tid; @@ -293,23 +293,23 @@ void CharmCommandSession::handleCommand(QByteArray payload) m_device->write(DATAMODEL->taskIdAndSmartNameString(tid).toLatin1()); m_device->write("\n"); } else { - sendNak("UNKNOWN TASK"); + sendNak(QStringLiteral("UNKNOWN TASK")); } - } else if (segment[0].compare(CHARM_CI_COMMAND_STATUS, Qt::CaseInsensitive) == 0) { + } else if (segment[0].compare(QStringLiteral(CHARM_CI_COMMAND_STATUS), Qt::CaseInsensitive) == 0) { qDebug("STATUS command received."); const EventIdList activeEvents = DATAMODEL->activeEvents(); if (!activeEvents.isEmpty()) { foreach (EventId id, activeEvents) { const Event &event = DATAMODEL->eventForId(id); - m_device->write(QString("%0 %1\n") - .arg(event.taskId(), 4, 10, QChar('0')) + m_device->write(QStringLiteral("%0 %1\n") + .arg(event.taskId(), 4, 10, QLatin1Char('0')) .arg(event.duration()).toLatin1()); } } else { - sendNak("WORK HARDER"); + sendNak(QStringLiteral("WORK HARDER")); } - } else if (segment[0].compare(CHARM_CI_COMMAND_RECENT, Qt::CaseInsensitive) == 0) { + } else if (segment[0].compare(QStringLiteral(CHARM_CI_COMMAND_RECENT), Qt::CaseInsensitive) == 0) { bool offset_ok; bool count_ok; int offset; @@ -342,14 +342,14 @@ void CharmCommandSession::handleCommand(QByteArray payload) m_device->write("\n"); } } else { - sendNak("INVALID REQUEST"); + sendNak(QStringLiteral("INVALID REQUEST")); } - } else if (segment[0].compare(CHARM_CI_COMMAND_DISCONNECT, Qt::CaseInsensitive) == 0) { + } else if (segment[0].compare(QStringLiteral(CHARM_CI_COMMAND_DISCONNECT), Qt::CaseInsensitive) == 0) { qDebug("BYE command received. Closing connection."); m_device->close(); } /* unknown command sent */ else { - sendNak("UNKNOWN COMMAND"); + sendNak(QStringLiteral("UNKNOWN COMMAND")); } } diff --git a/Charm/CI/CharmCommandSession.h b/Charm/CI/CharmCommandSession.h index 3826e80a..c2fbf210 100644 --- a/Charm/CI/CharmCommandSession.h +++ b/Charm/CI/CharmCommandSession.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2015-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2015-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Guillermo A. Amaral @@ -71,23 +71,23 @@ class CharmCommandSession : public QObject, public CharmDataModelAdapterInterfac { } - void eventAboutToBeAdded(EventId id) + void eventAboutToBeAdded(EventId) { } - void eventAdded(EventId id) + void eventAdded(EventId) { } - void eventModified(EventId id, Event discardedEvent) + void eventModified(EventId, Event) { } - void eventAboutToBeDeleted(EventId id) + void eventAboutToBeDeleted(EventId) { } - void eventDeleted(EventId id) + void eventDeleted(EventId) { } @@ -97,7 +97,7 @@ class CharmCommandSession : public QObject, public CharmDataModelAdapterInterfac protected: void reset(); -private slots: +private Q_SLOTS: void onReadyRead(); private: diff --git a/Charm/CI/CharmLocalCommandServer.cpp b/Charm/CI/CharmLocalCommandServer.cpp index 84438406..dc8d7ab9 100644 --- a/Charm/CI/CharmLocalCommandServer.cpp +++ b/Charm/CI/CharmLocalCommandServer.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2015-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2015-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Guillermo A. Amaral @@ -47,7 +47,7 @@ CharmLocalCommandServer::~CharmLocalCommandServer() bool CharmLocalCommandServer::listen() { - const QString name(QDir::tempPath() + '/' + "charm.sock"); + const QString name(QDir::tempPath().append(QStringLiteral("/charm.sock"))); #ifdef Q_OS_UNIX QFile::remove(name); // Try to clean up stale socket if possible diff --git a/Charm/CI/CharmLocalCommandServer.h b/Charm/CI/CharmLocalCommandServer.h index d8570d88..e300dd40 100644 --- a/Charm/CI/CharmLocalCommandServer.h +++ b/Charm/CI/CharmLocalCommandServer.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2015-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2015-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Guillermo A. Amaral @@ -38,7 +38,7 @@ class CharmLocalCommandServer : public CharmCommandServer bool listen() override; void close() override; -private slots: +private Q_SLOTS: void onNewConnection(); private: diff --git a/Charm/CI/CharmTCPCommandServer.cpp b/Charm/CI/CharmTCPCommandServer.cpp index 960f742f..f1918ec4 100644 --- a/Charm/CI/CharmTCPCommandServer.cpp +++ b/Charm/CI/CharmTCPCommandServer.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2015-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2015-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Guillermo A. Amaral diff --git a/Charm/CI/CharmTCPCommandServer.h b/Charm/CI/CharmTCPCommandServer.h index 551d2ad5..024d8f69 100644 --- a/Charm/CI/CharmTCPCommandServer.h +++ b/Charm/CI/CharmTCPCommandServer.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2015-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2015-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Guillermo A. Amaral @@ -50,7 +50,7 @@ class CharmTCPCommandServer : public CharmCommandServer protected: /* reimpl */ void timerEvent(QTimerEvent *event); -private slots: +private Q_SLOTS: void onNewConnection(); private: diff --git a/Charm/CMake/Modules/FindXCB.cmake b/Charm/CMake/Modules/FindXCB.cmake index 2e7c63fd..ee418aec 100644 --- a/Charm/CMake/Modules/FindXCB.cmake +++ b/Charm/CMake/Modules/FindXCB.cmake @@ -1,4 +1,4 @@ -# Copyright (C) 2015-2017 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com +# Copyright (C) 2015-2018 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.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 diff --git a/Charm/CMakeLists.txt b/Charm/CMakeLists.txt index 9ed8a650..21761360 100644 --- a/Charm/CMakeLists.txt +++ b/Charm/CMakeLists.txt @@ -24,15 +24,17 @@ SET( Commands/CommandExportToXml.cpp Commands/CommandImportFromXml.cpp Commands/CommandMakeAndActivateEvent.cpp - HttpClient/HttpJob.cpp + HttpClient/CheckForUpdatesJob.cpp HttpClient/GetProjectCodesJob.cpp + HttpClient/HttpJob.cpp + HttpClient/RestJob.cpp HttpClient/UploadTimesheetJob.cpp - HttpClient/GetUserInfoJob.cpp - HttpClient/CheckForUpdatesJob.cpp Idle/IdleDetector.cpp + Lotsofcake/Configuration.cpp Reports/TimesheetInfo.cpp Reports/MonthlyTimesheetXmlWriter.cpp Reports/WeeklyTimesheetXmlWriter.cpp + Reports/TimesheetXmlWriter.cpp Widgets/ActivityReport.cpp Widgets/BillDialog.cpp Widgets/CharmPreferences.cpp diff --git a/Charm/Charm.cpp b/Charm/Charm.cpp index fff9e036..e4e7e0cb 100644 --- a/Charm/Charm.cpp +++ b/Charm/Charm.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Mike McQuaid @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -37,14 +38,16 @@ #include "Core/CharmExceptions.h" #include "CharmCMake.h" -static std::shared_ptr createApplicationCore(TaskId startupTask) -{ +struct StartupOptions { + static std::shared_ptr createApplicationCore(TaskId startupTask, bool hideAtStart) + { #ifdef Q_OS_OSX - return std::make_shared(startupTask); + return std::make_shared(startupTask, hideAtStart); #else - return std::make_shared(startupTask); + return std::make_shared(startupTask, hideAtStart); #endif -} + } +}; void showCriticalError(const QString &msg) { @@ -56,10 +59,12 @@ void showCriticalError(const QString &msg) int main(int argc, char **argv) { TaskId startupTask = -1; + bool hideAtStart = false; +#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0) if (argc >= 2) { if (qstrcmp(argv[1], "--version") == 0) { using namespace std; - cout << "Charm version " << CHARM_VERSION << endl; + cout << "Charm version " << qPrintable(CharmVersion()) << endl; return 0; } else if (argc == 3 && qstrcmp(argv[1], "--start-task") == 0) { bool ok = true; @@ -68,8 +73,11 @@ int main(int argc, char **argv) std::cerr << "Invalid task id passed: " << argv[2]; return 1; } + } else if (qstrcmp(argv[1], "--hide-at-start") == 0) { + hideAtStart = true; } } +#endif const QByteArray charmHomeEnv = qgetenv("CHARM_HOME"); if (!charmHomeEnv.isEmpty()) { @@ -87,6 +95,7 @@ int main(int argc, char **argv) } try { +#ifdef Q_OS_WIN // High DPI support #if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0) QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true); @@ -96,12 +105,45 @@ int main(int argc, char **argv) QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true); #endif +#endif // Q_OS_WIN + QApplication app(argc, argv); - const std::shared_ptr core(createApplicationCore(startupTask)); - QObject::connect(&app, SIGNAL(commitDataRequest(QSessionManager&)), core.get(), - SLOT(commitData(QSessionManager&))); - QObject::connect(&app, SIGNAL(saveStateRequest(QSessionManager&)), core.get(), - SLOT(saveState(QSessionManager&))); + +#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0) + //Now we can use more command line arguments: + //charmtimetracker --hide-at-start --start-task 8714 + const QCommandLineOption startTaskOption(QLatin1String("start-task"), + QLatin1String("Start up the task with "), + QLatin1String("task-id")); + const QCommandLineOption hideAtStartOption(QLatin1String("hide-at-start"), + QLatin1String("Hide Timetracker window at start")); + + QCommandLineParser parser; + parser.addHelpOption(); + parser.addVersionOption(); + parser.addOption(hideAtStartOption); + parser.addOption(startTaskOption); + + parser.process(app); + + bool ok = true; + if (parser.isSet(startTaskOption)) { + const QString value = parser.value(startTaskOption); + startupTask = value.toInt(&ok); + if (!ok || startupTask < 0) { + std::cerr << "Invalid task id passed: " << qPrintable(value) << std::endl; + return 1; + } + } + if (parser.isSet(hideAtStartOption)) + hideAtStart = true; +#endif + + const std::shared_ptr core(StartupOptions::createApplicationCore(startupTask, hideAtStart)); + QObject::connect(&app, &QGuiApplication::commitDataRequest, core.get(), + &ApplicationCore::commitData); + QObject::connect(&app, &QGuiApplication::saveStateRequest, core.get(), + &ApplicationCore::saveState); return app.exec(); } catch (const AlreadyRunningException &) { using namespace std; diff --git a/Charm/Commands/CommandAddTask.cpp b/Charm/Commands/CommandAddTask.cpp index 51ad61b0..667262c0 100644 --- a/Charm/Commands/CommandAddTask.cpp +++ b/Charm/Commands/CommandAddTask.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Charm/Commands/CommandAddTask.h b/Charm/Commands/CommandAddTask.h index 21a4d556..a4117379 100644 --- a/Charm/Commands/CommandAddTask.h +++ b/Charm/Commands/CommandAddTask.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Charm/Commands/CommandDeleteEvent.cpp b/Charm/Commands/CommandDeleteEvent.cpp index f7682f4a..b56c5f45 100644 --- a/Charm/Commands/CommandDeleteEvent.cpp +++ b/Charm/Commands/CommandDeleteEvent.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Charm/Commands/CommandDeleteEvent.h b/Charm/Commands/CommandDeleteEvent.h index 7ce1d534..31c0c9da 100644 --- a/Charm/Commands/CommandDeleteEvent.h +++ b/Charm/Commands/CommandDeleteEvent.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Charm/Commands/CommandDeleteTask.cpp b/Charm/Commands/CommandDeleteTask.cpp index 97871992..ccbc8bcd 100644 --- a/Charm/Commands/CommandDeleteTask.cpp +++ b/Charm/Commands/CommandDeleteTask.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Charm/Commands/CommandDeleteTask.h b/Charm/Commands/CommandDeleteTask.h index 392aa832..8cf023fa 100644 --- a/Charm/Commands/CommandDeleteTask.h +++ b/Charm/Commands/CommandDeleteTask.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Charm/Commands/CommandExportToXml.cpp b/Charm/Commands/CommandExportToXml.cpp index 3f9b2f78..88886c12 100644 --- a/Charm/Commands/CommandExportToXml.cpp +++ b/Charm/Commands/CommandExportToXml.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Charm/Commands/CommandExportToXml.h b/Charm/Commands/CommandExportToXml.h index 50968da6..c955b405 100644 --- a/Charm/Commands/CommandExportToXml.h +++ b/Charm/Commands/CommandExportToXml.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Charm/Commands/CommandImportFromXml.cpp b/Charm/Commands/CommandImportFromXml.cpp index e96b28e6..7339c56b 100644 --- a/Charm/Commands/CommandImportFromXml.cpp +++ b/Charm/Commands/CommandImportFromXml.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Charm/Commands/CommandImportFromXml.h b/Charm/Commands/CommandImportFromXml.h index a03e7437..814c5a64 100644 --- a/Charm/Commands/CommandImportFromXml.h +++ b/Charm/Commands/CommandImportFromXml.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Charm/Commands/CommandMakeAndActivateEvent.cpp b/Charm/Commands/CommandMakeAndActivateEvent.cpp index 3cc2e87c..1d634cb1 100644 --- a/Charm/Commands/CommandMakeAndActivateEvent.cpp +++ b/Charm/Commands/CommandMakeAndActivateEvent.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Charm/Commands/CommandMakeAndActivateEvent.h b/Charm/Commands/CommandMakeAndActivateEvent.h index 5f8bc9bc..3bde1c25 100644 --- a/Charm/Commands/CommandMakeAndActivateEvent.h +++ b/Charm/Commands/CommandMakeAndActivateEvent.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Charm/Commands/CommandMakeEvent.cpp b/Charm/Commands/CommandMakeEvent.cpp index 2c83f4ce..997efdd7 100644 --- a/Charm/Commands/CommandMakeEvent.cpp +++ b/Charm/Commands/CommandMakeEvent.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Charm/Commands/CommandMakeEvent.h b/Charm/Commands/CommandMakeEvent.h index 51500b5a..2eb851ab 100644 --- a/Charm/Commands/CommandMakeEvent.h +++ b/Charm/Commands/CommandMakeEvent.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Charm/Commands/CommandModifyEvent.cpp b/Charm/Commands/CommandModifyEvent.cpp index 79c456b9..1dfd00a9 100644 --- a/Charm/Commands/CommandModifyEvent.cpp +++ b/Charm/Commands/CommandModifyEvent.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Charm/Commands/CommandModifyEvent.h b/Charm/Commands/CommandModifyEvent.h index 9501ca18..8c080cd6 100644 --- a/Charm/Commands/CommandModifyEvent.h +++ b/Charm/Commands/CommandModifyEvent.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Charm/Commands/CommandModifyTask.cpp b/Charm/Commands/CommandModifyTask.cpp index 499b3b4c..dea2298f 100644 --- a/Charm/Commands/CommandModifyTask.cpp +++ b/Charm/Commands/CommandModifyTask.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Charm/Commands/CommandModifyTask.h b/Charm/Commands/CommandModifyTask.h index d217a016..87e8ba6f 100644 --- a/Charm/Commands/CommandModifyTask.h +++ b/Charm/Commands/CommandModifyTask.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Charm/Commands/CommandRelayCommand.cpp b/Charm/Commands/CommandRelayCommand.cpp index 8e1aab25..28239443 100644 --- a/Charm/Commands/CommandRelayCommand.cpp +++ b/Charm/Commands/CommandRelayCommand.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Charm/Commands/CommandRelayCommand.h b/Charm/Commands/CommandRelayCommand.h index f82c1e66..4f150f04 100644 --- a/Charm/Commands/CommandRelayCommand.h +++ b/Charm/Commands/CommandRelayCommand.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Charm/Commands/CommandSetAllTasks.cpp b/Charm/Commands/CommandSetAllTasks.cpp index 0ace35ce..ca82f827 100644 --- a/Charm/Commands/CommandSetAllTasks.cpp +++ b/Charm/Commands/CommandSetAllTasks.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Charm/Commands/CommandSetAllTasks.h b/Charm/Commands/CommandSetAllTasks.h index 94122f65..d8db3e2e 100644 --- a/Charm/Commands/CommandSetAllTasks.h +++ b/Charm/Commands/CommandSetAllTasks.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Charm/Data.cpp b/Charm/Data.cpp index 8c70b41e..496d381a 100644 --- a/Charm/Data.cpp +++ b/Charm/Data.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Charm/Data.h b/Charm/Data.h index cbe94243..5aec5d1c 100644 --- a/Charm/Data.h +++ b/Charm/Data.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Mike McQuaid diff --git a/Charm/EventModelAdapter.cpp b/Charm/EventModelAdapter.cpp index b132d221..783a7548 100644 --- a/Charm/EventModelAdapter.cpp +++ b/Charm/EventModelAdapter.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Charm/EventModelAdapter.h b/Charm/EventModelAdapter.h index 03733980..9927cef4 100644 --- a/Charm/EventModelAdapter.h +++ b/Charm/EventModelAdapter.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Charm/EventModelFilter.cpp b/Charm/EventModelFilter.cpp index 9fd0af71..4728a5b9 100644 --- a/Charm/EventModelFilter.cpp +++ b/Charm/EventModelFilter.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Charm/EventModelFilter.h b/Charm/EventModelFilter.h index 2bebdc4d..23cce139 100644 --- a/Charm/EventModelFilter.h +++ b/Charm/EventModelFilter.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Charm/GUIState.cpp b/Charm/GUIState.cpp index 46021ccb..4cd2a897 100644 --- a/Charm/GUIState.cpp +++ b/Charm/GUIState.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Charm/GUIState.h b/Charm/GUIState.h index 908a842c..a2d2732b 100644 --- a/Charm/GUIState.h +++ b/Charm/GUIState.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Charm/HttpClient/CheckForUpdatesJob.cpp b/Charm/HttpClient/CheckForUpdatesJob.cpp index ac3f6cd9..711c2bd0 100644 --- a/Charm/HttpClient/CheckForUpdatesJob.cpp +++ b/Charm/HttpClient/CheckForUpdatesJob.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2011-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2011-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Michel Boyer de la Giroday @@ -61,7 +61,7 @@ void CheckForUpdatesJob::start() { Q_ASSERT(!m_url.toString().isEmpty()); QNetworkAccessManager *manager = new QNetworkAccessManager(this); - connect(manager, SIGNAL(finished(QNetworkReply*)), SLOT(jobFinished(QNetworkReply*))); + connect(manager, &QNetworkAccessManager::finished, this, &CheckForUpdatesJob::jobFinished); manager->get(QNetworkRequest(m_url)); } diff --git a/Charm/HttpClient/CheckForUpdatesJob.h b/Charm/HttpClient/CheckForUpdatesJob.h index 69393792..b87af91d 100644 --- a/Charm/HttpClient/CheckForUpdatesJob.h +++ b/Charm/HttpClient/CheckForUpdatesJob.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2011-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2011-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Michel Boyer de la Giroday diff --git a/Charm/HttpClient/GetProjectCodesJob.cpp b/Charm/HttpClient/GetProjectCodesJob.cpp index 199e6d89..84edf512 100644 --- a/Charm/HttpClient/GetProjectCodesJob.cpp +++ b/Charm/HttpClient/GetProjectCodesJob.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2011-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2011-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -31,9 +31,6 @@ GetProjectCodesJob::GetProjectCodesJob(QObject *parent) : HttpJob(parent) { - QSettings s; - s.beginGroup(QStringLiteral("httpconfig")); - setDownloadUrl(s.value(QStringLiteral("projectCodeDownloadUrl")).toUrl()); } GetProjectCodesJob::~GetProjectCodesJob() @@ -45,33 +42,29 @@ QByteArray GetProjectCodesJob::payload() const return m_payload; } -bool GetProjectCodesJob::execute(int state, QNetworkAccessManager *manager) +void GetProjectCodesJob::executeRequest(QNetworkAccessManager *manager) { - if (state != GetProjectCodes) - return HttpJob::execute(state, manager); QNetworkRequest request(m_downloadUrl); QNetworkReply *reply = manager->get(request); + connect(reply, &QNetworkReply::finished, this, &GetProjectCodesJob::handleResult); if (reply->error() != QNetworkReply::NoError) - setErrorFromReplyAndEmitFinished(reply); - return true; + setErrorFromReplyAndEmitFinishedOrRestart(reply); } -bool GetProjectCodesJob::handle(QNetworkReply *reply) +void GetProjectCodesJob::handleResult() { + auto reply = qobject_cast(sender()); + reply->deleteLater(); /* check for failure */ if (reply->error() != QNetworkReply::NoError) { - setErrorFromReplyAndEmitFinished(reply); - return false; + setErrorFromReplyAndEmitFinishedOrRestart(reply); + return; } - if (state() != GetProjectCodes) - return HttpJob::handle(reply); - m_payload = reply->readAll(); - delayedNext(); - return true; + emitFinishedOrRestart(); } QUrl GetProjectCodesJob::downloadUrl() const diff --git a/Charm/HttpClient/GetProjectCodesJob.h b/Charm/HttpClient/GetProjectCodesJob.h index 60bb1d0e..a6ae6172 100644 --- a/Charm/HttpClient/GetProjectCodesJob.h +++ b/Charm/HttpClient/GetProjectCodesJob.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2011-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2011-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -43,16 +43,11 @@ class GetProjectCodesJob : public HttpJob void setVerbose(bool verbose); bool isVerbose() const; -public Q_SLOTS: - - bool execute(int state, QNetworkAccessManager *manager) override; - bool handle(QNetworkReply *reply) override; - protected: + void executeRequest(QNetworkAccessManager *) override; - enum State { - GetProjectCodes = HttpJob::Base - }; +private: + void handleResult(); private: QByteArray m_payload; diff --git a/Charm/HttpClient/GetUserInfoJob.cpp b/Charm/HttpClient/GetUserInfoJob.cpp deleted file mode 100644 index df97ff0d..00000000 --- a/Charm/HttpClient/GetUserInfoJob.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - GetUserInfoJob.cpp - - This file is part of Charm, a task-based time tracking application. - - Copyright (C) 2015-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com - - Author: Pál Tóth - - 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. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "GetUserInfoJob.h" -#include -#include -#include -#include - -GetUserInfoJob::GetUserInfoJob(QObject *parent, const QString &schema) - : HttpJob(parent) - , m_schema(schema) -{ - QSettings s; - s.beginGroup(m_schema); - setDownloadUrl(s.value(QStringLiteral("userInfoDownloadUrl")).toUrl()); -} - -GetUserInfoJob::~GetUserInfoJob() -{ -} - -QByteArray GetUserInfoJob::userInfo() const -{ - return m_userInfo; -} - -QString GetUserInfoJob::schema() const -{ - return m_schema; -} - -void GetUserInfoJob::setSchema(const QString &schema) -{ - m_schema = schema; -} - -bool GetUserInfoJob::execute(int state, QNetworkAccessManager *manager) -{ - if (state != GetProjectCodes) - return HttpJob::execute(state, manager); - QNetworkRequest request(m_downloadUrl); - - QNetworkReply *reply = manager->get(request); - - if (reply->error() != QNetworkReply::NoError) - setErrorFromReplyAndEmitFinished(reply); - return true; -} - -bool GetUserInfoJob::handle(QNetworkReply *reply) -{ - /* check for failure */ - if (reply->error() != QNetworkReply::NoError) { - setErrorFromReplyAndEmitFinished(reply); - return false; - } - - m_userInfo = reply->readAll(); - - delayedNext(); - return true; -} - -QUrl GetUserInfoJob::downloadUrl() const -{ - return m_downloadUrl; -} - -void GetUserInfoJob::setDownloadUrl(const QUrl &url) -{ - m_downloadUrl = url; -} diff --git a/Charm/HttpClient/HttpJob.cpp b/Charm/HttpClient/HttpJob.cpp index 35894925..0475fc75 100644 --- a/Charm/HttpClient/HttpJob.cpp +++ b/Charm/HttpClient/HttpJob.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2011-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2011-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld Author: Olivier JG @@ -32,81 +32,15 @@ #include #include #include -#include -#include #include -static void setLastAuthenticationFailed(bool failed) -{ - QSettings settings; - settings.beginGroup(QStringLiteral("httpconfig")); - settings.setValue(QStringLiteral("lastAuthenticationFailed"), failed); -} - -bool HttpJob::lastAuthenticationFailed() -{ - QSettings settings; - settings.beginGroup(QStringLiteral("httpconfig")); - return settings.value(QStringLiteral("lastAuthenticationFailed"), false).toBool(); -} - -bool HttpJob::credentialsAvailable() -{ - QSettings settings; - settings.beginGroup(QStringLiteral("httpconfig")); - return !settings.value(QStringLiteral("username")).toString().isEmpty() - && settings.value(QStringLiteral("portalUrl")).toUrl().isValid() - && settings.value(QStringLiteral("loginUrl")).toUrl().isValid(); -} - -QString HttpJob::extractErrorMessageFromReply(const QByteArray &xml) -{ - class XmlStreamEntityResolver : public QXmlStreamEntityResolver - { - public: - XmlStreamEntityResolver() : QXmlStreamEntityResolver() - { - } - - QString resolveUndeclaredEntity(const QString &name) override - { - Q_UNUSED(name) - return QLatin1String(" "); // replace undeclared entities with a whitespace just to not abort parsing - } - }; - XmlStreamEntityResolver resolver; - QXmlStreamReader reader(xml); - reader.setEntityResolver(&resolver); - - while (!reader.atEnd() && !reader.hasError()) { - reader.readNext(); - if (reader.isStartElement() && reader.name() == QLatin1String("div") - && reader.attributes().value(QLatin1String("class")) - == QLatin1String("ErrorResultMessage")) - return reader.readElementText(); - } - if (reader.hasError()) - return tr("Error parsing response: %1").arg(reader.errorString()); - - return QString(); -} - HttpJob::HttpJob(QObject *parent) : QObject(parent) , m_networkManager(new QNetworkAccessManager(this)) { - connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), SLOT(handle(QNetworkReply*))); - connect(m_networkManager, SIGNAL(authenticationRequired(QNetworkReply *, - QAuthenticator *)), - SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*))); - QSettings settings; - settings.beginGroup(QStringLiteral("httpconfig")); - setUsername(settings.value(QStringLiteral("username")).toString()); - setPortalUrl(settings.value(QStringLiteral("portalUrl")).toUrl()); - setLoginUrl(settings.value(QStringLiteral("loginUrl")).toUrl()); - m_lastAuthenticationFailed - = settings.value(QStringLiteral("lastAuthenticationFailed"), false).toBool(); + connect(m_networkManager, &QNetworkAccessManager::authenticationRequired, + this, &HttpJob::authenticationRequired); } HttpJob::~HttpJob() @@ -133,31 +67,6 @@ void HttpJob::setPassword(const QString &value) m_password = value; } -QUrl HttpJob::portalUrl() const -{ - return m_portalUrl; -} - -void HttpJob::setPortalUrl(const QUrl &value) -{ - m_portalUrl = value; -} - -QUrl HttpJob::loginUrl() const -{ - return m_loginUrl; -} - -void HttpJob::setLoginUrl(const QUrl &value) -{ - m_loginUrl = value; -} - -int HttpJob::state() const -{ - return m_currentState; -} - int HttpJob::error() const { return m_errorCode; @@ -177,16 +86,14 @@ using namespace QKeychain; void HttpJob::doStart() { - if (m_username.isEmpty() || m_loginUrl.isEmpty() || m_portalUrl.isEmpty()) { - setErrorAndEmitFinished(NotConfigured, - tr( - "Timesheet upload and task list download not configured. Download and import the task list manually to configure them.")); + if (m_username.isEmpty()) { + setErrorAndEmitFinishedOrRestart(NotConfigured, + tr("lotsofcake login data not configured. Download and import the task list manually to configure them.")); return; } auto readJob = new ReadPasswordJob(QStringLiteral("Charm"), this); - connect(readJob, SIGNAL(finished(QKeychain::Job*)), this, - SLOT(passwordRead(QKeychain::Job*))); + connect(readJob, &Job::finished, this, &HttpJob::passwordRead); readJob->setKey(QStringLiteral("lotsofcake")); readJob->start(); } @@ -201,10 +108,8 @@ void HttpJob::passwordRead(QKeychain::Job *j) const QString oldpass = job->error() ? QString() : job->textData(); - const bool authenticationFailed = lastAuthenticationFailed(); - - if (oldpass.isEmpty() || authenticationFailed) { - emit passwordRequested(); + if (oldpass.isEmpty() || m_lastAuthenticationFailed) { + emit passwordRequested(oldpass.isEmpty() ? HttpJob::NoPasswordFound : HttpJob::PasswordIncorrect); return; } else { provideRequestedPassword(oldpass); @@ -218,7 +123,7 @@ void HttpJob::provideRequestedPassword(const QString &password) if (oldpass != m_password && !m_passwordReadError) { auto writeJob = new WritePasswordJob(QStringLiteral("Charm"), this); - connect(writeJob, SIGNAL(finished(QKeychain::Job*)), this, SLOT(passwordWritten())); + connect(writeJob, &Job::finished, this, &HttpJob::passwordWritten); writeJob->setKey(QStringLiteral("lotsofcake")); writeJob->setTextData(m_password); writeJob->start(); @@ -229,13 +134,13 @@ void HttpJob::provideRequestedPassword(const QString &password) void HttpJob::passwordRequestCanceled() { - setErrorAndEmitFinished(Canceled, tr("Canceled")); + setErrorAndEmitFinishedOrRestart(Canceled, tr("Canceled")); } void HttpJob::passwordWritten() { emit transferStarted(); - delayedNext(); + executeRequest(m_networkManager); } void HttpJob::cancel() @@ -245,97 +150,7 @@ void HttpJob::cancel() void HttpJob::doCancel() { - setErrorAndEmitFinished(Canceled, tr("Canceled")); -} - -void HttpJob::next() -{ - /* go to the next state */ - ++m_currentState; - - /* skip login if authenticationRequired() was called meanwhile */ - if (m_authenticationDoneAlready && m_currentState == Login) - ++m_currentState; - - /* finish if next state is not found */ - if (!execute(m_currentState, m_networkManager)) { - emitFinished(); - return; - } -} - -void HttpJob::delayedNext() -{ - QMetaObject::invokeMethod(this, "next", Qt::QueuedConnection); -} - -bool HttpJob::execute(int state, QNetworkAccessManager *manager) -{ - switch (state) { - case Init: - case Portal: - { - QNetworkRequest request(m_portalUrl); - - QNetworkReply *reply = manager->get(request); - - if (reply->error() != QNetworkReply::NoError) - setErrorFromReplyAndEmitFinished(reply); - } return true; - - case Login: - { - QUrlQuery urlQuery; - urlQuery.addQueryItem(QStringLiteral("j_username"), m_username); - urlQuery.addQueryItem(QStringLiteral("j_password"), m_password); - QByteArray encodedQueryPlusPlus = urlQuery.query(QUrl::FullyEncoded).toUtf8().replace('+', - "%2b"); - - QNetworkRequest request(m_loginUrl); - - request.setHeader(QNetworkRequest::ContentTypeHeader, - QStringLiteral("application/x-www-form-urlencoded")); - request.setHeader(QNetworkRequest::ContentLengthHeader, encodedQueryPlusPlus.size()); - - QNetworkReply *reply = manager->post(request, encodedQueryPlusPlus); - - if (reply->error() != QNetworkReply::NoError) - setErrorFromReplyAndEmitFinished(reply); - } return true; - - default: - break; - } - - return false; -} - -bool HttpJob::handle(QNetworkReply *reply) -{ - // check for failure - if (reply->error() != QNetworkReply::NoError) { - setErrorFromReplyAndEmitFinished(reply); - return false; - } - - switch (m_currentState) { - case Init: - case Portal: - delayedNext(); - return true; - case Login: - if (reply->header(QNetworkRequest::LocationHeader).isNull()) { - setErrorAndEmitFinished(AuthenticationFailed, - tr("Login failed. Wrong username or password.")); - } else { - delayedNext(); - } - return true; - default: - break; - } - - return false; + setErrorAndEmitFinishedOrRestart(Canceled, tr("Canceled")); } void HttpJob::authenticationRequired(QNetworkReply *, QAuthenticator *authenticator) @@ -347,37 +162,39 @@ void HttpJob::authenticationRequired(QNetworkReply *, QAuthenticator *authentica } } -void HttpJob::emitFinished() +void HttpJob::emitFinishedOrRestart() { if (m_errorCode == AuthenticationFailed) { - setLastAuthenticationFailed(true); - } else if (m_errorCode == NoError) { - setLastAuthenticationFailed(false); + m_authenticationDoneAlready = false; + m_lastAuthenticationFailed = true; + m_errorCode = NoError; + m_errorString.clear(); + start(); + return; } m_networkManager->disconnect(this); emit finished(this); deleteLater(); } -void HttpJob::setErrorAndEmitFinished(int code, const QString &errorString) +void HttpJob::setErrorAndEmitFinishedOrRestart(int code, const QString &errorString) { m_errorCode = code; m_errorString = errorString; - emitFinished(); + emitFinishedOrRestart(); } -void HttpJob::setErrorFromReplyAndEmitFinished(QNetworkReply *reply) +void HttpJob::setErrorFromReplyAndEmitFinishedOrRestart(QNetworkReply *reply) { - m_authenticationDoneAlready = false; switch (reply->error()) { case QNetworkReply::HostNotFoundError: - setErrorAndEmitFinished(HostNotFound, reply->errorString()); + setErrorAndEmitFinishedOrRestart(HostNotFound, reply->errorString()); break; case QNetworkReply::AuthenticationRequiredError: - setErrorAndEmitFinished(AuthenticationFailed, reply->errorString()); + setErrorAndEmitFinishedOrRestart(AuthenticationFailed, reply->errorString()); break; default: - setErrorAndEmitFinished(SomethingWentWrong, reply->errorString()); + setErrorAndEmitFinishedOrRestart(SomethingWentWrong, reply->errorString()); break; } } diff --git a/Charm/HttpClient/HttpJob.h b/Charm/HttpClient/HttpJob.h index 8b96a7e8..4755bf3f 100644 --- a/Charm/HttpClient/HttpJob.h +++ b/Charm/HttpClient/HttpJob.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2011-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2011-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -40,10 +40,6 @@ class HttpJob : public QObject { Q_OBJECT public: - - static bool credentialsAvailable(); - static bool lastAuthenticationFailed(); - enum Error { NoError = 0, Canceled, @@ -53,6 +49,11 @@ class HttpJob : public QObject HostNotFound }; + enum PasswordRequestReason { + NoPasswordFound, + PasswordIncorrect + }; + explicit HttpJob(QObject *parent = nullptr); ~HttpJob() override; @@ -62,12 +63,6 @@ class HttpJob : public QObject QString password() const; void setPassword(const QString &value); - QUrl portalUrl() const; - void setPortalUrl(const QUrl &value); - - QUrl loginUrl() const; - void setLoginUrl(const QUrl &value); - QString errorString() const; int error() const; @@ -88,36 +83,19 @@ class HttpJob : public QObject * * Must be replied to via provideRequestedPassword() or passwordRequestCanceled() to continue. */ - void passwordRequested(); - -protected: - - enum State { - Ready = 0, - Init, - Login, - Portal, - Base - }; - - int state() const; - - virtual bool execute(int state, QNetworkAccessManager *manager); - - void emitFinished(); - void setErrorAndEmitFinished(int code, const QString &errorString); - void delayedNext(); - void setErrorFromReplyAndEmitFinished(QNetworkReply *reply); - - static QString extractErrorMessageFromReply(const QByteArray &xml); + void passwordRequested(PasswordRequestReason); protected Q_SLOTS: - virtual bool handle(QNetworkReply *reply); + virtual void executeRequest(QNetworkAccessManager *) = 0; + +protected: + void emitFinishedOrRestart(); + void setErrorAndEmitFinishedOrRestart(int code, const QString &errorString); + void setErrorFromReplyAndEmitFinishedOrRestart(QNetworkReply *reply); private Q_SLOTS: void doStart(); void doCancel(); - void next(); void passwordRead(QKeychain::Job *); void passwordWritten(); void authenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator); @@ -126,12 +104,9 @@ private Q_SLOTS: QNetworkAccessManager *m_networkManager; QString m_username; QString m_password; - int m_currentState = Ready; int m_errorCode = NoError; QString m_errorString; - QUrl m_loginUrl; - QUrl m_portalUrl; - bool m_lastAuthenticationFailed = true; + bool m_lastAuthenticationFailed = false; bool m_authenticationDoneAlready = false; bool m_passwordReadError = false; }; diff --git a/Charm/HttpClient/RestJob.cpp b/Charm/HttpClient/RestJob.cpp new file mode 100644 index 00000000..606ef35d --- /dev/null +++ b/Charm/HttpClient/RestJob.cpp @@ -0,0 +1,76 @@ +/* + RestJob.cpp + + This file is part of Charm, a task-based time tracking application. + + Copyright (C) 2015-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + + Author: Pál Tóth + + 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "RestJob.h" +#include +#include +#include + +RestJob::RestJob(QObject *parent) + : HttpJob(parent) +{ +} + +RestJob::~RestJob() +{ +} + +QByteArray RestJob::resultData() const +{ + return m_resultData; +} + +void RestJob::executeRequest(QNetworkAccessManager *manager) +{ + QNetworkRequest request(m_url); + + QNetworkReply *reply = manager->get(request); + connect(reply, &QNetworkReply::finished, this, &RestJob::handleResult); + + if (reply->error() != QNetworkReply::NoError) + setErrorFromReplyAndEmitFinishedOrRestart(reply); +} + +void RestJob::handleResult() +{ + auto reply = qobject_cast(sender()); + reply->deleteLater(); + + if (reply->error() != QNetworkReply::NoError) { + setErrorFromReplyAndEmitFinishedOrRestart(reply); + return; + } + + m_resultData = reply->readAll(); + emitFinishedOrRestart(); +} + +QUrl RestJob::url() const +{ + return m_url; +} + +void RestJob::setUrl(const QUrl &url) +{ + m_url = url; +} diff --git a/Charm/HttpClient/GetUserInfoJob.h b/Charm/HttpClient/RestJob.h similarity index 54% rename from Charm/HttpClient/GetUserInfoJob.h rename to Charm/HttpClient/RestJob.h index 4c26df72..f7816a2a 100644 --- a/Charm/HttpClient/GetUserInfoJob.h +++ b/Charm/HttpClient/RestJob.h @@ -1,9 +1,9 @@ /* - GetUserInfoJob.h + RestJob.h This file is part of Charm, a task-based time tracking application. - Copyright (C) 2015-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2015-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Pál Tóth @@ -21,44 +21,35 @@ along with this program. If not, see . */ -#ifndef GETUSERINFOJOB_H -#define GETUSERINFOJOB_H +#ifndef RESTJOB_H +#define RESTJOB_H #include "HttpJob.h" #include #include #include -class GetUserInfoJob : public HttpJob +class RestJob : public HttpJob { Q_OBJECT public: - explicit GetUserInfoJob(QObject *parent = nullptr, const QString &schema = QStringLiteral(" ")); - ~GetUserInfoJob() override; + explicit RestJob(QObject *parent = nullptr); + ~RestJob() override; - QByteArray userInfo() const; + QByteArray resultData() const; - QUrl downloadUrl() const; - void setDownloadUrl(const QUrl &url); - QString schema() const; - void setSchema(const QString &schema); + QUrl url() const; + void setUrl(const QUrl &url); public Q_SLOTS: - bool execute(int state, QNetworkAccessManager *manager) override; - bool handle(QNetworkReply *reply) override; - -protected: - - enum State { - GetProjectCodes = HttpJob::Base - }; + void executeRequest(QNetworkAccessManager *manager) override; + void handleResult(); private: - QByteArray m_userInfo; - QUrl m_downloadUrl; - QString m_schema; + QByteArray m_resultData; + QUrl m_url; }; -#endif // GETUSERINFOJOB_H +#endif // RESTJOB_H diff --git a/Charm/HttpClient/UploadTimesheetJob.cpp b/Charm/HttpClient/UploadTimesheetJob.cpp index ee979151..de60cbcc 100644 --- a/Charm/HttpClient/UploadTimesheetJob.cpp +++ b/Charm/HttpClient/UploadTimesheetJob.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2011-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2011-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld Author: Guillermo A. Amaral @@ -27,16 +27,15 @@ #include #include #include -#include // Required for Qt 4 -#include + +#include +#include +#include UploadTimesheetJob::UploadTimesheetJob(QObject *parent) : HttpJob(parent) , m_fileName(QStringLiteral("payload")) { - QSettings s; - s.beginGroup(QStringLiteral("httpconfig")); - setUploadUrl(s.value(QStringLiteral("timesheetUploadUrl")).toUrl()); } UploadTimesheetJob::~UploadTimesheetJob() @@ -73,12 +72,18 @@ void UploadTimesheetJob::setUploadUrl(const QUrl &url) m_uploadUrl = url; } -bool UploadTimesheetJob::execute(int state, QNetworkAccessManager *manager) +UploadTimesheetJob::Status UploadTimesheetJob::status() const { - if (state != UploadTimesheet) - return HttpJob::execute(state, manager); + return m_status; +} - QByteArray data; +void UploadTimesheetJob::setStatus(Status status) +{ + m_status = status; +} + +void UploadTimesheetJob::executeRequest(QNetworkAccessManager *manager) +{ QByteArray uploadName; /* validate filename */ @@ -89,6 +94,7 @@ bool UploadTimesheetJob::execute(int state, QNetworkAccessManager *manager) uploadName = m_fileName.toUtf8(); } + QByteArray data; /* username */ data += "--KDAB\r\n" "Content-Disposition: form-data; name=\"user\"\r\n\r\n"; @@ -102,7 +108,12 @@ bool UploadTimesheetJob::execute(int state, QNetworkAccessManager *manager) data += m_payload; data += "\r\n"; - /* eot */ + if (m_status == Staged) { + data += "--KDAB\r\n"; + data += "Content-Disposition: form-data; name=\"status\"\r\n\r\n"; + data += "STAGED\r\n"; + } + data += "--KDAB--\r\n"; QNetworkRequest request(m_uploadUrl); @@ -111,32 +122,28 @@ bool UploadTimesheetJob::execute(int state, QNetworkAccessManager *manager) request.setHeader(QNetworkRequest::ContentLengthHeader, data.size()); QNetworkReply *reply = manager->post(request, data); - - if (reply->error() != QNetworkReply::NoError) - setErrorFromReplyAndEmitFinished(reply); - return true; + connect(reply, &QNetworkReply::finished, this, &UploadTimesheetJob::handleResult); } -bool UploadTimesheetJob::handle(QNetworkReply *reply) +void UploadTimesheetJob::handleResult() { - /* check for failure */ - if (reply->error() != QNetworkReply::NoError) { - setErrorFromReplyAndEmitFinished(reply); - return false; - } + auto reply = qobject_cast(sender()); + reply->deleteLater(); - if (state() != UploadTimesheet) - return HttpJob::handle(reply); + if (reply->error() == QNetworkReply::ProtocolInvalidOperationError) { + const auto doc = QJsonDocument::fromJson(reply->readAll()); + const auto errorMessage = doc.object().value(QLatin1String("message")).toString(); - const QByteArray answer = reply->readAll(); + setErrorAndEmitFinishedOrRestart(SomethingWentWrong, !errorMessage.isEmpty() + ? errorMessage + : tr("An error occurred, could not extract details")); + return; + } - if (answer.contains("SuccessResultMessage")) { - delayedNext(); - } else { - const QString errorMessage = extractErrorMessageFromReply(answer); - setErrorAndEmitFinished(SomethingWentWrong, !errorMessage.isEmpty() - ? errorMessage - : tr("An error occurred, could not extract details")); + if (reply->error() != QNetworkReply::NoError) { + setErrorFromReplyAndEmitFinishedOrRestart(reply); + return; } - return true; + + emitFinishedOrRestart(); } diff --git a/Charm/HttpClient/UploadTimesheetJob.h b/Charm/HttpClient/UploadTimesheetJob.h index d3e33bbb..2300e925 100644 --- a/Charm/HttpClient/UploadTimesheetJob.h +++ b/Charm/HttpClient/UploadTimesheetJob.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2011-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2011-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -32,6 +32,10 @@ class UploadTimesheetJob : public HttpJob { Q_OBJECT public: + enum Status { + Unreviewed, + Staged + }; explicit UploadTimesheetJob(QObject *parent = nullptr); ~UploadTimesheetJob() override; @@ -43,18 +47,16 @@ class UploadTimesheetJob : public HttpJob QUrl uploadUrl() const; void setUploadUrl(const QUrl &url); -public Q_SLOTS: - - bool execute(int state, QNetworkAccessManager *manager) override; - bool handle(QNetworkReply *reply) override; + Status status() const; + void setStatus(Status status); -protected: +public Q_SLOTS: - enum State { - UploadTimesheet = HttpJob::Base - }; + void executeRequest(QNetworkAccessManager *manager) override; + void handleResult(); private: + Status m_status = Unreviewed; QByteArray m_payload; QString m_fileName; QUrl m_uploadUrl; diff --git a/Charm/Idle/IdleDetector.cpp b/Charm/Idle/IdleDetector.cpp index 8e25c5ee..ee38cada 100644 --- a/Charm/Idle/IdleDetector.cpp +++ b/Charm/Idle/IdleDetector.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Mike McQuaid @@ -29,6 +29,7 @@ #include "MacIdleDetector.h" #include "WindowsIdleDetector.h" #include "X11IdleDetector.h" +#include "ViewHelpers.h" #include "Core/Configuration.h" @@ -37,7 +38,7 @@ IdleDetector::IdleDetector(QObject *parent) : QObject(parent) - , m_idlenessDuration(CHARM_IDLE_TIME) // from CharmCMake.h + , m_idlenessDuration(CharmIdleTime) // from CharmCMake.h { } @@ -98,7 +99,7 @@ int IdleDetector::idlenessDuration() const void IdleDetector::maybeIdle(IdlePeriod period) { - if (!Configuration::instance().detectIdling) + if (!Configuration::instance().detectIdling || DATAMODEL->activeEventCount() == 0) return; qDebug() << "IdleDetector::maybeIdle: Checking for idleness"; @@ -136,7 +137,7 @@ void IdleDetector::maybeIdle(IdlePeriod period) // notify application if (!idlePeriods().isEmpty()) { qDebug() << "IdleDetector::maybeIdle: Found idleness"; - emit maybeIdle(); + QTimer::singleShot(0, this, [=](){ emit maybeIdle(); }); } } diff --git a/Charm/Idle/IdleDetector.h b/Charm/Idle/IdleDetector.h index d2132493..453839c7 100644 --- a/Charm/Idle/IdleDetector.h +++ b/Charm/Idle/IdleDetector.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Charm/Idle/MacIdleDetector.h b/Charm/Idle/MacIdleDetector.h index 43902604..80689a82 100644 --- a/Charm/Idle/MacIdleDetector.h +++ b/Charm/Idle/MacIdleDetector.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2011-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2011-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mike McQuaid diff --git a/Charm/Idle/MacIdleDetector.mm b/Charm/Idle/MacIdleDetector.mm index 0c200379..05a3f698 100644 --- a/Charm/Idle/MacIdleDetector.mm +++ b/Charm/Idle/MacIdleDetector.mm @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2011-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2011-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mike McQuaid diff --git a/Charm/Idle/WindowsIdleDetector.cpp b/Charm/Idle/WindowsIdleDetector.cpp index 7225bcdd..52e472ab 100644 --- a/Charm/Idle/WindowsIdleDetector.cpp +++ b/Charm/Idle/WindowsIdleDetector.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2010-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2010-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld Author: Mike McQuaid @@ -30,7 +30,7 @@ WindowsIdleDetector::WindowsIdleDetector(QObject *parent) : IdleDetector(parent) { - connect(&m_timer, SIGNAL(timeout()), this, SLOT(timeout())); + connect(&m_timer, &QTimer::timeout, this, &WindowsIdleDetector::timeout); m_timer.setInterval(idlenessDuration() * 1000 / 2); m_timer.setSingleShot(false); m_timer.start(); diff --git a/Charm/Idle/WindowsIdleDetector.h b/Charm/Idle/WindowsIdleDetector.h index 737a3b93..3f1a49d2 100644 --- a/Charm/Idle/WindowsIdleDetector.h +++ b/Charm/Idle/WindowsIdleDetector.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2010-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2010-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -35,7 +35,7 @@ class WindowsIdleDetector : public IdleDetector explicit WindowsIdleDetector(QObject *parent); protected: - void onIdlenessDurationChanged(); + void onIdlenessDurationChanged() override; private Q_SLOTS: void timeout(); diff --git a/Charm/Idle/X11IdleDetector.cpp b/Charm/Idle/X11IdleDetector.cpp index 38fa03f3..55bb1829 100644 --- a/Charm/Idle/X11IdleDetector.cpp +++ b/Charm/Idle/X11IdleDetector.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Jesper Pedersen Author: Frank Osterfeld @@ -32,7 +32,7 @@ X11IdleDetector::X11IdleDetector(QObject *parent) : IdleDetector(parent) { - connect(&m_timer, SIGNAL(timeout()), this, SLOT(checkIdleness())); + connect(&m_timer, &QTimer::timeout, this, &X11IdleDetector::checkIdleness); m_timer.start(idlenessDuration() * 1000 / 5); m_heartbeat = QDateTime::currentDateTime(); } diff --git a/Charm/Idle/X11IdleDetector.h b/Charm/Idle/X11IdleDetector.h index e47ee667..710f0013 100644 --- a/Charm/Idle/X11IdleDetector.h +++ b/Charm/Idle/X11IdleDetector.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Jesper Pedersen Author: Frank Osterfeld @@ -41,7 +41,7 @@ class X11IdleDetector : public IdleDetector bool idleCheckPossible(); protected: - void onIdlenessDurationChanged(); + void onIdlenessDurationChanged() override; private Q_SLOTS: void checkIdleness(); diff --git a/Charm/Lotsofcake/Configuration.cpp b/Charm/Lotsofcake/Configuration.cpp new file mode 100644 index 00000000..deff297a --- /dev/null +++ b/Charm/Lotsofcake/Configuration.cpp @@ -0,0 +1,113 @@ +/* + Configuration.cpp + + This file is part of Charm, a task-based time tracking application. + + Copyright (C) 2017-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + + Author: Frank Osterfeld + + 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "Lotsofcake/Configuration.h" +#include "Core/XmlSerialization.h" + +#include +#include + +static const char *s_group = "httpconfig"; +static const char *s_keyUsername = "username"; +static const char *s_keyTimesheetUploadUrl = "timesheetUploadUrl"; +static const char *s_keyProjectCodeDownloadUrl = "projectCodeDownloadUrl"; +static const char *s_keyRestUrl = "restUrl"; +static const char *s_keyLastStagedTimesheetUpload = "lastStagedTimesheetUpload"; + +static void setValueIfNotNull(QSettings *s, const QString &key, const QString &value) +{ + if (!value.isNull()) { + s->setValue(key, value); + } else { + s->remove(key); + } +} + +bool Lotsofcake::Configuration::isConfigured() const +{ + return !username().isEmpty(); +} + +void Lotsofcake::Configuration::importFromTaskExport(const TaskExport &exporter) +{ + QSettings settings; + settings.beginGroup(QLatin1String(s_group)); + setValueIfNotNull(&settings, QLatin1String(s_keyUsername), + exporter.metadata(QStringLiteral("username"))); + setValueIfNotNull(&settings, QLatin1String(s_keyTimesheetUploadUrl), + exporter.metadata(QStringLiteral("timesheet-upload-url"))); + setValueIfNotNull(&settings, QLatin1String(s_keyProjectCodeDownloadUrl), + exporter.metadata(QStringLiteral("project-code-download-url"))); + setValueIfNotNull(&settings, QLatin1String(s_keyRestUrl), exporter.metadata(QStringLiteral("rest-url"))); +} + +QString Lotsofcake::Configuration::username() const +{ + QSettings settings; + settings.beginGroup(QLatin1String(s_group)); + return settings.value(QLatin1String(s_keyUsername)).toString(); +} + +QUrl Lotsofcake::Configuration::timesheetUploadUrl() const +{ + QSettings settings; + settings.beginGroup(QLatin1String(s_group)); + QUrl url = settings.value(QLatin1String(s_keyTimesheetUploadUrl)).toUrl(); + url.setPath(QLatin1String("/KdabHome/apps/timesheets/rest/upload")); // TODO don't use hardcoded path + return url; +} + +QUrl Lotsofcake::Configuration::projectCodeDownloadUrl() const +{ + QSettings settings; + settings.beginGroup(QLatin1String(s_group)); + return settings.value(QLatin1String(s_keyProjectCodeDownloadUrl)).toUrl(); +} + +QUrl Lotsofcake::Configuration::restUrl() const +{ + QSettings settings; + settings.beginGroup(QLatin1String(s_group)); + return settings.value(QLatin1String(s_keyRestUrl)).toUrl(); +} + +QDate Lotsofcake::Configuration::lastStagedTimesheetUpload() const +{ + if (!m_lastStagedTimesheetUpload.set) { + QSettings settings; + settings.beginGroup(QLatin1String(s_group)); + m_lastStagedTimesheetUpload.date = settings.value(QLatin1String(s_keyLastStagedTimesheetUpload)).toDate(); + m_lastStagedTimesheetUpload.set = true; + } + + return m_lastStagedTimesheetUpload.date; +} + +void Lotsofcake::Configuration::setLastStagedTimesheetUpload(const QDate &date) +{ + QSettings settings; + settings.beginGroup(QLatin1String(s_group)); + settings.setValue(QLatin1String(s_keyLastStagedTimesheetUpload), date); + m_lastStagedTimesheetUpload.date = date; + m_lastStagedTimesheetUpload.set = true; +} diff --git a/Core/Installation.h b/Charm/Lotsofcake/Configuration.h similarity index 50% rename from Core/Installation.h rename to Charm/Lotsofcake/Configuration.h index 4f210e97..a56003f1 100644 --- a/Core/Installation.h +++ b/Charm/Lotsofcake/Configuration.h @@ -1,11 +1,11 @@ /* - Installation.h + Configuration.h This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2017-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com - Author: Mirko Boehm + Author: Frank Osterfeld 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 @@ -21,58 +21,40 @@ along with this program. If not, see . */ -#ifndef INSTALLATION_H -#define INSTALLATION_H +#ifndef LOTSOFCAKE_CONFIGURATION_H +#define LOTSOFCAKE_CONFIGURATION_H -#include +#include -class Installation +class QString; +class QUrl; + +class TaskExport; + +namespace Lotsofcake { + +class Configuration { public: - Installation() : m_id() - , m_userId() - { - } - - bool isValid() const - { - return m_id != 0; - } - - int id() const - { - return m_id; - } - - void setId(int newid) - { - m_id = newid; - } - - int userId() const - { - return m_userId; - } - - void setUserId(int userId) - { - m_userId = userId; - } - - QString name() const - { - return m_name; - } - - void setName(const QString &newname) - { - m_name = newname; - } + bool isConfigured() const; + + void importFromTaskExport(const TaskExport &exporter); + + QDate lastStagedTimesheetUpload() const; + void setLastStagedTimesheetUpload(const QDate &date); + + QString username() const; + QUrl timesheetUploadUrl() const; + QUrl projectCodeDownloadUrl() const; + QUrl restUrl() const; private: - int m_id; - int m_userId; - QString m_name; + mutable struct { + bool set = false; + QDate date; + } m_lastStagedTimesheetUpload; }; +} + #endif diff --git a/Charm/MacApplicationCore.h b/Charm/MacApplicationCore.h index b90019b8..309989e4 100644 --- a/Charm/MacApplicationCore.h +++ b/Charm/MacApplicationCore.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -30,7 +30,7 @@ class MacApplicationCore : public ApplicationCore { Q_OBJECT public: - explicit MacApplicationCore(TaskId startupTask, QObject *parent = nullptr); + explicit MacApplicationCore(TaskId startupTask, bool hideAtStart, QObject *parent = nullptr); ~MacApplicationCore(); // This method to be public due to lack of friend classes in Objective-C and // the lack inheritance of Objective-C classes from C++ ones. diff --git a/Charm/MacApplicationCore.mm b/Charm/MacApplicationCore.mm index 3c7b4a12..f7e70bb1 100644 --- a/Charm/MacApplicationCore.mm +++ b/Charm/MacApplicationCore.mm @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -121,8 +121,8 @@ - (void)handleDockClickEvent:(NSAppleEventDescriptor*)event withReplyEvent:(NSAp andEventID:kAEReopenApplication]; } -MacApplicationCore::MacApplicationCore( TaskId startupTask, QObject* parent ) - : ApplicationCore( startupTask, parent ) +MacApplicationCore::MacApplicationCore( TaskId startupTask, bool hideAtStart, QObject* parent ) + : ApplicationCore( startupTask, hideAtStart, parent ) , m_private( new MacApplicationCore::Private() ) { m_private->dockIconClickEventHandler->macApplication = this; diff --git a/Charm/ModelConnector.cpp b/Charm/ModelConnector.cpp index cb199b9f..13cf90d2 100644 --- a/Charm/ModelConnector.cpp +++ b/Charm/ModelConnector.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld @@ -39,12 +39,12 @@ ModelConnector::ModelConnector() , m_eventModelFilter(&m_dataModel) , m_findEventModelFilter(&m_dataModel) { - connect(&m_dataModel, SIGNAL(makeAndActivateEvent(Task)), - SLOT(slotMakeAndActivateEvent(Task))); - connect(&m_dataModel, SIGNAL(requestEventModification(Event,Event)), - SLOT(slotRequestEventModification(Event,Event))); - connect(&m_dataModel, SIGNAL(sysTrayUpdate(QString,bool)), - SLOT(slotSysTrayUpdate(QString,bool))); + connect(&m_dataModel, &CharmDataModel::makeAndActivateEvent, + this, &ModelConnector::slotMakeAndActivateEvent); + connect(&m_dataModel, &CharmDataModel::requestEventModification, + this, &ModelConnector::slotRequestEventModification); + connect(&m_dataModel, &CharmDataModel::sysTrayUpdate, + this, &ModelConnector::slotSysTrayUpdate); } CharmDataModel *ModelConnector::charmDataModel() diff --git a/Charm/ModelConnector.h b/Charm/ModelConnector.h index e7212632..ca972d8b 100644 --- a/Charm/ModelConnector.h +++ b/Charm/ModelConnector.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: David Faure diff --git a/Charm/QtQuick/Charm.cpp b/Charm/QtQuick/Charm.cpp index 7ce9384a..6a2df991 100644 --- a/Charm/QtQuick/Charm.cpp +++ b/Charm/QtQuick/Charm.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/QtQuick/qml/main.qml b/Charm/QtQuick/qml/main.qml index 85587cfb..9cff7af2 100644 --- a/Charm/QtQuick/qml/main.qml +++ b/Charm/QtQuick/qml/main.qml @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/Reports/MonthlyTimesheetXmlWriter.cpp b/Charm/Reports/MonthlyTimesheetXmlWriter.cpp index 8325ee92..ae11a333 100644 --- a/Charm/Reports/MonthlyTimesheetXmlWriter.cpp +++ b/Charm/Reports/MonthlyTimesheetXmlWriter.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -24,22 +24,13 @@ #include "MonthlyTimesheetXmlWriter.h" #include "TimesheetInfo.h" -#include "CharmCMake.h" - -#include "Core/CharmDataModel.h" -#include - #include MonthlyTimesheetXmlWriter::MonthlyTimesheetXmlWriter() + : TimesheetXmlWriter(QLatin1String("monthly-timesheet")) { } -void MonthlyTimesheetXmlWriter::setDataModel(const CharmDataModel *dataModel) -{ - m_dataModel = dataModel; -} - void MonthlyTimesheetXmlWriter::setYearOfMonth(int yearOfMonth) { m_yearOfMonth = yearOfMonth; @@ -50,118 +41,27 @@ void MonthlyTimesheetXmlWriter::setMonthNumber(int monthNumber) m_monthNumber = monthNumber; } -void MonthlyTimesheetXmlWriter::setEvents(const EventList &events) -{ - m_events = events; -} - void MonthlyTimesheetXmlWriter::setNumberOfWeeks(int numberOfWeeks) { m_numberOfWeeks = numberOfWeeks; } -void MonthlyTimesheetXmlWriter::setRootTask(TaskId rootTask) +void MonthlyTimesheetXmlWriter::writeMetadata(QDomDocument &document, QDomElement &metadata) const { - m_rootTask = rootTask; + QDomElement yearElement = document.createElement(QStringLiteral("year")); + metadata.appendChild(yearElement); + QDomText text = document.createTextNode(QString::number(m_yearOfMonth)); + yearElement.appendChild(text); + QDomElement monthElement = document.createElement(QStringLiteral("serial-number")); + monthElement.setAttribute(QStringLiteral("semantics"), QStringLiteral("month-number")); + metadata.appendChild(monthElement); + QDomText monthtext = document.createTextNode(QString::number(m_monthNumber)); + monthElement.appendChild(monthtext); } -QByteArray MonthlyTimesheetXmlWriter::saveToXml() const +QList MonthlyTimesheetXmlWriter::createTimeSheetInfo() const { - QDomDocument document - = XmlSerialization::createXmlTemplate(QStringLiteral("monthly-timesheet")); - - // find metadata and report element: - QDomElement root = document.documentElement(); - QDomElement metadata = XmlSerialization::metadataElement(document); - QDomElement charmVersion = document.createElement(QStringLiteral("charmversion")); - QDomText charmVersionString = document.createTextNode(QStringLiteral(CHARM_VERSION)); - charmVersion.appendChild(charmVersionString); - metadata.appendChild(charmVersion); - QDomElement report = XmlSerialization::reportElement(document); - Q_ASSERT(!root.isNull() && !metadata.isNull() && !report.isNull()); - - // extend metadata tag: add year, and serial (month) number: - { - QDomElement yearElement = document.createElement(QStringLiteral("year")); - metadata.appendChild(yearElement); - QDomText text = document.createTextNode(QString::number(m_yearOfMonth)); - yearElement.appendChild(text); - QDomElement monthElement = document.createElement(QStringLiteral("serial-number")); - monthElement.setAttribute(QStringLiteral("semantics"), QStringLiteral("month-number")); - metadata.appendChild(monthElement); - QDomText monthtext = document.createTextNode(QString::number(m_monthNumber)); - monthElement.appendChild(monthtext); - } - - typedef QMap< TaskId, QVector > SecondsMap; - SecondsMap secondsMap; - TimeSheetInfoList timeSheetInfo = TimeSheetInfo::filteredTaskWithSubTasks( - TimeSheetInfo::taskWithSubTasks(m_dataModel, m_numberOfWeeks, m_rootTask, secondsMap), - false); // here, we don't care about active or not, because we only report on the tasks - - // extend report tag: add tasks and effort structure - { // tasks - QDomElement tasks = document.createElement(QStringLiteral("tasks")); - report.appendChild(tasks); - Q_FOREACH (const TimeSheetInfo &info, timeSheetInfo) { - if (info.taskId == 0) // the root task - continue; - const Task &modelTask = m_dataModel->getTask(info.taskId); - tasks.appendChild(modelTask.toXml(document)); - } - } - { // effort - // make effort element: - QDomElement effort = document.createElement(QStringLiteral("effort")); - report.appendChild(effort); - - // aggregate (group by task and day): - typedef QPair Key; - QMap< Key, Event> events; - Q_FOREACH (const Event &event, m_events) { - TimeSheetInfoList::iterator it; - for (it = timeSheetInfo.begin(); it != timeSheetInfo.end(); ++it) - if ((*it).taskId == event.taskId()) break; - if (it == timeSheetInfo.end()) - continue; - Key key(event.taskId(), event.startDateTime().date()); - if (events.contains(key)) { - // add to previous events: - const Event &oldEvent = events[key]; - const int seconds = oldEvent.duration() + event.duration(); - const QDateTime start = oldEvent.startDateTime(); - const QDateTime end(start.addSecs(seconds)); - Q_ASSERT(start.secsTo(end) == seconds); - Event newEvent(oldEvent); - newEvent.setStartDateTime(start); - newEvent.setEndDateTime(end); - Q_ASSERT(newEvent.duration() == seconds); - QString comment = oldEvent.comment(); - if (!event.comment().isEmpty()) { - if (!comment.isEmpty()) // make separator - comment += QLatin1String(" / "); - comment += event.comment(); - newEvent.setComment(comment); - } - events[key] = newEvent; - } else { - // add this event: - events[key] = event; - events[key].setId(-events[key].id()); // "synthetic" :-) - // move to start at midnight in UTC (for privacy reasons) - // never, never, never use setTime() here, it breaks on DST changes! (twice a year) - QDateTime start(event.startDateTime().date(), QTime(0, 0, 0, 0), Qt::UTC); - QDateTime end(start.addSecs(event.duration())); - events[key].setStartDateTime(start); - events[key].setEndDateTime(end); - Q_ASSERT(events[key].duration() == event.duration()); - Q_ASSERT(start.time() == QTime(0, 0, 0, 0)); - } - } - // create elements: - Q_FOREACH (const Event &event, events) - effort.appendChild(event.toXml(document)); - } - - return document.toByteArray(4); + return TimeSheetInfo::filteredTaskWithSubTasks( + TimeSheetInfo::taskWithSubTasks(dataModel(), m_numberOfWeeks, rootTask(), SecondsMap()), + false); // here, we don't care about active or not, because we only report on the tasks } diff --git a/Charm/Reports/MonthlyTimesheetXmlWriter.h b/Charm/Reports/MonthlyTimesheetXmlWriter.h index 4c99700c..9db31352 100644 --- a/Charm/Reports/MonthlyTimesheetXmlWriter.h +++ b/Charm/Reports/MonthlyTimesheetXmlWriter.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -24,35 +24,25 @@ #ifndef MONTHLYTIMESHEETXMLWRITER_H #define MONTHLYTIMESHEETXMLWRITER_H -#include "Core/Event.h" -#include "Core/Task.h" +#include "TimesheetXmlWriter.h" -class QByteArray; -class CharmDataModel; - -class MonthlyTimesheetXmlWriter +class MonthlyTimesheetXmlWriter : public TimesheetXmlWriter { public: MonthlyTimesheetXmlWriter(); - /** - * @throws XmlSerializationException - */ - QByteArray saveToXml() const; - void setDataModel(const CharmDataModel *dataModel); void setYearOfMonth(int yearOfMonth); void setMonthNumber(int monthNumber); void setNumberOfWeeks(int numberOfWeeks); - void setEvents(const EventList &events); - void setRootTask(TaskId rootTask); + +protected: + void writeMetadata(QDomDocument &document, QDomElement &metadata) const override; + QList createTimeSheetInfo() const override; private: - const CharmDataModel *m_dataModel = nullptr; int m_yearOfMonth = 0; int m_monthNumber = 0; int m_numberOfWeeks = 0; - TaskId m_rootTask = {}; - EventList m_events; }; #endif diff --git a/Charm/Reports/TimesheetInfo.cpp b/Charm/Reports/TimesheetInfo.cpp index 89baefb5..12936f5f 100644 --- a/Charm/Reports/TimesheetInfo.cpp +++ b/Charm/Reports/TimesheetInfo.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/Reports/TimesheetInfo.h b/Charm/Reports/TimesheetInfo.h index abea4964..94060305 100644 --- a/Charm/Reports/TimesheetInfo.h +++ b/Charm/Reports/TimesheetInfo.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/Reports/TimesheetXmlWriter.cpp b/Charm/Reports/TimesheetXmlWriter.cpp new file mode 100644 index 00000000..5b221826 --- /dev/null +++ b/Charm/Reports/TimesheetXmlWriter.cpp @@ -0,0 +1,172 @@ +/* + TimesheetXmlWriter.cpp + + This file is part of Charm, a task-based time tracking application. + + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + + Author: Frank Osterfeld + + 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "TimesheetXmlWriter.h" +#include "TimesheetInfo.h" +#include "CharmCMake.h" + +#include "Core/CharmDataModel.h" +#include "Core/CharmConstants.h" +#include "Core/XmlSerialization.h" + +#include + +TimesheetXmlWriter::TimesheetXmlWriter(const QString &templateName) + : m_templateName(templateName) +{ +} + +TimesheetXmlWriter::~TimesheetXmlWriter() +{ +} + +const CharmDataModel *TimesheetXmlWriter::dataModel() const +{ + return m_dataModel; +} + +void TimesheetXmlWriter::setDataModel(const CharmDataModel *model) +{ + m_dataModel = model; +} + +EventList TimesheetXmlWriter::events() const +{ + return m_events; +} + +void TimesheetXmlWriter::setEvents(const EventList &events) +{ + m_events = events; +} + +TaskId TimesheetXmlWriter::rootTask() const +{ + return m_rootTask; +} + +void TimesheetXmlWriter::setRootTask(TaskId rootTask) +{ + m_rootTask = rootTask; +} + +bool TimesheetXmlWriter::includeTaskList() const +{ + return m_includeTaskList; +} + +void TimesheetXmlWriter::setIncludeTaskList(bool includeTaskList) +{ + m_includeTaskList = includeTaskList; +} + +QByteArray TimesheetXmlWriter::saveToXml() const +{ + // now create the report: + QDomDocument document = XmlSerialization::createXmlTemplate(m_templateName); + + // find metadata and report element: + QDomElement root = document.documentElement(); + QDomElement metadata = XmlSerialization::metadataElement(document); + QDomElement charmVersion = document.createElement(QStringLiteral("charmversion")); + QDomText charmVersionString = document.createTextNode(CharmVersion()); + charmVersion.appendChild(charmVersionString); + metadata.appendChild(charmVersion); + auto installationId = document.createElement(QStringLiteral("installation-id")); + const auto installationIdString = document.createTextNode(QString::number(CONFIGURATION.installationId)); + installationId.appendChild(installationIdString); + metadata.appendChild(installationId); + + QDomElement report = XmlSerialization::reportElement(document); + Q_ASSERT(!root.isNull() && !metadata.isNull() && !report.isNull()); + + writeMetadata(document, metadata); + + TimeSheetInfoList timeSheetInfo = createTimeSheetInfo(); + // extend report tag: add tasks and effort structure + + if (m_includeTaskList) { // tasks + QDomElement tasks = document.createElement(QStringLiteral("tasks")); + report.appendChild(tasks); + Q_FOREACH (const TimeSheetInfo &info, timeSheetInfo) { + if (info.taskId == 0) // the root task + continue; + const Task &modelTask = m_dataModel->getTask(info.taskId); + tasks.appendChild(modelTask.toXml(document)); + } + } + { // effort + // make effort element: + QDomElement effort = document.createElement(QStringLiteral("effort")); + report.appendChild(effort); + + // aggregate (group by task and day): + typedef QPair Key; + QMap< Key, Event> events; + Q_FOREACH (const Event &event, m_events) { + TimeSheetInfoList::iterator it; + for (it = timeSheetInfo.begin(); it != timeSheetInfo.end(); ++it) + if ((*it).taskId == event.taskId()) break; + if (it == timeSheetInfo.end()) + continue; + Key key(event.taskId(), event.startDateTime().date()); + if (events.contains(key)) { + // add to previous events: + const Event &oldEvent = events[key]; + const int seconds = oldEvent.duration() + event.duration(); + const QDateTime start = oldEvent.startDateTime(); + const QDateTime end(start.addSecs(seconds)); + Q_ASSERT(start.secsTo(end) == seconds); + Event newEvent(oldEvent); + newEvent.setStartDateTime(start); + newEvent.setEndDateTime(end); + Q_ASSERT(newEvent.duration() == seconds); + QString comment = oldEvent.comment(); + if (!event.comment().isEmpty()) { + if (!comment.isEmpty()) // make separator + comment += QLatin1String(" / "); + comment += event.comment(); + newEvent.setComment(comment); + } + events[key] = newEvent; + } else { + // add this event: + events[key] = event; + events[key].setId(-events[key].id()); // "synthetic" :-) + // move to start at midnight in UTC (for privacy reasons) + // never, never, never use setTime() here, it breaks on DST changes! (twice a year) + QDateTime start(event.startDateTime().date(), QTime(0, 0, 0, 0), Qt::UTC); + QDateTime end(start.addSecs(event.duration())); + events[key].setStartDateTime(start); + events[key].setEndDateTime(end); + Q_ASSERT(events[key].duration() == event.duration()); + Q_ASSERT(start.time() == QTime(0, 0, 0, 0)); + } + } + // create elements: + Q_FOREACH (const Event &event, events) + effort.appendChild(event.toXml(document)); + } + + return document.toByteArray(4); +} diff --git a/Charm/Reports/TimesheetXmlWriter.h b/Charm/Reports/TimesheetXmlWriter.h new file mode 100644 index 00000000..b8313fd0 --- /dev/null +++ b/Charm/Reports/TimesheetXmlWriter.h @@ -0,0 +1,73 @@ +/* + TimesheetXmlWriter.h + + This file is part of Charm, a task-based time tracking application. + + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + + Author: Frank Osterfeld + + 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef TIMESHEETXMLWRITER_H +#define TIMESHEETXMLWRITER_H + +#include + +#include "Core/Event.h" +#include "Core/Task.h" + +class QByteArray; +class QDomDocument; +class QDomElement; + +class CharmDataModel; +class TimeSheetInfo; + +class TimesheetXmlWriter { +public: + explicit TimesheetXmlWriter(const QString &templateName); + virtual ~TimesheetXmlWriter(); + + const CharmDataModel *dataModel() const; + void setDataModel(const CharmDataModel *model); + + TaskId rootTask() const; + void setRootTask(TaskId rootTask); + + bool includeTaskList() const; + void setIncludeTaskList(bool); + + /** + * @throws XmlSerializationException + */ + QByteArray saveToXml() const; + + EventList events() const; + void setEvents(const EventList &events); + +protected: + virtual void writeMetadata(QDomDocument &document, QDomElement &metadata) const = 0; + virtual QList createTimeSheetInfo() const = 0; + +private: + const CharmDataModel *m_dataModel = nullptr; + EventList m_events; + TaskId m_rootTask = {}; + QString m_templateName; + bool m_includeTaskList = true; +}; + +#endif diff --git a/Charm/Reports/WeeklyTimesheetXmlWriter.cpp b/Charm/Reports/WeeklyTimesheetXmlWriter.cpp index 23770942..0e959998 100644 --- a/Charm/Reports/WeeklyTimesheetXmlWriter.cpp +++ b/Charm/Reports/WeeklyTimesheetXmlWriter.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -23,24 +23,14 @@ #include "WeeklyTimesheetXmlWriter.h" #include "TimesheetInfo.h" -#include "CharmCMake.h" - -#include "Core/CharmDataModel.h" -#include #include -static const int DaysInWeek = 7; - WeeklyTimesheetXmlWriter::WeeklyTimesheetXmlWriter() + : TimesheetXmlWriter(QLatin1String("weekly-timesheet")) { } -void WeeklyTimesheetXmlWriter::setDataModel(const CharmDataModel *model) -{ - m_dataModel = model; -} - void WeeklyTimesheetXmlWriter::setYear(int year) { m_year = year; @@ -51,122 +41,24 @@ void WeeklyTimesheetXmlWriter::setWeekNumber(int weekNumber) m_weekNumber = weekNumber; } -void WeeklyTimesheetXmlWriter::setEvents(const EventList &events) +void WeeklyTimesheetXmlWriter::writeMetadata(QDomDocument &document, QDomElement &metadata) const { - m_events = events; -} - -void WeeklyTimesheetXmlWriter::setRootTask(TaskId rootTask) -{ - m_rootTask = rootTask; + // extend metadata tag: add year, and serial (week) number: + QDomElement yearElement = document.createElement(QStringLiteral("year")); + metadata.appendChild(yearElement); + QDomText text = document.createTextNode(QString::number(m_year)); + yearElement.appendChild(text); + QDomElement weekElement = document.createElement(QStringLiteral("serial-number")); + weekElement.setAttribute(QStringLiteral("semantics"), QStringLiteral("week-number")); + metadata.appendChild(weekElement); + QDomText weektext = document.createTextNode(QString::number(m_weekNumber)); + weekElement.appendChild(weektext); } -QByteArray WeeklyTimesheetXmlWriter::saveToXml() const +QList WeeklyTimesheetXmlWriter::createTimeSheetInfo() const { - // now create the report: - QDomDocument document = XmlSerialization::createXmlTemplate(QStringLiteral("weekly-timesheet")); - - // find metadata and report element: - QDomElement root = document.documentElement(); - QDomElement metadata = XmlSerialization::metadataElement(document); - QDomElement charmVersion = document.createElement(QStringLiteral("charmversion")); - QDomText charmVersionString = document.createTextNode(QStringLiteral(CHARM_VERSION)); - charmVersion.appendChild(charmVersionString); - metadata.appendChild(charmVersion); - QDomElement report = XmlSerialization::reportElement(document); - Q_ASSERT(!root.isNull() && !metadata.isNull() && !report.isNull()); - - // extend metadata tag: add year, and serial (week) number: - { - QDomElement yearElement = document.createElement(QStringLiteral("year")); - metadata.appendChild(yearElement); - QDomText text = document.createTextNode(QString::number(m_year)); - yearElement.appendChild(text); - QDomElement weekElement = document.createElement(QStringLiteral("serial-number")); - weekElement.setAttribute(QStringLiteral("semantics"), QStringLiteral("week-number")); - metadata.appendChild(weekElement); - QDomText weektext = document.createTextNode(QString::number(m_weekNumber)); - weekElement.appendChild(weektext); - } - - typedef QMap< TaskId, QVector > SecondsMap; - SecondsMap secondsMap; - TimeSheetInfoList timeSheetInfo = TimeSheetInfo::filteredTaskWithSubTasks( - TimeSheetInfo::taskWithSubTasks(m_dataModel, DaysInWeek, m_rootTask, secondsMap), - false); // here, we don't care about active or not, because we only report on the tasks - - // extend report tag: add tasks and effort structure - { // tasks - QDomElement tasks = document.createElement(QStringLiteral("tasks")); - report.appendChild(tasks); - Q_FOREACH (const TimeSheetInfo &info, timeSheetInfo) { - if (info.taskId == 0) // the root task - continue; - const Task &modelTask = m_dataModel->getTask(info.taskId); - tasks.appendChild(modelTask.toXml(document)); -// TaskId parentTask = DATAMODEL->parentItem( modelTask ).task().id(); -// QDomElement task = document.createElement( "task" ); -// task.setAttribute( "taskid", QString::number( info.taskId ) ); -// if ( parentTask != 0 ) -// task.setAttribute( "parent", QString::number( parentTask ) ); - -// QDomText name = document.createTextNode( modelTask.name() ); -// task.appendChild( name ); -// tasks.appendChild( task ); - } - } - { // effort - // make effort element: - QDomElement effort = document.createElement(QStringLiteral("effort")); - report.appendChild(effort); - - // aggregate (group by task and day): - typedef QPair Key; - QMap< Key, Event> events; - Q_FOREACH (const Event &event, m_events) { - TimeSheetInfoList::iterator it; - for (it = timeSheetInfo.begin(); it != timeSheetInfo.end(); ++it) - if ((*it).taskId == event.taskId()) break; - if (it == timeSheetInfo.end()) - continue; - Key key(event.taskId(), event.startDateTime().date()); - if (events.contains(key)) { - // add to previous events: - const Event &oldEvent = events[key]; - const int seconds = oldEvent.duration() + event.duration(); - const QDateTime start = oldEvent.startDateTime(); - const QDateTime end(start.addSecs(seconds)); - Q_ASSERT(start.secsTo(end) == seconds); - Event newEvent(oldEvent); - newEvent.setStartDateTime(start); - newEvent.setEndDateTime(end); - Q_ASSERT(newEvent.duration() == seconds); - QString comment = oldEvent.comment(); - if (!event.comment().isEmpty()) { - if (!comment.isEmpty()) // make separator - comment += QLatin1String(" / "); - comment += event.comment(); - newEvent.setComment(comment); - } - events[key] = newEvent; - } else { - // add this event: - events[key] = event; - events[key].setId(-events[key].id()); // "synthetic" :-) - // move to start at midnight in UTC (for privacy reasons) - // never, never, never use setTime() here, it breaks on DST changes! (twice a year) - QDateTime start(event.startDateTime().date(), QTime(0, 0, 0, 0), Qt::UTC); - QDateTime end(start.addSecs(event.duration())); - events[key].setStartDateTime(start); - events[key].setEndDateTime(end); - Q_ASSERT(events[key].duration() == event.duration()); - Q_ASSERT(start.time() == QTime(0, 0, 0, 0)); - } - } - // create elements: - Q_FOREACH (const Event &event, events) - effort.appendChild(event.toXml(document)); - } - - return document.toByteArray(4); + static const int DaysInWeek = 7; + return TimeSheetInfo::filteredTaskWithSubTasks( + TimeSheetInfo::taskWithSubTasks(dataModel(), DaysInWeek, rootTask(), SecondsMap()), + false); // here, we don't care about active or not, because we only report on the tasks } diff --git a/Charm/Reports/WeeklyTimesheetXmlWriter.h b/Charm/Reports/WeeklyTimesheetXmlWriter.h index 5528a9f3..e762a8e8 100644 --- a/Charm/Reports/WeeklyTimesheetXmlWriter.h +++ b/Charm/Reports/WeeklyTimesheetXmlWriter.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -24,32 +24,23 @@ #ifndef WEEKLYTIMESHEETXMLWRITER_H #define WEEKLYTIMESHEETXMLWRITER_H -#include "Core/Event.h" -#include "Core/Task.h" +#include "TimesheetXmlWriter.h" -class QByteArray; -class CharmDataModel; - -class WeeklyTimesheetXmlWriter +class WeeklyTimesheetXmlWriter : public TimesheetXmlWriter { public: WeeklyTimesheetXmlWriter(); - /** - * @throws XmlSerializationException - */ - QByteArray saveToXml() const; - void setDataModel(const CharmDataModel *model); void setYear(int year); void setWeekNumber(int weekNumber); - void setEvents(const EventList &events); - void setRootTask(TaskId rootTask); + +protected: + void writeMetadata(QDomDocument &document, QDomElement &metadata) const override; + QList createTimeSheetInfo() const override; + private: - const CharmDataModel *m_dataModel = nullptr; int m_year = 0; int m_weekNumber = 0; - TaskId m_rootTask = {}; - EventList m_events; }; #endif diff --git a/Charm/TaskModelAdapter.cpp b/Charm/TaskModelAdapter.cpp index 6c2d40db..5e696e33 100644 --- a/Charm/TaskModelAdapter.cpp +++ b/Charm/TaskModelAdapter.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Charm/TaskModelAdapter.h b/Charm/TaskModelAdapter.h index 03261326..847ffa98 100644 --- a/Charm/TaskModelAdapter.h +++ b/Charm/TaskModelAdapter.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Charm/TemporaryValue.h b/Charm/TemporaryValue.h index e5f874aa..90da8bc5 100644 --- a/Charm/TemporaryValue.h +++ b/Charm/TemporaryValue.h @@ -1,7 +1,7 @@ /* This file is part of Charm, a task-based time tracking application. - Copyright (C) 2009-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2009-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/UndoCharmCommandWrapper.cpp b/Charm/UndoCharmCommandWrapper.cpp index 0259bc55..4f2f4fe8 100644 --- a/Charm/UndoCharmCommandWrapper.cpp +++ b/Charm/UndoCharmCommandWrapper.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2012-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2012-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Nicholas Van Sickle diff --git a/Charm/UndoCharmCommandWrapper.h b/Charm/UndoCharmCommandWrapper.h index 840cfb87..e34c4461 100644 --- a/Charm/UndoCharmCommandWrapper.h +++ b/Charm/UndoCharmCommandWrapper.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2012-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2012-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Nicholas Van Sickle diff --git a/Charm/ViewFilter.cpp b/Charm/ViewFilter.cpp index df22604c..f4f36bfc 100644 --- a/Charm/ViewFilter.cpp +++ b/Charm/ViewFilter.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld @@ -38,10 +38,10 @@ ViewFilter::ViewFilter(CharmDataModel *model, QObject *parent) setFilterCaseSensitivity(Qt::CaseInsensitive); // relay signals to the view: - connect(&m_model, SIGNAL(eventActivationNotice(EventId)), - SIGNAL(eventActivationNotice(EventId))); - connect(&m_model, SIGNAL(eventDeactivationNotice(EventId)), - SIGNAL(eventDeactivationNotice(EventId))); + connect(&m_model, &TaskModelAdapter::eventActivationNotice, + this, &ViewFilter::eventActivationNotice); + connect(&m_model, &TaskModelAdapter::eventDeactivationNotice, + this, &ViewFilter::eventDeactivationNotice); sort(Column_TaskId); } diff --git a/Charm/ViewFilter.h b/Charm/ViewFilter.h index d15ada09..e68a6e2a 100644 --- a/Charm/ViewFilter.h +++ b/Charm/ViewFilter.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Charm/ViewHelpers.cpp b/Charm/ViewHelpers.cpp index 66c17eeb..64632e17 100644 --- a/Charm/ViewHelpers.cpp +++ b/Charm/ViewHelpers.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Charm/ViewHelpers.h b/Charm/ViewHelpers.h index dc7c693e..a80b6412 100644 --- a/Charm/ViewHelpers.h +++ b/Charm/ViewHelpers.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Charm/WeeklySummary.cpp b/Charm/WeeklySummary.cpp index 00418cd1..9f26a792 100644 --- a/Charm/WeeklySummary.cpp +++ b/Charm/WeeklySummary.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/WeeklySummary.h b/Charm/WeeklySummary.h index 035ece14..182ab001 100644 --- a/Charm/WeeklySummary.h +++ b/Charm/WeeklySummary.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/Widgets/ActivityReport.cpp b/Charm/Widgets/ActivityReport.cpp index 4fbd4b63..408246f3 100644 --- a/Charm/Widgets/ActivityReport.cpp +++ b/Charm/Widgets/ActivityReport.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -53,22 +53,24 @@ ActivityReportConfigurationDialog::ActivityReportConfigurationDialog(QWidget *pa m_ui->dateEditStart->calendarWidget()->setFirstDayOfWeek(Qt::Monday); m_ui->dateEditStart->calendarWidget()->setVerticalHeaderFormat(QCalendarWidget::ISOWeekNumbers); m_ui->tabWidget->setCurrentIndex(0); - connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept())); - connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject())); - connect(m_ui->comboBox, SIGNAL(currentIndexChanged(int)), - SLOT(slotTimeSpanSelected(int))); - connect(m_ui->addExcludeTaskButton, SIGNAL(clicked()), - SLOT(slotExcludeTask())); - connect(m_ui->removeExcludeTaskButton, SIGNAL(clicked()), - SLOT(slotRemoveExcludedTask())); - connect(m_ui->addIncludeTaskButton, SIGNAL(clicked()), - SLOT(slotSelectTask())); - connect(m_ui->removeIncludeTaskButton, SIGNAL(clicked()), - SLOT(slotRemoveIncludeTask())); - connect(m_ui->checkBoxGroupTasks, SIGNAL(clicked(bool)), - SLOT(slotGroupTasks(bool))); - connect(m_ui->checkBoxGroupTasksComments, SIGNAL(clicked(bool)), - SLOT(slotGroupTasksComments(bool))); + connect(m_ui->buttonBox, &QDialogButtonBox::accepted, + this, &ActivityReportConfigurationDialog::accept); + connect(m_ui->buttonBox, &QDialogButtonBox::rejected, + this, &ActivityReportConfigurationDialog::reject); + connect(m_ui->comboBox, static_cast(&QComboBox::currentIndexChanged), + this, &ActivityReportConfigurationDialog::slotTimeSpanSelected ); + connect(m_ui->addExcludeTaskButton, &QToolButton::clicked, + this, &ActivityReportConfigurationDialog::slotExcludeTask); + connect(m_ui->removeExcludeTaskButton, &QToolButton::clicked, + this, &ActivityReportConfigurationDialog::slotRemoveExcludedTask); + connect(m_ui->addIncludeTaskButton, &QToolButton::clicked, + this, &ActivityReportConfigurationDialog::slotSelectTask); + connect(m_ui->removeIncludeTaskButton, &QToolButton::clicked, + this, &ActivityReportConfigurationDialog::slotRemoveIncludeTask); + connect(m_ui->checkBoxGroupTasks, &QCheckBox::clicked, + this, &ActivityReportConfigurationDialog::slotGroupTasks); + connect(m_ui->checkBoxGroupTasksComments, &QCheckBox::clicked, + this, &ActivityReportConfigurationDialog::slotGroupTasksComments); new DateEntrySyncer(m_ui->spinBoxStartWeek, m_ui->spinBoxStartYear, m_ui->dateEditStart, 1, this); @@ -85,8 +87,9 @@ void ActivityReportConfigurationDialog::slotDelayedInitialization() { slotStandardTimeSpansChanged(); connect(ApplicationCore::instance().dateChangeWatcher(), - SIGNAL(dateChanged()), - SLOT(slotStandardTimeSpansChanged())); + &DateChangeWatcher::dateChanged, + this, + &ActivityReportConfigurationDialog::slotStandardTimeSpansChanged); // FIXME load settings } @@ -203,6 +206,11 @@ void ActivityReportConfigurationDialog::accept() QDialog::accept(); } +void ActivityReportConfigurationDialog::reject() +{ + QDialog::reject(); +} + void ActivityReportConfigurationDialog::showReportPreviewDialog() { const int index = m_ui->comboBox->currentIndex(); @@ -229,7 +237,8 @@ ActivityReport::ActivityReport(QWidget *parent) saveToXmlButton()->hide(); saveToTextButton()->hide(); uploadButton()->hide(); - connect(this, SIGNAL(anchorClicked(QUrl)), SLOT(slotLinkClicked(QUrl))); + connect(this, &ReportPreviewWindow::anchorClicked, + this, &ActivityReport::slotLinkClicked); } ActivityReport::~ActivityReport() @@ -486,48 +495,29 @@ void ActivityReport::slotUpdate() void ActivityReport::slotLinkClicked(const QUrl &which) { + const int direction = which.toString() == QLatin1String("Previous") ? -1 : 1; switch (m_properties.timeSpanSelection.timeSpanType) { case Day: - m_properties.start = which.toString() - == QLatin1String("Previous") ? m_properties.start.addDays(-1) - : m_properties.start.addDays(1); - m_properties.end = which.toString() == QLatin1String("Previous") ? m_properties.end.addDays( - -1) : m_properties.end.addDays(1); + m_properties.start = m_properties.start.addDays(1 * direction); + m_properties.end = m_properties.end.addDays(1 * direction); break; case Week: - m_properties.start = which.toString() - == QLatin1String("Previous") ? m_properties.start.addDays(-7) - : m_properties.start.addDays(7); - m_properties.end = which.toString() == QLatin1String("Previous") ? m_properties.end.addDays( - -7) : m_properties.end.addDays(7); + m_properties.start = m_properties.start.addDays(7 * direction); + m_properties.end = m_properties.end.addDays(7 * direction); break; case Month: - m_properties.start = which.toString() - == QLatin1String("Previous") ? m_properties.start.addMonths(-1) - : m_properties.start. - addMonths(1); - m_properties.end = which.toString() - == QLatin1String("Previous") ? m_properties.end.addMonths(-1) - : m_properties.end.addMonths(1); + m_properties.start = m_properties.start.addMonths(1 * direction); + m_properties.end = m_properties.end.addMonths(1 * direction); break; case Year: - m_properties.start = which.toString() - == QLatin1String("Previous") ? m_properties.start.addYears(-1) - : m_properties.start.addYears( - 1); - m_properties.end = which.toString() - == QLatin1String("Previous") ? m_properties.end.addYears(-1) - : m_properties.end.addYears(1); + m_properties.start = m_properties.start.addYears(1 * direction); + m_properties.end = m_properties.end.addYears(1 * direction); break; case Range: { - int spanRange = m_properties.start.daysTo(m_properties.end); - m_properties.start = which.toString() - == QLatin1String("Previous") ? m_properties.start.addDays(-spanRange) - : m_properties. - start.addDays(spanRange); - m_properties.end = which.toString() == QLatin1String("Previous") ? m_properties.end.addDays( - -spanRange) : m_properties.end.addDays(spanRange); + const int spanRange = m_properties.start.daysTo(m_properties.end); + m_properties.start = m_properties.start.addDays(spanRange * direction); + m_properties.end = m_properties.end.addDays(spanRange * direction); break; } default: diff --git a/Charm/Widgets/ActivityReport.h b/Charm/Widgets/ActivityReport.h index e3971347..995f5f1e 100644 --- a/Charm/Widgets/ActivityReport.h +++ b/Charm/Widgets/ActivityReport.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -64,6 +64,7 @@ class ActivityReportConfigurationDialog : public ReportConfigurationDialog public Q_SLOTS: void accept() override; + void reject() override; private Q_SLOTS: void slotDelayedInitialization(); diff --git a/Charm/Widgets/BillDialog.cpp b/Charm/Widgets/BillDialog.cpp index f39e63cd..ea568be2 100644 --- a/Charm/Widgets/BillDialog.cpp +++ b/Charm/Widgets/BillDialog.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -41,11 +41,11 @@ BillDialog::BillDialog(QWidget *parent, Qt::WindowFlags f) setWindowTitle(QStringLiteral("Yeah... about those timesheets...")); m_asYouWish = new QPushButton(QStringLiteral("As you wish")); - connect(m_asYouWish, SIGNAL(clicked()), SLOT(slotAsYouWish())); + connect(m_asYouWish, &QPushButton::clicked, this, &BillDialog::slotAsYouWish); m_alreadyDone = new QPushButton(QStringLiteral("Already done")); - connect(m_alreadyDone, SIGNAL(clicked()), SLOT(slotAlreadyDone())); + connect(m_alreadyDone, &QPushButton::clicked, this, &BillDialog::slotAlreadyDone); m_later = new QPushButton(QStringLiteral("Later")); - connect(m_later, SIGNAL(clicked()), SLOT(slotLater())); + connect(m_later, &QPushButton::clicked, this, &BillDialog::slotLater); auto layout = new QVBoxLayout(this); auto buttonBox = new QDialogButtonBox(); diff --git a/Charm/Widgets/BillDialog.h b/Charm/Widgets/BillDialog.h index 2bd96a61..f70fcd96 100644 --- a/Charm/Widgets/BillDialog.h +++ b/Charm/Widgets/BillDialog.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/Widgets/CharmAboutDialog.cpp b/Charm/Widgets/CharmAboutDialog.cpp index 8f4e1083..66839cc9 100644 --- a/Charm/Widgets/CharmAboutDialog.cpp +++ b/Charm/Widgets/CharmAboutDialog.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -32,7 +32,7 @@ CharmAboutDialog::CharmAboutDialog(QWidget *parent) { m_ui->setupUi(this); QString versionText = m_ui->versionLabel->text(); - versionText.replace(QLatin1String("CHARM_VERSION"), QStringLiteral(CHARM_VERSION)); + versionText.replace(QLatin1String("CHARM_VERSION"), CharmVersion()); m_ui->versionLabel->setText(versionText); } diff --git a/Charm/Widgets/CharmAboutDialog.h b/Charm/Widgets/CharmAboutDialog.h index 5539450f..04635321 100644 --- a/Charm/Widgets/CharmAboutDialog.h +++ b/Charm/Widgets/CharmAboutDialog.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/Widgets/CharmAboutDialog.ui b/Charm/Widgets/CharmAboutDialog.ui index d1328a06..d4b34638 100644 --- a/Charm/Widgets/CharmAboutDialog.ui +++ b/Charm/Widgets/CharmAboutDialog.ui @@ -78,7 +78,7 @@ <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'.Lucida Grande UI'; font-size:13pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Copyright © 2006-2017 The Charm Authors</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Copyright © 2006-2018 The Charm Authors</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-size:9pt;">Licensed under the terms of the GPL.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande'; font-size:9pt;">Charm is supported and maintained by </span><a href="http://www.kdab.com"><span style=" font-family:'Sans Serif'; font-size:9pt; text-decoration: underline; color:#0057ae;">KDAB</span></a></p> diff --git a/Charm/Widgets/CharmNewReleaseDialog.cpp b/Charm/Widgets/CharmNewReleaseDialog.cpp index b122ad5b..c754d867 100644 --- a/Charm/Widgets/CharmNewReleaseDialog.cpp +++ b/Charm/Widgets/CharmNewReleaseDialog.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2015-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2015-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Michel Boyer de la Giroday @@ -35,11 +35,11 @@ CharmNewReleaseDialog::CharmNewReleaseDialog(QWidget *parent) { m_ui->setupUi(this); m_skipUpdate = new QPushButton(tr("Skip Update")); - connect(m_skipUpdate, SIGNAL(clicked()), SLOT(slotSkipVersion())); + connect(m_skipUpdate, &QPushButton::clicked, this, &CharmNewReleaseDialog::slotSkipVersion); m_remindMeLater = new QPushButton(tr("Remind Me Later")); - connect(m_remindMeLater, SIGNAL(clicked()), SLOT(slotRemindMe())); + connect(m_remindMeLater, &QPushButton::clicked, this, &CharmNewReleaseDialog::slotRemindMe); m_update = new QPushButton(tr("Update")); - connect(m_update, SIGNAL(clicked()), SLOT(slotLaunchBrowser())); + connect(m_update, &QPushButton::clicked, this, &CharmNewReleaseDialog::slotLaunchBrowser); m_ui->buttonBox->addButton(m_skipUpdate, QDialogButtonBox::NoRole); m_ui->buttonBox->addButton(m_remindMeLater, QDialogButtonBox::RejectRole); diff --git a/Charm/Widgets/CharmNewReleaseDialog.h b/Charm/Widgets/CharmNewReleaseDialog.h index bc8140b1..80d8aff2 100644 --- a/Charm/Widgets/CharmNewReleaseDialog.h +++ b/Charm/Widgets/CharmNewReleaseDialog.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2015-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2015-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Michel Boyer de la Giroday diff --git a/Charm/Widgets/CharmPreferences.cpp b/Charm/Widgets/CharmPreferences.cpp index 08331a87..ef30c997 100644 --- a/Charm/Widgets/CharmPreferences.cpp +++ b/Charm/Widgets/CharmPreferences.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld Author: Mathias Hasselmann @@ -28,7 +28,7 @@ #include "Core/Configuration.h" #include "Idle/IdleDetector.h" -#include "HttpClient/HttpJob.h" +#include "Lotsofcake/Configuration.h" #include #include @@ -41,26 +41,23 @@ CharmPreferences::CharmPreferences(const Configuration &config, QWidget *parent_ m_ui.setupUi(this); const bool haveIdleDetection = ApplicationCore::instance().idleDetector()->available(); const bool haveCommandInterface = (ApplicationCore::instance().commandInterface() != nullptr); - const bool httpJobPossible = HttpJob::credentialsAvailable(); + const bool httpJobPossible = Lotsofcake::Configuration().isConfigured(); m_ui.lbWarnUnuploadedTimesheets->setVisible(httpJobPossible); m_ui.cbWarnUnuploadedTimesheets->setVisible(httpJobPossible); - m_ui.lbResetPassword->setVisible(httpJobPossible); - m_ui.pbResetPassword->setVisible(httpJobPossible); m_ui.cbIdleDetection->setEnabled(haveIdleDetection); m_ui.lbIdleDetection->setEnabled(haveIdleDetection); m_ui.cbIdleDetection->setChecked(config.detectIdling && m_ui.cbIdleDetection->isEnabled()); m_ui.cbWarnUnuploadedTimesheets->setChecked(config.warnUnuploadedTimesheets); m_ui.cbRequestEventComment->setChecked(config.requestEventComment); - m_ui.lbCommandInterface->setEnabled(haveCommandInterface); + m_ui.lbCommandInterface->setVisible(haveCommandInterface); m_ui.cbEnableCommandInterface->setEnabled(haveCommandInterface); + m_ui.cbEnableCommandInterface->setVisible(haveCommandInterface); m_ui.cbEnableCommandInterface->setChecked(haveCommandInterface && config.enableCommandInterface); - connect(m_ui.cbWarnUnuploadedTimesheets, SIGNAL(toggled(bool)), - SLOT(slotWarnUnuploadedChanged(bool))); - connect(m_ui.pbResetPassword, SIGNAL(clicked()), - SLOT(slotResetPassword())); + connect(m_ui.cbWarnUnuploadedTimesheets, &QCheckBox::toggled, + this, &CharmPreferences::slotWarnUnuploadedChanged); // this would not need a switch, but i hate casting enums to int: switch (config.timeTrackerFontSize) { @@ -101,6 +98,9 @@ CharmPreferences::CharmPreferences(const Configuration &config, QWidget *parent_ m_ui.cbToolButtonStyle->setCurrentIndex(4); break; } + + m_ui.sbNumberOfTaskSelectorEntries->setValue(config.numberOfTaskSelectorEntries); + // resize( minimumSize() ); } @@ -128,6 +128,11 @@ bool CharmPreferences::enableCommandInterface() const return m_ui.cbEnableCommandInterface->isChecked(); } +int CharmPreferences::numberOfTaskSelectorEntries() const +{ + return m_ui.sbNumberOfTaskSelectorEntries->value(); +} + Configuration::DurationFormat CharmPreferences::durationFormat() const { switch (m_ui.cbDurationFormat->currentIndex()) { @@ -187,7 +192,7 @@ Qt::ToolButtonStyle CharmPreferences::toolButtonStyle() const void CharmPreferences::slotWarnUnuploadedChanged(bool enabled) { - if (!HttpJob::credentialsAvailable()) + if (!Lotsofcake::Configuration().isConfigured()) return; if (!enabled) { @@ -202,18 +207,3 @@ void CharmPreferences::slotWarnUnuploadedChanged(bool enabled) m_ui.cbWarnUnuploadedTimesheets->setCheckState(Qt::Checked); } } - -void CharmPreferences::slotResetPassword() -{ - HttpJob *job = new HttpJob(this); - bool ok; - QPointer that(this); //guard against destruction while dialog is open - const QString newpass - = QInputDialog::getText(this, tr("Password"), tr( - "Please enter your lotsofcake password"), QLineEdit::Password, - QLatin1String(""), &ok); - if (!that) - return; - if (ok) - job->provideRequestedPassword(newpass); -} diff --git a/Charm/Widgets/CharmPreferences.h b/Charm/Widgets/CharmPreferences.h index 515f0cc6..f4746ea4 100644 --- a/Charm/Widgets/CharmPreferences.h +++ b/Charm/Widgets/CharmPreferences.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -42,13 +42,13 @@ class CharmPreferences : public QDialog bool warnUnuploadedTimesheets() const; bool requestEventComment() const; bool enableCommandInterface() const; + int numberOfTaskSelectorEntries() const; Qt::ToolButtonStyle toolButtonStyle() const; Configuration::TimeTrackerFontSize timeTrackerFontSize() const; private Q_SLOTS: void slotWarnUnuploadedChanged(bool); - void slotResetPassword(); private: Ui::CharmPreferences m_ui; diff --git a/Charm/Widgets/CharmPreferences.ui b/Charm/Widgets/CharmPreferences.ui index 1cc5081c..26c2162b 100644 --- a/Charm/Widgets/CharmPreferences.ui +++ b/Charm/Widgets/CharmPreferences.ui @@ -6,8 +6,8 @@ 0 0 - 382 - 254 + 505 + 311 @@ -16,43 +16,47 @@ - - - - - 0 - 0 - - + + - Duration format (requires restart) - - - false + - - cbDurationFormat + + true - - - - - 0 - 0 - - - - Buttons show - - - cbToolButtonStyle - + + + + + Icons + + + + + Text + + + + + Text under icon + + + + + Text beside icon + + + + + System default + + - - + + 0 @@ -60,10 +64,10 @@ - Time tracker window font size + Enable Bill Lumbergh - cbTimeTrackerFontSize + cbWarnUnuploadedTimesheets @@ -91,58 +95,6 @@ - - - - - 0 - 0 - - - - Enable Bill Lumbergh - - - cbWarnUnuploadedTimesheets - - - - - - - Reset password - - - - - - - - Icons - - - - - Text - - - - - Text under icon - - - - - Text beside icon - - - - - System default - - - - @@ -153,8 +105,8 @@ - - + + @@ -163,8 +115,8 @@ - - + + 0 @@ -172,15 +124,15 @@ - Comment finished events + Time tracker window font size - cbRequestEventComment + cbTimeTrackerFontSize - - + + 0 @@ -188,15 +140,18 @@ - Enable idle detection + Enable command interface + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - cbIdleDetection + cbEnableCommandInterface - - + + 0 @@ -204,33 +159,29 @@ - Enable command interface + Duration format (requires restart) - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + false - cbEnableCommandInterface + cbDurationFormat - - - - - - - true + + + + + 0 + 0 + - - - - - Reset password + Enable idle detection - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + cbIdleDetection @@ -253,6 +204,61 @@ + + + + + 0 + 0 + + + + Comment finished events + + + cbRequestEventComment + + + + + + + + 0 + 0 + + + + Buttons show + + + cbToolButtonStyle + + + + + + + + 0 + 0 + + + + Limit recently used tasks to + + + sbNumberOfTaskSelectorEntries + + + + + + + 5 + + + diff --git a/Charm/Widgets/CharmWindow.cpp b/Charm/Widgets/CharmWindow.cpp index 770cff46..c31373f8 100644 --- a/Charm/Widgets/CharmWindow.cpp +++ b/Charm/Widgets/CharmWindow.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -49,8 +49,7 @@ CharmWindow::CharmWindow(const QString &name, QWidget *parent) setWindowName(name); connect(m_openCharmAction, SIGNAL(triggered(bool)), SLOT(showView())); connect(m_showAction, SIGNAL(triggered(bool)), SLOT(showView())); - connect(this, SIGNAL(visibilityChanged(bool)), SLOT(handleOpenCharm(bool))); - connect(this, SIGNAL(visibilityChanged(bool)), SLOT(handleShow(bool))); + connect(this, &CharmWindow::visibilityChanged, this, &CharmWindow::handleShow); m_toolBar = addToolBar(QStringLiteral("Toolbar")); m_toolBar->setMovable(false); @@ -183,11 +182,6 @@ void CharmWindow::sendCommandRollback(CharmCommand *cmd) emit emitCommandRollback(relay); } -void CharmWindow::handleOpenCharm(bool visible) -{ - m_openCharmAction->setEnabled(!visible); -} - void CharmWindow::handleShow(bool visible) { const QString text = tr("Show %1").arg(m_windowName); @@ -217,6 +211,7 @@ void CharmWindow::keyPressEvent(QKeyEvent *event) void CharmWindow::showView(QWidget *w) { w->show(); + w->setWindowState(w->windowState() & ~Qt::WindowMinimized); w->raise(); w->activateWindow(); } @@ -267,11 +262,21 @@ void CharmWindow::restoreGuiState() settings.beginGroup(identifier); WidgetUtils::restoreGeometry(this, MetaKey_MainWindowGeometry); // restore visibility - if (settings.contains(MetaKey_MainWindowVisible)) { - // Time Tracking Window should always be visible - const bool visible - = (identifier == QLatin1String("window_tracking")) ? true : settings.value( - MetaKey_MainWindowVisible).toBool(); - setVisible(visible); + bool visible = true; + if (m_hideAtStartUp) + { + visible = false; + } + else + { + // Time Tracking Window should always be visible, except when Charm is started with --hide-at-start + visible = (identifier == QLatin1String("window_tracking")) ? true : settings.value( + MetaKey_MainWindowVisible).toBool(); } + setVisible(visible); +} + +void CharmWindow::setHideAtStartup(const bool &value) +{ + m_hideAtStartUp = value; } diff --git a/Charm/Widgets/CharmWindow.h b/Charm/Widgets/CharmWindow.h index faa6cf44..b92fc7b0 100644 --- a/Charm/Widgets/CharmWindow.h +++ b/Charm/Widgets/CharmWindow.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -77,6 +77,8 @@ class CharmWindow : public QMainWindow, public UIStateInterface static void showView(QWidget *w); static bool showHideView(QWidget *w); + void setHideAtStartup(const bool &); + Q_SIGNALS: void visibilityChanged(bool); void saveConfiguration(); @@ -91,7 +93,6 @@ public Q_SLOTS: void configurationChanged() override; private Q_SLOTS: - void handleOpenCharm(bool visible); void handleShow(bool visible); private: @@ -103,6 +104,7 @@ private Q_SLOTS: QShortcut *m_shortcut = nullptr; QToolBar *m_toolBar; bool m_isVisibility = false; + bool m_hideAtStartUp = false; }; #endif diff --git a/Charm/Widgets/CommentEditorPopup.cpp b/Charm/Widgets/CommentEditorPopup.cpp index e6dbb2b4..c1829635 100644 --- a/Charm/Widgets/CommentEditorPopup.cpp +++ b/Charm/Widgets/CommentEditorPopup.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2015-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2015-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mathias Hasselmann diff --git a/Charm/Widgets/CommentEditorPopup.h b/Charm/Widgets/CommentEditorPopup.h index cdd7747a..b8435545 100644 --- a/Charm/Widgets/CommentEditorPopup.h +++ b/Charm/Widgets/CommentEditorPopup.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2015-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2015-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mathias Hasselmann diff --git a/Charm/Widgets/ConfigurationDialog.cpp b/Charm/Widgets/ConfigurationDialog.cpp index 35b0f95e..9e36a241 100644 --- a/Charm/Widgets/ConfigurationDialog.cpp +++ b/Charm/Widgets/ConfigurationDialog.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -33,8 +33,8 @@ ConfigurationDialog::ConfigurationDialog(const Configuration &config, QWidget *p m_ui.setupUi(this); m_ui.nameLineEdit->setText(config.user.name()); m_ui.databaseLocation->setText(config.localStorageDatabase); - connect(m_ui.buttonBox, SIGNAL(rejected()), SLOT(reject())); - connect(m_ui.buttonBox, SIGNAL(accepted()), SLOT(accept())); + connect(m_ui.buttonBox, &QDialogButtonBox::rejected, this, &ConfigurationDialog::reject); + connect(m_ui.buttonBox, &QDialogButtonBox::accepted, this, &ConfigurationDialog::accept); #ifdef Q_OS_ANDROID setWindowState(windowState() | Qt::WindowMaximized); #endif @@ -52,7 +52,7 @@ void ConfigurationDialog::on_databaseLocation_textChanged(const QString &) void ConfigurationDialog::accept() { - m_config.installationId = 1; + m_config.installationId = m_config.createInstallationId(); m_config.user.setId(1); m_config.user.setName(m_ui.nameLineEdit->text()); m_config.localStorageType = CHARM_SQLITE_BACKEND_DESCRIPTOR; diff --git a/Charm/Widgets/ConfigurationDialog.h b/Charm/Widgets/ConfigurationDialog.h index b1cd7363..77acc2e2 100644 --- a/Charm/Widgets/ConfigurationDialog.h +++ b/Charm/Widgets/ConfigurationDialog.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/Widgets/DateEntrySyncer.cpp b/Charm/Widgets/DateEntrySyncer.cpp index 75fd5738..db031cff 100644 --- a/Charm/Widgets/DateEntrySyncer.cpp +++ b/Charm/Widgets/DateEntrySyncer.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/Widgets/DateEntrySyncer.h b/Charm/Widgets/DateEntrySyncer.h index 13fa79bb..74d57cf7 100644 --- a/Charm/Widgets/DateEntrySyncer.h +++ b/Charm/Widgets/DateEntrySyncer.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/Widgets/EnterVacationDialog.cpp b/Charm/Widgets/EnterVacationDialog.cpp index c5dd5f6b..628c967d 100644 --- a/Charm/Widgets/EnterVacationDialog.cpp +++ b/Charm/Widgets/EnterVacationDialog.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -98,11 +98,11 @@ EnterVacationDialog::EnterVacationDialog(QWidget *parent) const QDate referenceDate = QDate::currentDate().addDays(7); m_ui->startDate->setDate(Charm::weekDayInWeekOf(Qt::Monday, referenceDate)); m_ui->endDate->setDate(Charm::weekDayInWeekOf(Qt::Friday, referenceDate)); - connect(m_ui->startDate, SIGNAL(dateChanged(QDate)), this, SLOT(updateButtonStates())); - connect(m_ui->endDate, SIGNAL(dateChanged(QDate)), this, SLOT(updateButtonStates())); - connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(okClicked())); - connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject())); - connect(m_ui->selectTaskButton, SIGNAL(clicked()), this, SLOT(selectTask())); + connect(m_ui->startDate, &QDateEdit::dateChanged, this, &EnterVacationDialog::updateButtonStates); + connect(m_ui->endDate, &QDateEdit::dateChanged, this, &EnterVacationDialog::updateButtonStates); + connect(m_ui->buttonBox, &QDialogButtonBox::accepted, this, &EnterVacationDialog::okClicked); + connect(m_ui->buttonBox, &QDialogButtonBox::rejected, this, &EnterVacationDialog::reject); + connect(m_ui->selectTaskButton, &QPushButton::clicked, this, &EnterVacationDialog::selectTask); QSettings settings; settings.beginGroup(QStringLiteral("EnterVacation")); m_ui->hoursSpinBox->setValue(settings.value(QStringLiteral("workHours"), 8).toInt()); @@ -137,8 +137,8 @@ void EnterVacationDialog::createEvents() auto box = new QDialogButtonBox; box->setStandardButtons(QDialogButtonBox::Ok|QDialogButtonBox::Cancel); box->button(QDialogButtonBox::Ok)->setText(tr("Create")); - connect(box, SIGNAL(accepted()), &confirmationDialog, SLOT(accept())); - connect(box, SIGNAL(rejected()), &confirmationDialog, SLOT(reject())); + connect(box, &QDialogButtonBox::accepted, &confirmationDialog, &QDialog::accept); + connect(box, &QDialogButtonBox::rejected, &confirmationDialog, &QDialog::reject); layout->addWidget(box); const QString startDate = m_ui->startDate->date().toString(Qt::TextDate); diff --git a/Charm/Widgets/EnterVacationDialog.h b/Charm/Widgets/EnterVacationDialog.h index ee3a6d98..1a732c9b 100644 --- a/Charm/Widgets/EnterVacationDialog.h +++ b/Charm/Widgets/EnterVacationDialog.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/Widgets/EventEditor.cpp b/Charm/Widgets/EventEditor.cpp index faa791e6..2bcfb409 100644 --- a/Charm/Widgets/EventEditor.cpp +++ b/Charm/Widgets/EventEditor.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld @@ -55,22 +55,23 @@ EventEditor::EventEditor(const Event &event, QWidget *parent) SLOT(durationHoursEdited(int))); connect(m_ui->spinBoxMinutes, SIGNAL(valueChanged(int)), SLOT(durationMinutesEdited(int))); - connect(m_ui->dateEditStart, SIGNAL(dateChanged(QDate)), - SLOT(startDateChanged(QDate))); - connect(m_ui->timeEditStart, SIGNAL(timeChanged(QTime)), - SLOT(startTimeChanged(QTime))); - connect(m_ui->dateEditEnd, SIGNAL(dateChanged(QDate)), - SLOT(endDateChanged(QDate))); - connect(m_ui->timeEditEnd, SIGNAL(timeChanged(QTime)), - SLOT(endTimeChanged(QTime))); - connect(m_ui->pushButtonSelectTask, SIGNAL(clicked()), - SLOT(selectTaskClicked())); - connect(m_ui->textEditComment, SIGNAL(textChanged()), - SLOT(commentChanged())); - connect(m_ui->startToNowButton, SIGNAL(clicked()), - SLOT(startToNowButtonClicked())); - connect(m_ui->endToNowButton, SIGNAL(clicked()), - SLOT(endToNowButtonClicked())); + connect(m_ui->dateEditStart, &QDateEdit::dateChanged, + this, &EventEditor::startDateChanged); + connect(m_ui->timeEditStart, &QTimeEdit::timeChanged, + this, &EventEditor::startTimeChanged); + connect(m_ui->dateEditEnd, &QDateEdit::dateChanged, + this, &EventEditor::endDateChanged); + connect(m_ui->timeEditEnd, &QTimeEdit::timeChanged, + this, &EventEditor::endTimeChanged); + connect(m_ui->pushButtonSelectTask, &QPushButton::clicked, + this, &EventEditor::selectTaskClicked); + connect(m_ui->textEditComment, &QTextEdit::textChanged, + this, &EventEditor::commentChanged); + connect(m_ui->startToNowButton, &QPushButton::clicked, + this, &EventEditor::startToNowButtonClicked); + connect(m_ui->endToNowButton, &QPushButton::clicked, + this, &EventEditor::endToNowButtonClicked); + // what a fricking hack - but QDateTimeEdit does not seem to have // a simple function to toggle 12h and 24h mode: // yeah, I know, this will survive changes in the user prefs, but diff --git a/Charm/Widgets/EventEditor.h b/Charm/Widgets/EventEditor.h index 4fd67dde..bee8d90b 100644 --- a/Charm/Widgets/EventEditor.h +++ b/Charm/Widgets/EventEditor.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Charm/Widgets/EventEditorDelegate.cpp b/Charm/Widgets/EventEditorDelegate.cpp index fc7feecf..203da823 100644 --- a/Charm/Widgets/EventEditorDelegate.cpp +++ b/Charm/Widgets/EventEditorDelegate.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/Widgets/EventEditorDelegate.h b/Charm/Widgets/EventEditorDelegate.h index a42c26a4..4f370794 100644 --- a/Charm/Widgets/EventEditorDelegate.h +++ b/Charm/Widgets/EventEditorDelegate.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/Widgets/EventView.cpp b/Charm/Widgets/EventView.cpp index 1e562aed..c4260271 100644 --- a/Charm/Widgets/EventView.cpp +++ b/Charm/Widgets/EventView.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -78,18 +78,16 @@ EventView::EventView(QWidget *parent) m_listView->setAlternatingRowColors(true); m_listView->setContextMenuPolicy(Qt::CustomContextMenu); - connect(m_listView, - SIGNAL(customContextMenuRequested(QPoint)), - SLOT(slotContextMenuRequested(QPoint))); - connect(m_listView, - SIGNAL(doubleClicked(QModelIndex)), - SLOT(slotEventDoubleClicked(QModelIndex))); - connect(&m_actionNewEvent, SIGNAL(triggered()), - SLOT(slotNewEvent())); + connect(m_listView, &QListView::customContextMenuRequested, + this, &EventView::slotContextMenuRequested); + connect(m_listView, &QListView::doubleClicked, + this, &EventView::slotEventDoubleClicked); + connect(&m_actionNewEvent, &QAction::triggered, + this, &EventView::slotNewEvent); connect(&m_actionEditEvent, SIGNAL(triggered()), SLOT(slotEditEvent())); - connect(&m_actionDeleteEvent, SIGNAL(triggered()), - SLOT(slotDeleteEvent())); + connect(&m_actionDeleteEvent, &QAction::triggered, + this, &EventView::slotDeleteEvent); // connect( &m_commitTimer, SIGNAL(timeout()), // SLOT(slotCommitTimeout()) ); // m_commitTimer.setSingleShot( true ); @@ -105,15 +103,15 @@ EventView::EventView(QWidget *parent) m_actionRedo.setEnabled(false); m_undoStack = new QUndoStack(this); - connect(m_undoStack, SIGNAL(canUndoChanged(bool)), &m_actionUndo, SLOT(setEnabled(bool))); - connect(m_undoStack, SIGNAL(undoTextChanged(QString)), this, - SLOT(slotUndoTextChanged(QString))); - connect(&m_actionUndo, SIGNAL(triggered()), m_undoStack, SLOT(undo())); + connect(m_undoStack, &QUndoStack::canUndoChanged, + &m_actionUndo, &QAction::setEnabled); + connect(m_undoStack, &QUndoStack::undoTextChanged, + this, &EventView::slotUndoTextChanged); + connect(&m_actionUndo, &QAction::triggered, m_undoStack, &QUndoStack::undo); - connect(m_undoStack, SIGNAL(canRedoChanged(bool)), &m_actionRedo, SLOT(setEnabled(bool))); - connect(m_undoStack, SIGNAL(redoTextChanged(QString)), this, - SLOT(slotRedoTextChanged(QString))); - connect(&m_actionRedo, SIGNAL(triggered()), m_undoStack, SLOT(redo())); + connect(m_undoStack, &QUndoStack::canRedoChanged, &m_actionRedo, &QAction::setEnabled); + connect(m_undoStack, &QUndoStack::redoTextChanged, this, &EventView::slotRedoTextChanged); + connect(&m_actionRedo, &QAction::triggered, m_undoStack, &QUndoStack::redo); m_actionNewEvent.setText(tr("New Event...")); m_actionNewEvent.setToolTip(tr("Create a new Event")); @@ -131,7 +129,7 @@ EventView::EventView(QWidget *parent) m_actionFindAndReplace.setIcon(Data::searchIcon()); m_toolBar->addAction(&m_actionFindAndReplace); - connect(&m_actionFindAndReplace, SIGNAL(triggered()), SLOT(slotFindAndReplace())); + connect(&m_actionFindAndReplace, &QAction::triggered, this, &EventView::slotFindAndReplace); m_actionDeleteEvent.setText(tr("Delete Event...")); QList deleteShortcuts; @@ -169,14 +167,15 @@ EventView::EventView(QWidget *parent) EventView::~EventView() { + // Prevents a crash on exit, with the stack emitting undoTextChanged on destruction + m_undoStack->disconnect(this); } void EventView::delayedInitialization() { timeSpansChanged(); - connect(ApplicationCore::instance().dateChangeWatcher(), - SIGNAL(dateChanged()), - SLOT(timeSpansChanged())); + connect(ApplicationCore::instance().dateChangeWatcher(), &DateChangeWatcher::dateChanged, + this, &EventView::timeSpansChanged); } void EventView::populateEditMenu(QMenu *menu) @@ -242,12 +241,9 @@ void EventView::setCurrentEvent(const Event &event) void EventView::stageCommand(CharmCommand *command) { auto undoCommand = new UndoCharmCommandWrapper(command); - connect(command, SIGNAL(emitExecute(CharmCommand*)), this, - SIGNAL(emitCommand(CharmCommand*))); - connect(command, SIGNAL(emitRollback(CharmCommand*)), this, - SIGNAL(emitCommandRollback(CharmCommand*))); - connect(command, SIGNAL(emitSlotEventIdChanged(int,int)), this, SLOT(slotEventIdChanged(int, - int))); + connect(command, &CharmCommand::emitExecute, this, &EventView::emitCommand); + connect(command, &CharmCommand::emitRollback, this, &EventView::emitCommandRollback); + connect(command, &CharmCommand::emitSlotEventIdChanged, this, &EventView::slotEventIdChanged); m_undoStack->push(undoCommand); } @@ -459,8 +455,8 @@ void EventView::stateChanged(State) switch (ApplicationCore::instance().state()) { case Connecting: setModel(&MODEL); - connect(MODEL.charmDataModel(), SIGNAL(resetGUIState()), - SLOT(restoreGuiState())); + connect(MODEL.charmDataModel(), &CharmDataModel::resetGUIState, + this, &EventView::restoreGuiState); break; case Connected: //the model is populated when entering Connected, so delay state restore @@ -498,29 +494,28 @@ void EventView::setModel(ModelConnector *connector) m_listView->setSelectionBehavior(QAbstractItemView::SelectRows); m_listView->setSelectionMode(QAbstractItemView::SingleSelection); - connect(m_listView->selectionModel(), - SIGNAL(currentChanged(QModelIndex,QModelIndex)), - SLOT(slotCurrentItemChanged(QModelIndex,QModelIndex))); - - connect(model, SIGNAL(eventActivationNotice(EventId)), - SLOT(slotEventActivated(EventId))); - connect(model, SIGNAL(eventDeactivationNotice(EventId)), - SLOT(slotEventDeactivated(EventId))); - - connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), - SLOT(slotUpdateCurrent())); - connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), - SLOT(slotUpdateTotal())); - connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), - SLOT(slotUpdateTotal())); - connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), - SLOT(slotConfigureUi())); - connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), - SLOT(slotConfigureUi())); - connect(model, SIGNAL(layoutChanged()), - SLOT(slotUpdateCurrent())); - connect(model, SIGNAL(modelReset()), - SLOT(slotUpdateTotal())); + connect(m_listView->selectionModel(),&QItemSelectionModel::currentChanged, + this, &EventView::slotCurrentItemChanged); + + connect(model, &EventModelFilter::eventActivationNotice, + this, &EventView::slotEventActivated); + connect(model, &EventModelFilter::eventDeactivationNotice, + this, &EventView::slotEventDeactivated); + + connect(model, &EventModelFilter::dataChanged, + this, &EventView::slotUpdateCurrent); + connect(model, &EventModelFilter::rowsInserted, + this, &EventView::slotUpdateTotal); + connect(model, &EventModelFilter::rowsRemoved, + this, &EventView::slotUpdateTotal); + connect(model, &EventModelFilter::rowsInserted, + this, &EventView::slotConfigureUi); + connect(model, &EventModelFilter::rowsRemoved, + this, &EventView::slotConfigureUi); + connect(model, &EventModelFilter::layoutChanged, + this, &EventView::slotUpdateCurrent); + connect(model, &EventModelFilter::modelReset, + this, &EventView::slotUpdateTotal); m_model = model; // normally, the model is set only once, so this should be no problem: @@ -549,8 +544,8 @@ void EventView::slotEditEvent(const Event &event) if (!newEvent.isValid()) { auto command = new CommandMakeEvent(newEvent, this); - connect(command, SIGNAL(finishedOk(Event)), - this, SLOT(slotEventChangesCompleted(Event)), + connect(command, &CommandMakeEvent::finishedOk, + this, &EventView::slotEventChangesCompleted, Qt::QueuedConnection); stageCommand(command); return; diff --git a/Charm/Widgets/EventView.h b/Charm/Widgets/EventView.h index 99b12fcb..081d0fe0 100644 --- a/Charm/Widgets/EventView.h +++ b/Charm/Widgets/EventView.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/Widgets/ExpandStatesHelper.cpp b/Charm/Widgets/ExpandStatesHelper.cpp index 5fb5f321..b1629cb8 100644 --- a/Charm/Widgets/ExpandStatesHelper.cpp +++ b/Charm/Widgets/ExpandStatesHelper.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/Widgets/ExpandStatesHelper.h b/Charm/Widgets/ExpandStatesHelper.h index 173c3545..865cc493 100644 --- a/Charm/Widgets/ExpandStatesHelper.h +++ b/Charm/Widgets/ExpandStatesHelper.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/Widgets/FindAndReplaceEventsDialog.cpp b/Charm/Widgets/FindAndReplaceEventsDialog.cpp index 4f56b379..3313324d 100644 --- a/Charm/Widgets/FindAndReplaceEventsDialog.cpp +++ b/Charm/Widgets/FindAndReplaceEventsDialog.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2010-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2010-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Michel Boyer de la Giroday @@ -42,9 +42,10 @@ FindAndReplaceEventsDialog::FindAndReplaceEventsDialog(QWidget *parent) m_replace = new QPushButton(tr("Replace")); m_replace->setEnabled(false); - connect(m_replace, SIGNAL(clicked()), SLOT(slotReplaceProjectCode())); + connect(m_replace, &QPushButton::clicked, + this, &FindAndReplaceEventsDialog::slotReplaceProjectCode); m_cancel = new QPushButton(tr("Cancel")); - connect(m_cancel, SIGNAL(clicked()), SLOT(reject())); + connect(m_cancel, &QPushButton::clicked, this, &QDialog::reject); m_ui->buttonBox->addButton(m_cancel, QDialogButtonBox::RejectRole); m_ui->buttonBox->addButton(m_replace, QDialogButtonBox::AcceptRole); @@ -60,16 +61,17 @@ FindAndReplaceEventsDialog::FindAndReplaceEventsDialog(QWidget *parent) // and we add a day when filtering. m_ui->dateEditEnd->setDate(m_timeSpan.second.addDays(-1)); - connect(m_ui->dateEditStart->calendarWidget(), SIGNAL(selectionChanged()), - SLOT(slotTimeSpansChanged())); - connect(m_ui->dateEditEnd->calendarWidget(), SIGNAL(selectionChanged()), - SLOT(slotTimeSpansChanged())); - connect(ApplicationCore::instance().dateChangeWatcher(), - SIGNAL(dateChanged()), - SLOT(slotTimeSpansChanged())); - - connect(m_ui->selectSearchTaskPB, SIGNAL(clicked()), SLOT(slotSelectTaskToSearch())); - connect(m_ui->selectReplaceWithTaskPB, SIGNAL(clicked()), SLOT(slotSelectTaskToReplaceWith())); + connect(m_ui->dateEditStart->calendarWidget(), &QCalendarWidget::selectionChanged, + this, &FindAndReplaceEventsDialog::slotTimeSpansChanged); + connect(m_ui->dateEditEnd->calendarWidget(), &QCalendarWidget::selectionChanged, + this, &FindAndReplaceEventsDialog::slotTimeSpansChanged); + connect(ApplicationCore::instance().dateChangeWatcher(), &DateChangeWatcher::dateChanged, + this, &FindAndReplaceEventsDialog::slotTimeSpansChanged); + + connect(m_ui->selectSearchTaskPB, &QPushButton::clicked, + this, &FindAndReplaceEventsDialog::slotSelectTaskToSearch); + connect(m_ui->selectReplaceWithTaskPB, &QPushButton::clicked, + this, &FindAndReplaceEventsDialog::slotSelectTaskToReplaceWith); m_model.reset(new EventModelFilter(DATAMODEL)); m_ui->findAndReplaceLV->setModel(m_model.data()); diff --git a/Charm/Widgets/FindAndReplaceEventsDialog.h b/Charm/Widgets/FindAndReplaceEventsDialog.h index 600106fe..b76a9f98 100644 --- a/Charm/Widgets/FindAndReplaceEventsDialog.h +++ b/Charm/Widgets/FindAndReplaceEventsDialog.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2010-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2010-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Michel Boyer de la Giroday diff --git a/Charm/Widgets/HttpJobProgressDialog.cpp b/Charm/Widgets/HttpJobProgressDialog.cpp index 0157ba45..0d40c596 100644 --- a/Charm/Widgets/HttpJobProgressDialog.cpp +++ b/Charm/Widgets/HttpJobProgressDialog.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -32,9 +32,9 @@ HttpJobProgressDialog::HttpJobProgressDialog(HttpJob *job, QWidget *parent) setLabelText(tr("Wait...")); Q_ASSERT(job); - connect(job, SIGNAL(finished(HttpJob*)), this, SLOT(jobFinished(HttpJob*))); - connect(job, SIGNAL(transferStarted()), this, SLOT(jobTransferStarted())); - connect(job, SIGNAL(passwordRequested()), this, SLOT(jobPasswordRequested())); + connect(job, &HttpJob::finished, this, &HttpJobProgressDialog::jobFinished); + connect(job, &HttpJob::transferStarted, this, &HttpJobProgressDialog::jobTransferStarted); + connect(job, &HttpJob::passwordRequested, this, &HttpJobProgressDialog::jobPasswordRequested); } void HttpJobProgressDialog::jobTransferStarted() @@ -47,14 +47,15 @@ void HttpJobProgressDialog::jobFinished(HttpJob *) deleteLater(); } -void HttpJobProgressDialog::jobPasswordRequested() +void HttpJobProgressDialog::jobPasswordRequested(HttpJob::PasswordRequestReason reason) { bool ok; QPointer that(this); //guard against destruction while dialog is open - const QString newpass - = QInputDialog::getText(parentWidget(), tr("Password"), tr( - "Please enter your lotsofcake password"), QLineEdit::Password, - m_job->password(), &ok); + + const auto title = reason == HttpJob::PasswordIncorrect ? tr("Authentication Failed") : tr("Password"); + const auto message = reason == HttpJob::PasswordIncorrect ? tr("Please re-enter your lotsofcake password") : tr("Please enter your lotsofcake password"); + const auto newpass = QInputDialog::getText(parentWidget(), title, message, QLineEdit::Password, m_job->password(), &ok); + if (!that) return; if (ok) { diff --git a/Charm/Widgets/HttpJobProgressDialog.h b/Charm/Widgets/HttpJobProgressDialog.h index 9d75cca0..136cfd51 100644 --- a/Charm/Widgets/HttpJobProgressDialog.h +++ b/Charm/Widgets/HttpJobProgressDialog.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -37,7 +37,7 @@ class HttpJobProgressDialog : public QProgressDialog private Q_SLOTS: void jobFinished(HttpJob *); void jobTransferStarted(); - void jobPasswordRequested(); + void jobPasswordRequested(HttpJob::PasswordRequestReason reason); private: QPointer m_job; diff --git a/Charm/Widgets/IdleCorrectionDialog.cpp b/Charm/Widgets/IdleCorrectionDialog.cpp index 1bdfb7cf..4b9f7da3 100644 --- a/Charm/Widgets/IdleCorrectionDialog.cpp +++ b/Charm/Widgets/IdleCorrectionDialog.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -55,6 +55,8 @@ IdleCorrectionDialog::Result IdleCorrectionDialog::result() const return Idle_Ignore; } else if (m_ui->endEvent->isChecked()) { return Idle_EndEvent; + } else if (m_ui->restartEvent->isChecked()) { + return Idle_RestartEvent; } else { Q_ASSERT(false); // unhandled whatever? } diff --git a/Charm/Widgets/IdleCorrectionDialog.h b/Charm/Widgets/IdleCorrectionDialog.h index 565cbdde..d8742a22 100644 --- a/Charm/Widgets/IdleCorrectionDialog.h +++ b/Charm/Widgets/IdleCorrectionDialog.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -41,7 +41,8 @@ class IdleCorrectionDialog : public QDialog enum Result { Idle_NoResult, Idle_Ignore, - Idle_EndEvent + Idle_EndEvent, + Idle_RestartEvent }; explicit IdleCorrectionDialog(const IdleDetector::IdlePeriod &idlePeriod, diff --git a/Charm/Widgets/IdleCorrectionDialog.ui b/Charm/Widgets/IdleCorrectionDialog.ui index 8909183a..177e7dfa 100644 --- a/Charm/Widgets/IdleCorrectionDialog.ui +++ b/Charm/Widgets/IdleCorrectionDialog.ui @@ -41,6 +41,13 @@ + + + + End event(s) at idle time and restart it from now on + + + diff --git a/Charm/Widgets/MakeTemporarilyVisible.h b/Charm/Widgets/MakeTemporarilyVisible.h index c0e0ffb7..efdc359e 100644 --- a/Charm/Widgets/MakeTemporarilyVisible.h +++ b/Charm/Widgets/MakeTemporarilyVisible.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/Widgets/MessageBox.cpp b/Charm/Widgets/MessageBox.cpp index ea0c997c..af43bf18 100644 --- a/Charm/Widgets/MessageBox.cpp +++ b/Charm/Widgets/MessageBox.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/Widgets/MessageBox.h b/Charm/Widgets/MessageBox.h index e581cfa5..89ccc429 100644 --- a/Charm/Widgets/MessageBox.h +++ b/Charm/Widgets/MessageBox.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/Widgets/MonthlyTimesheet.cpp b/Charm/Widgets/MonthlyTimesheet.cpp index 48708714..83fff9d8 100644 --- a/Charm/Widgets/MonthlyTimesheet.cpp +++ b/Charm/Widgets/MonthlyTimesheet.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -55,7 +55,8 @@ MonthlyTimeSheetReport::MonthlyTimeSheetReport(QWidget *parent) m_dailyhours = 8; } - connect(this, SIGNAL(anchorClicked(QUrl)), SLOT(slotLinkClicked(QUrl))); + connect(this, &MonthlyTimeSheetReport::anchorClicked, + this, &MonthlyTimeSheetReport::slotLinkClicked); } MonthlyTimeSheetReport::~MonthlyTimeSheetReport() @@ -110,7 +111,7 @@ QByteArray MonthlyTimeSheetReport::saveToText() return output; } -QByteArray MonthlyTimeSheetReport::saveToXml() +QByteArray MonthlyTimeSheetReport::saveToXml(SaveToXmlMode mode) { try { MonthlyTimesheetXmlWriter timesheet; @@ -119,6 +120,7 @@ QByteArray MonthlyTimeSheetReport::saveToXml() timesheet.setYearOfMonth(m_yearOfMonth); timesheet.setNumberOfWeeks(m_numberOfWeeks); timesheet.setRootTask(rootTask()); + timesheet.setIncludeTaskList(mode == IncludeTaskList); const EventIdList matchingEventIds = DATAMODEL->eventsThatStartInTimeFrame( startDate(), endDate()); EventList events; diff --git a/Charm/Widgets/MonthlyTimesheet.h b/Charm/Widgets/MonthlyTimesheet.h index 1e035a67..1b2cf011 100644 --- a/Charm/Widgets/MonthlyTimesheet.h +++ b/Charm/Widgets/MonthlyTimesheet.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -48,7 +48,7 @@ private Q_SLOTS: QString suggestedFileName() const override; void update() override; QByteArray saveToText() override; - QByteArray saveToXml() override; + QByteArray saveToXml(SaveToXmlMode mode) override; private: // properties of the report: diff --git a/Charm/Widgets/MonthlyTimesheetConfigurationDialog.cpp b/Charm/Widgets/MonthlyTimesheetConfigurationDialog.cpp index 5dba3d63..c5b8f7dd 100644 --- a/Charm/Widgets/MonthlyTimesheetConfigurationDialog.cpp +++ b/Charm/Widgets/MonthlyTimesheetConfigurationDialog.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -42,22 +42,23 @@ MonthlyTimesheetConfigurationDialog::MonthlyTimesheetConfigurationDialog(QWidget setWindowTitle(tr("Monthly Timesheet")); m_ui->setupUi(this); - connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept())); - connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + connect(m_ui->buttonBox, &QDialogButtonBox::accepted, + this, &MonthlyTimesheetConfigurationDialog::accept); + connect(m_ui->buttonBox, &QDialogButtonBox::rejected, + this, &MonthlyTimesheetConfigurationDialog::reject); connect(m_ui->comboBoxMonth, SIGNAL(currentIndexChanged(int)), SLOT(slotMonthComboItemSelected(int))); - connect(m_ui->toolButtonSelectTask, SIGNAL(clicked()), - SLOT(slotSelectTask())); - connect(m_ui->checkBoxSubTasksOnly, SIGNAL(toggled(bool)), - SLOT(slotCheckboxSubtasksOnlyChecked(bool))); + connect(m_ui->toolButtonSelectTask, &QToolButton::clicked, + this, &MonthlyTimesheetConfigurationDialog::slotSelectTask); + connect(m_ui->checkBoxSubTasksOnly, &QCheckBox::toggled, + this, &MonthlyTimesheetConfigurationDialog::slotCheckboxSubtasksOnlyChecked); m_ui->comboBoxMonth->setCurrentIndex(1); slotCheckboxSubtasksOnlyChecked(m_ui->checkBoxSubTasksOnly->isChecked()); slotStandardTimeSpansChanged(); - connect(ApplicationCore::instance().dateChangeWatcher(), - SIGNAL(dateChanged()), - SLOT(slotStandardTimeSpansChanged())); + connect(ApplicationCore::instance().dateChangeWatcher(), &DateChangeWatcher::dateChanged, + this, &MonthlyTimesheetConfigurationDialog::slotStandardTimeSpansChanged); // set current month and year: m_ui->spinBoxMonth->setValue(QDate::currentDate().month()); diff --git a/Charm/Widgets/MonthlyTimesheetConfigurationDialog.h b/Charm/Widgets/MonthlyTimesheetConfigurationDialog.h index 94a7808f..f9a889b8 100644 --- a/Charm/Widgets/MonthlyTimesheetConfigurationDialog.h +++ b/Charm/Widgets/MonthlyTimesheetConfigurationDialog.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/Widgets/NotificationPopup.cpp b/Charm/Widgets/NotificationPopup.cpp index 6511e664..622397bd 100644 --- a/Charm/Widgets/NotificationPopup.cpp +++ b/Charm/Widgets/NotificationPopup.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2015-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2015-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Michel Boyer de la Giroday @@ -27,6 +27,7 @@ #include #include #include +#include NotificationPopup::NotificationPopup(QWidget *parent) : QDialog(parent) diff --git a/Charm/Widgets/NotificationPopup.h b/Charm/Widgets/NotificationPopup.h index 7a1203bb..d1a942d1 100644 --- a/Charm/Widgets/NotificationPopup.h +++ b/Charm/Widgets/NotificationPopup.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2015-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2015-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Michel Boyer de la Giroday diff --git a/Charm/Widgets/ReportConfigurationDialog.cpp b/Charm/Widgets/ReportConfigurationDialog.cpp index 4c42cf70..b6c1ec81 100644 --- a/Charm/Widgets/ReportConfigurationDialog.cpp +++ b/Charm/Widgets/ReportConfigurationDialog.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/Widgets/ReportConfigurationDialog.h b/Charm/Widgets/ReportConfigurationDialog.h index 2887ae0d..b657ed5a 100644 --- a/Charm/Widgets/ReportConfigurationDialog.h +++ b/Charm/Widgets/ReportConfigurationDialog.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/Widgets/ReportPreviewWindow.cpp b/Charm/Widgets/ReportPreviewWindow.cpp index ff743924..985d6a85 100644 --- a/Charm/Widgets/ReportPreviewWindow.cpp +++ b/Charm/Widgets/ReportPreviewWindow.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -37,27 +37,27 @@ ReportPreviewWindow::ReportPreviewWindow(QWidget *parent) { m_ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose); - connect(m_ui->pushButtonClose, SIGNAL(clicked()), - SLOT(slotClose())); - connect(m_ui->pushButtonUpdate, SIGNAL(clicked()), - SLOT(slotUpdate())); - connect(m_ui->pushButtonSave, SIGNAL(clicked()), - SLOT(slotSaveToXml())); - connect(m_ui->pushButtonSaveTotals, SIGNAL(clicked()), - SLOT(slotSaveToText())); - connect(m_ui->textBrowser, SIGNAL(anchorClicked(QUrl)), - SIGNAL(anchorClicked(QUrl))); + connect(m_ui->pushButtonClose, &QPushButton::clicked, + this, &ReportPreviewWindow::slotClose); + connect(m_ui->pushButtonUpdate, &QPushButton::clicked, + this, &ReportPreviewWindow::slotUpdate); + connect(m_ui->pushButtonSave, &QPushButton::clicked, + this, &ReportPreviewWindow::slotSaveToXml); + connect(m_ui->pushButtonSaveTotals, &QPushButton::clicked, + this, &ReportPreviewWindow::slotSaveToText); + connect(m_ui->textBrowser, &QTextBrowser::anchorClicked, + this, &ReportPreviewWindow::anchorClicked); #ifndef QT_NO_PRINTER - connect(m_ui->pushButtonPrint, SIGNAL(clicked()), - SLOT(slotPrint())); + connect(m_ui->pushButtonPrint, &QPushButton::clicked, + this, &ReportPreviewWindow::slotPrint); #else m_ui->pushButtonPrint->setEnabled(false); #endif m_updateTimer.setInterval(60 * 1000); m_updateTimer.start(); - connect(&m_updateTimer, SIGNAL(timeout()), - SLOT(slotUpdate())); + connect(&m_updateTimer, &QTimer::timeout, + this, &ReportPreviewWindow::slotUpdate); resize(850, 600); } diff --git a/Charm/Widgets/ReportPreviewWindow.h b/Charm/Widgets/ReportPreviewWindow.h index c2a2ed92..881e6ccf 100644 --- a/Charm/Widgets/ReportPreviewWindow.h +++ b/Charm/Widgets/ReportPreviewWindow.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/Widgets/SelectTaskDialog.cpp b/Charm/Widgets/SelectTaskDialog.cpp index f7135d85..491c0e3b 100644 --- a/Charm/Widgets/SelectTaskDialog.cpp +++ b/Charm/Widgets/SelectTaskDialog.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -74,23 +74,23 @@ SelectTaskDialog::SelectTaskDialog(QWidget *parent) m_ui->treeView->header()->hide(); m_ui->buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(true); m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); - connect(m_ui->treeView->selectionModel(), - SIGNAL(currentChanged(QModelIndex,QModelIndex)), - SLOT(slotCurrentItemChanged(QModelIndex,QModelIndex))); - connect(m_ui->treeView, - SIGNAL(doubleClicked(QModelIndex)), - SLOT(slotDoubleClicked(QModelIndex))); - - connect(m_ui->filter, SIGNAL(textChanged(QString)), - SLOT(slotFilterTextChanged(QString))); - connect(m_ui->showExpired, SIGNAL(toggled(bool)), - SLOT(slotPrefilteringChanged())); - connect(m_ui->showSelected, SIGNAL(toggled(bool)), - SLOT(slotPrefilteringChanged())); - connect(this, SIGNAL(accepted()), - SLOT(slotAccepted())); - connect(MODEL.charmDataModel(), SIGNAL(resetGUIState()), - SLOT(slotResetState())); + connect(m_ui->treeView->selectionModel(), &QItemSelectionModel::currentChanged, + this, &SelectTaskDialog::slotCurrentItemChanged); + connect(m_ui->treeView, &QTreeView::doubleClicked, + this, &SelectTaskDialog::slotDoubleClicked); + + connect(m_ui->filter, &QLineEdit::textChanged, + this, &SelectTaskDialog::slotFilterTextChanged); + connect(m_ui->showExpired, &QCheckBox::toggled, + this, &SelectTaskDialog::slotPrefilteringChanged); + connect(m_ui->showSelected, &QCheckBox::toggled, + this, &SelectTaskDialog::slotPrefilteringChanged); + connect(this, &SelectTaskDialog::accepted, + this, &SelectTaskDialog::slotAccepted); + connect(MODEL.charmDataModel(), &CharmDataModel::resetGUIState, + this, &SelectTaskDialog::slotResetState); + connect(m_ui->filter, &QLineEdit::textChanged, + this, &SelectTaskDialog::slotSelectTask); QSettings settings; settings.beginGroup(QString::fromUtf8(staticMetaObject.className())); @@ -144,6 +144,16 @@ TaskId SelectTaskDialog::selectedTask() const return m_selectedTask; } +void SelectTaskDialog::selectTask(TaskId task) +{ + m_selectedTask = task; + QModelIndex index(m_proxy.indexForTaskId(m_selectedTask)); + if (index.isValid()) + m_ui->treeView->setCurrentIndex(index); + else + m_ui->treeView->setCurrentIndex(QModelIndex()); +} + void SelectTaskDialog::slotCurrentItemChanged(const QModelIndex &first, const QModelIndex &) { const Task task = m_proxy.taskForIndex(first); @@ -259,3 +269,17 @@ void SelectTaskDialog::setNonValidSelectable() { m_nonValidSelectable = true; } + +void SelectTaskDialog::slotSelectTask(const QString &filter) +{ + const QString filterText = filter.simplified().toUpper().replace(QLatin1Char('*'), QLatin1Char(' ')); + const int filterTaskId = filterText.toInt(); + const TaskList tasks = MODEL.charmDataModel()->getAllTasks(); + + for (const auto task : tasks) { + if (!task.isValid()) + continue; + if (task.name().toUpper().contains(filterText) || task.id() == filterTaskId) + selectTask(task.id()); + } +} diff --git a/Charm/Widgets/SelectTaskDialog.h b/Charm/Widgets/SelectTaskDialog.h index f5aae3dc..b7e80052 100644 --- a/Charm/Widgets/SelectTaskDialog.h +++ b/Charm/Widgets/SelectTaskDialog.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -62,6 +62,7 @@ class SelectTaskDialog : public QDialog TaskId selectedTask() const; void setNonTrackableSelectable(); void setNonValidSelectable(); + void selectTask(TaskId); Q_SIGNALS: void saveConfiguration(); @@ -77,6 +78,7 @@ private Q_SLOTS: void slotAccepted(); void slotPrefilteringChanged(); void slotResetState(); + void slotSelectTask(const QString &); private: bool isValidAndTrackable(const QModelIndex &index) const; diff --git a/Charm/Widgets/TaskEditor.cpp b/Charm/Widgets/TaskEditor.cpp index cb541396..9fea9a73 100644 --- a/Charm/Widgets/TaskEditor.cpp +++ b/Charm/Widgets/TaskEditor.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld @@ -46,16 +46,11 @@ TaskEditor::TaskEditor(QWidget *parent) m_ui->dateEditFrom->calendarWidget()->setVerticalHeaderFormat(QCalendarWidget::ISOWeekNumbers); m_ui->dateEditTo->calendarWidget()->setFirstDayOfWeek(Qt::Monday); m_ui->dateEditTo->calendarWidget()->setVerticalHeaderFormat(QCalendarWidget::ISOWeekNumbers); - connect(m_ui->pushButtonParent, SIGNAL(clicked()), - SLOT(slotSelectParent())); - connect(m_ui->dateEditFrom, SIGNAL(dateChanged(QDate)), - SLOT(slotDateChanged(QDate))); - connect(m_ui->dateEditTo, SIGNAL(dateChanged(QDate)), - SLOT(slotDateChanged(QDate))); - connect(m_ui->checkBoxFrom, SIGNAL(clicked(bool)), - SLOT(slotCheckBoxChecked(bool))); - connect(m_ui->checkBoxUntil, SIGNAL(clicked(bool)), - SLOT(slotCheckBoxChecked(bool))); + connect(m_ui->pushButtonParent, &QPushButton::clicked, this, &TaskEditor::slotSelectParent); + connect(m_ui->dateEditFrom, &QDateEdit::dateChanged, this, &TaskEditor::slotDateChanged); + connect(m_ui->dateEditTo, &QDateEdit::dateChanged, this, &TaskEditor::slotDateChanged); + connect(m_ui->checkBoxFrom, &QCheckBox::clicked, this, &TaskEditor::slotCheckBoxChecked); + connect(m_ui->checkBoxUntil, &QCheckBox::clicked, this, &TaskEditor::slotCheckBoxChecked); } TaskEditor::~TaskEditor() diff --git a/Charm/Widgets/TaskEditor.h b/Charm/Widgets/TaskEditor.h index 794bf605..b1d22723 100644 --- a/Charm/Widgets/TaskEditor.h +++ b/Charm/Widgets/TaskEditor.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Charm/Widgets/TaskIdDialog.cpp b/Charm/Widgets/TaskIdDialog.cpp index 7a521ace..d5b84604 100644 --- a/Charm/Widgets/TaskIdDialog.cpp +++ b/Charm/Widgets/TaskIdDialog.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -32,8 +32,8 @@ TaskIdDialog::TaskIdDialog(TaskModelInterface *model, TasksView *parent) { m_ui.setupUi(this); m_ui.spinBox->setRange(1, 1000*1000*1000); - connect(m_ui.buttonBox, SIGNAL(accepted()), this, SLOT(accept())); - connect(m_ui.buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + connect(m_ui.buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(m_ui.buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); // resize( minimumSize() ); } diff --git a/Charm/Widgets/TaskIdDialog.h b/Charm/Widgets/TaskIdDialog.h index 7e1fa9c3..900e4efc 100644 --- a/Charm/Widgets/TaskIdDialog.h +++ b/Charm/Widgets/TaskIdDialog.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/Widgets/TasksView.cpp b/Charm/Widgets/TasksView.cpp index 279fc58c..c0f1f9fe 100644 --- a/Charm/Widgets/TasksView.cpp +++ b/Charm/Widgets/TasksView.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -75,30 +75,30 @@ TasksView::TasksView(QWidget *parent) layout->addWidget(m_treeView); m_treeView->setItemDelegate(m_delegate); - connect(m_delegate, SIGNAL(editingStateChanged()), - SLOT(configureUi())); + connect(m_delegate, &TasksViewDelegate::editingStateChanged, + this, &TasksView::configureUi); // set up actions m_actionNewTask.setText(tr("New &Task")); m_actionNewTask.setShortcut(QKeySequence::New); m_actionNewTask.setIcon(Data::newTaskIcon()); m_toolBar->addAction(&m_actionNewTask); - connect(&m_actionNewTask, SIGNAL(triggered(bool)), - SLOT(actionNewTask())); + connect(&m_actionNewTask, &QAction::triggered, + this, &TasksView::actionNewTask); m_actionNewSubTask.setText(tr("New &Subtask")); m_actionNewSubTask.setShortcut(Qt::META + Qt::Key_N); m_actionNewSubTask.setIcon(Data::newSubtaskIcon()); m_toolBar->addAction(&m_actionNewSubTask); - connect(&m_actionNewSubTask, SIGNAL(triggered(bool)), - SLOT(actionNewSubTask())); + connect(&m_actionNewSubTask, &QAction::triggered, + this, &TasksView::actionNewSubTask); m_actionEditTask.setText(tr("Edit Task")); m_actionEditTask.setShortcut(Qt::CTRL + Qt::Key_E); m_actionEditTask.setIcon(Data::editTaskIcon()); m_toolBar->addAction(&m_actionEditTask); - connect(&m_actionEditTask, SIGNAL(triggered(bool)), - SLOT(actionEditTask())); + connect(&m_actionEditTask, &QAction::triggered, + this, &TasksView::actionEditTask); m_actionDeleteTask.setText(tr("Delete Task")); QList deleteShortcuts; @@ -109,36 +109,36 @@ TasksView::TasksView(QWidget *parent) m_actionDeleteTask.setShortcuts(deleteShortcuts); m_actionDeleteTask.setIcon(Data::deleteTaskIcon()); m_toolBar->addAction(&m_actionDeleteTask); - connect(&m_actionDeleteTask, SIGNAL(triggered(bool)), - SLOT(actionDeleteTask())); + connect(&m_actionDeleteTask, &QAction::triggered, + this, &TasksView::actionDeleteTask); m_actionExpandTree.setText(tr("Expand All")); - connect(&m_actionExpandTree, SIGNAL(triggered(bool)), - m_treeView, SLOT(expandAll())); + connect(&m_actionExpandTree, &QAction::triggered, + m_treeView, &QTreeView::expandAll); m_actionCollapseTree.setText(tr("Collapse All")); - connect(&m_actionCollapseTree, SIGNAL(triggered(bool)), - m_treeView, SLOT(collapseAll())); + connect(&m_actionCollapseTree, &QAction::triggered, + m_treeView, &QTreeView::collapseAll); // filter setup m_showCurrentOnly->setText(tr("Current")); m_showCurrentOnly->setCheckable(true); m_toolBar->addAction(m_showCurrentOnly); - connect(m_showCurrentOnly, SIGNAL(triggered(bool)), - SLOT(taskPrefilteringChanged())); + connect(m_showCurrentOnly, &QAction::triggered, + this, &TasksView::taskPrefilteringChanged); m_showSubscribedOnly->setText(tr("Selected")); m_showSubscribedOnly->setCheckable(true); m_toolBar->addAction(m_showSubscribedOnly); - connect(m_showSubscribedOnly, SIGNAL(triggered(bool)), - SLOT(taskPrefilteringChanged())); + connect(m_showSubscribedOnly, &QAction::triggered, + this, &TasksView::taskPrefilteringChanged); auto searchField = new QLineEdit(this); - connect(searchField, SIGNAL(textChanged(QString)), - SLOT(slotFiltertextChanged(QString))); + connect(searchField, &QLineEdit::textChanged, + this, &TasksView::slotFiltertextChanged); m_toolBar->addWidget(searchField); m_treeView->setEditTriggers(QAbstractItemView::EditKeyPressed); @@ -148,8 +148,8 @@ TasksView::TasksView(QWidget *parent) m_treeView->setTextElideMode(Qt::ElideNone); m_treeView->setRootIsDecorated(true); m_treeView->setContextMenuPolicy(Qt::CustomContextMenu); - connect(m_treeView, SIGNAL(customContextMenuRequested(QPoint)), - SLOT(slotContextMenuRequested(QPoint))); + connect(m_treeView, &QTreeView::customContextMenuRequested, + this, &TasksView::slotContextMenuRequested); // A reasonable default depth. m_treeView->expandToDepth(0); @@ -265,16 +265,19 @@ void TasksView::stateChanged(State) ViewFilter *filter = ApplicationCore::instance().model().taskModel(); m_treeView->setModel(filter); const QItemSelectionModel *smodel = m_treeView->selectionModel(); - connect(smodel, SIGNAL(currentChanged(QModelIndex,QModelIndex)), SLOT(configureUi())); - connect(smodel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), - SLOT(configureUi())); - connect(smodel, SIGNAL(currentColumnChanged(QModelIndex,QModelIndex)), SLOT(configureUi())); + connect(smodel, &QItemSelectionModel::currentChanged, + this, &TasksView::configureUi); + connect(smodel, &QItemSelectionModel::selectionChanged, + this, &TasksView::configureUi); + connect(smodel, &QItemSelectionModel::currentColumnChanged, + this, &TasksView::configureUi); + // due to multiple inheritence we can't use the new style connects here connect(filter, SIGNAL(eventActivationNotice(EventId)), - SLOT(slotEventActivated(EventId))); + this, SLOT(slotEventActivated(EventId))); connect(filter, SIGNAL(eventDeactivationNotice(EventId)), - SLOT(slotEventDeactivated(EventId))); - connect(MODEL.charmDataModel(), SIGNAL(resetGUIState()), - SLOT(restoreGuiState())); + this, SLOT(slotEventDeactivated(EventId))); + connect(MODEL.charmDataModel(), &CharmDataModel::resetGUIState, + this, &TasksView::restoreGuiState); configurationChanged(); break; } diff --git a/Charm/Widgets/TasksView.h b/Charm/Widgets/TasksView.h index db27f918..891d6322 100644 --- a/Charm/Widgets/TasksView.h +++ b/Charm/Widgets/TasksView.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/Widgets/TasksViewDelegate.cpp b/Charm/Widgets/TasksViewDelegate.cpp index 4e010984..4f200902 100644 --- a/Charm/Widgets/TasksViewDelegate.cpp +++ b/Charm/Widgets/TasksViewDelegate.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -32,8 +32,8 @@ TasksViewDelegate::TasksViewDelegate(QObject *parent) : QItemDelegate(parent) { - connect(this, SIGNAL(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)), - SLOT(slotCloseEditor(QWidget*,QAbstractItemDelegate::EndEditHint))); + connect(this, &TasksViewDelegate::closeEditor, + this, &TasksViewDelegate::slotCloseEditor); } QWidget *TasksViewDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, diff --git a/Charm/Widgets/TasksViewDelegate.h b/Charm/Widgets/TasksViewDelegate.h index ec7c99d2..10577b2e 100644 --- a/Charm/Widgets/TasksViewDelegate.h +++ b/Charm/Widgets/TasksViewDelegate.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/Widgets/TimeTrackingTaskSelector.cpp b/Charm/Widgets/TimeTrackingTaskSelector.cpp index 2cdb2d14..63347527 100644 --- a/Charm/Widgets/TimeTrackingTaskSelector.cpp +++ b/Charm/Widgets/TimeTrackingTaskSelector.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld Author: Montel Laurent @@ -28,6 +28,7 @@ #include "SelectTaskDialog.h" #include "ViewHelpers.h" +#include "Core/Configuration.h" #include "Core/Event.h" #include "Core/Task.h" @@ -81,15 +82,16 @@ TimeTrackingTaskSelector::TimeTrackingTaskSelector(QWidget *parent) m_stopGoAction->setIcon(Data::goIcon()); m_stopGoAction->setShortcut(QKeySequence(Qt::Key_Space)); m_stopGoAction->setCheckable(true); - connect(m_stopGoAction, SIGNAL(triggered(bool)), SLOT(slotGoStopToggled(bool))); + connect(m_stopGoAction, &QAction::triggered, + this, &TimeTrackingTaskSelector::slotGoStopToggled); m_stopGoButton->setDefaultAction(m_stopGoAction); m_editCommentAction->setText(tr("Edit Comment")); m_editCommentAction->setIcon(Data::editEventIcon()); m_editCommentAction->setShortcut(Qt::Key_E); m_editCommentAction->setToolTip(m_editCommentAction->text()); - connect(m_editCommentAction, SIGNAL(triggered(bool)), - SLOT(slotEditCommentClicked())); + connect(m_editCommentAction, &QAction::triggered, + this, &TimeTrackingTaskSelector::slotEditCommentClicked); m_editCommentButton->setDefaultAction(m_editCommentAction); m_taskSelectorButton->setPopupMode(QToolButton::InstantPopup); @@ -97,8 +99,8 @@ TimeTrackingTaskSelector::TimeTrackingTaskSelector(QWidget *parent) m_taskSelectorButton->setText(tr("Select Task")); m_startOtherTaskAction->setShortcut(Qt::Key_T); - connect(m_startOtherTaskAction, SIGNAL(triggered()), - SLOT(slotManuallySelectTask())); + connect(m_startOtherTaskAction, &QAction::triggered, + this, &TimeTrackingTaskSelector::slotManuallySelectTask); } void TimeTrackingTaskSelector::populateEditMenu(QMenu *menu) @@ -115,6 +117,8 @@ QMenu *TimeTrackingTaskSelector::menu() const void TimeTrackingTaskSelector::populate(const QVector &summaries) { + Q_UNUSED(summaries); + // Don't repopulate while the menu is displayed; very ugly and it can wait. if (m_menu->isActiveWindow()) return; @@ -136,7 +140,9 @@ void TimeTrackingTaskSelector::populate(const QVector &summaries) const TaskIdList interestingTasksToAdd = DATAMODEL->mostRecentlyUsedTasks(); - for (int i = 0; i < 5 && i < interestingTasksToAdd.size(); ++i) + const int maxEntries = qMin(interestingTasksToAdd.size(), + CONFIGURATION.numberOfTaskSelectorEntries); + for (int i = 0; i < maxEntries; ++i) m_menu->addAction(createTaskAction(interestingTasksToAdd.at(i))); m_menu->addSeparator(); m_menu->addAction(m_startOtherTaskAction); @@ -202,15 +208,15 @@ void TimeTrackingTaskSelector::slotActionSelected() const bool trackable = task.trackable(); if (!trackable || expired) { const bool notTrackableAndExpired = (!trackable && expired); - const auto id = QString::number(task.id()); - const QString name = task.name(); - const QString expirationDate = QLocale::system().toString( - task.validUntil(), QLocale::ShortFormat); - QString message = notTrackableAndExpired ? tr( - "The task %1 (%2) is not trackable and expired since %3").arg(id, name, expirationDate) - : expired ? tr("The task %1 (%2) is expired since %3").arg(id, name, - expirationDate) - : tr("The task %1 (%2) is not trackable").arg(id, name); + const QString expirationDate = QLocale::system().toString(task.validUntil().date(), QLocale::ShortFormat); + const auto taskName = DATAMODEL->taskIdAndSmartNameString(task.id()); + + const auto reason = notTrackableAndExpired + ? tr("The task is not trackable and expired since %1.").arg(expirationDate) + : expired ? tr("The task is expired since %1").arg(expirationDate) + : tr("The task is not trackable"); + + const auto message = tr("Cannot select task %1: %2. Please choose another task.").arg(taskName.toHtmlEscaped(), reason); QMessageBox::information(this, tr("Please choose another task"), message); return; diff --git a/Charm/Widgets/TimeTrackingTaskSelector.h b/Charm/Widgets/TimeTrackingTaskSelector.h index a1e956aa..50849a58 100644 --- a/Charm/Widgets/TimeTrackingTaskSelector.h +++ b/Charm/Widgets/TimeTrackingTaskSelector.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/Widgets/TimeTrackingView.cpp b/Charm/Widgets/TimeTrackingView.cpp index 2a3e1f9f..39dcd6d6 100644 --- a/Charm/Widgets/TimeTrackingView.cpp +++ b/Charm/Widgets/TimeTrackingView.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -49,12 +49,12 @@ TimeTrackingView::TimeTrackingView(QWidget *parent) m_paintAttributes.initialize(palette()); for (int i = 0; i < 7; ++i) m_shortDayNames[i] = QDate::shortDayName(i + 1); - connect(m_taskSelector, SIGNAL(startEvent(TaskId)), - SIGNAL(startEvent(TaskId))); - connect(m_taskSelector, SIGNAL(stopEvents()), - SIGNAL(stopEvents())); - connect(m_taskSelector, SIGNAL(updateSummariesPlease()), - SLOT(slotUpdateSummaries())); + connect(m_taskSelector, &TimeTrackingTaskSelector::startEvent, + this, &TimeTrackingView::startEvent); + connect(m_taskSelector, &TimeTrackingTaskSelector::stopEvents, + this, &TimeTrackingView::stopEvents); + connect(m_taskSelector, &TimeTrackingTaskSelector::updateSummariesPlease, + this, &TimeTrackingView::slotUpdateSummaries); setFocusProxy(m_taskSelector); setFocusPolicy(Qt::StrongFocus); @@ -348,6 +348,7 @@ void TimeTrackingView::setSummaries(const QVector &summaries) m_taskSelector->populate(m_summaries); // FIXME maybe remember last selected task handleActiveEvents(); + emit taskMenuChanged(); } bool TimeTrackingView::isTracking() const @@ -374,6 +375,10 @@ void TimeTrackingView::configurationChanged() break; } + // re-populate menu: + m_taskSelector->populate(m_summaries); + emit taskMenuChanged(); + m_narrowFont = font(); // stay with the desktop m_narrowFont.setPointSize(m_fixedFont.pointSize()); diff --git a/Charm/Widgets/TimeTrackingView.h b/Charm/Widgets/TimeTrackingView.h index 82568120..3869d16a 100644 --- a/Charm/Widgets/TimeTrackingView.h +++ b/Charm/Widgets/TimeTrackingView.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -83,9 +83,9 @@ class TimeTrackingView : public QWidget void configurationChanged(); Q_SIGNALS: - void maybeShrink(); void startEvent(TaskId); void stopEvents(); + void taskMenuChanged(); private Q_SLOTS: void slotUpdateSummaries(); diff --git a/Charm/Widgets/TimeTrackingWindow.cpp b/Charm/Widgets/TimeTrackingWindow.cpp index 4a2b6d8c..94d5278a 100644 --- a/Charm/Widgets/TimeTrackingWindow.cpp +++ b/Charm/Widgets/TimeTrackingWindow.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld Author: Mathias Hasselmann @@ -52,10 +52,14 @@ #include "Core/XmlSerialization.h" #include "HttpClient/GetProjectCodesJob.h" -#include "HttpClient/GetUserInfoJob.h" +#include "HttpClient/RestJob.h" +#include "HttpClient/UploadTimesheetJob.h" #include "Idle/IdleDetector.h" +#include "Lotsofcake/Configuration.h" + +#include "Reports/WeeklyTimesheetXmlWriter.h" #include "Widgets/HttpJobProgressDialog.h" #include @@ -68,6 +72,7 @@ #include #include #include +#include #include #include @@ -81,18 +86,20 @@ TimeTrackingWindow::TimeTrackingWindow(QWidget *parent) setWindowNumber(3); setWindowIdentifier(QStringLiteral("window_tracking")); setCentralWidget(m_summaryWidget); - connect(m_summaryWidget, SIGNAL(startEvent(TaskId)), - SLOT(slotStartEvent(TaskId))); - connect(m_summaryWidget, SIGNAL(stopEvents()), - SLOT(slotStopEvent())); - connect(&m_checkUploadedSheetsTimer, SIGNAL(timeout()), - SLOT(slotCheckUploadedTimesheets())); - connect(m_billDialog, SIGNAL(finished(int)), - SLOT(slotBillGone(int))); - connect(&m_checkCharmReleaseVersionTimer, SIGNAL(timeout()), - SLOT(slotCheckForUpdatesAutomatic())); - connect(&m_updateUserInfoAndTasksDefinitionsTimer, SIGNAL(timeout()), - SLOT(slotGetUserInfo())); + connect(m_summaryWidget, &TimeTrackingView::startEvent, + this, &TimeTrackingWindow::slotStartEvent); + connect(m_summaryWidget, &TimeTrackingView::stopEvents, + this, &TimeTrackingWindow::slotStopEvent); + connect(m_summaryWidget, &TimeTrackingView::taskMenuChanged, + this, &TimeTrackingWindow::taskMenuChanged); + connect(&m_checkUploadedSheetsTimer, &QTimer::timeout, + this, &TimeTrackingWindow::slotCheckUploadedTimesheets); + connect(m_billDialog, &BillDialog::finished, + this, &TimeTrackingWindow::slotBillGone); + connect(&m_checkCharmReleaseVersionTimer, &QTimer::timeout, + this, &TimeTrackingWindow::slotCheckForUpdatesAutomatic); + connect(&m_updateUserInfoAndTasksDefinitionsTimer, &QTimer::timeout, + this, &TimeTrackingWindow::slotGetUserInfo); //Check every 60 minutes if there are timesheets due if (CONFIGURATION.warnUnuploadedTimesheets) @@ -100,7 +107,7 @@ TimeTrackingWindow::TimeTrackingWindow(QWidget *parent) m_checkUploadedSheetsTimer.setInterval(60 * 60 * 1000); #if defined(Q_OS_OSX) || defined(Q_OS_WIN) m_checkCharmReleaseVersionTimer.setInterval(24 * 60 * 60 * 1000); - if (!QString::fromLatin1(UPDATE_CHECK_URL).isEmpty()) { + if (!CharmUpdateCheckUrl().isEmpty()) { QTimer::singleShot(1000, this, SLOT(slotCheckForUpdatesAutomatic())); m_checkCharmReleaseVersionTimer.start(); } @@ -141,8 +148,8 @@ void TimeTrackingWindow::stateChanged(State previous) CharmWindow::stateChanged(previous); switch (ApplicationCore::instance().state()) { case Connecting: - connect(ApplicationCore::instance().dateChangeWatcher(), SIGNAL(dateChanged()), - SLOT(slotSelectTasksToShow())); + connect(ApplicationCore::instance().dateChangeWatcher(), &DateChangeWatcher::dateChanged, + this, &TimeTrackingWindow::slotSelectTasksToShow); DATAMODEL->registerAdapter(this); m_summaryWidget->setSummaries(QVector()); m_summaryWidget->handleActiveEvents(); @@ -274,11 +281,17 @@ void TimeTrackingWindow::slotStartEvent(TaskId id) if (item.task().isCurrentlyValid()) { DATAMODEL->startEventRequested(item.task()); } else { - QString nm = item.task().name(); - QMessageBox::critical(this, tr("Invalid task"), + QString nm = DATAMODEL->taskIdAndSmartNameString(id); + if (item.task().isValid()) + QMessageBox::critical(this, tr("Invalid task"), tr("Task '%1' is no longer valid, so can't be started").arg(nm)); + else if (id > 0) + QMessageBox::critical(this, tr("Invalid task"), + tr("Task '%1' does not exist").arg(id)); + } ApplicationCore::instance().updateTaskList(); + uploadStagedTimesheet(); } void TimeTrackingWindow::slotStopEvent() @@ -299,6 +312,7 @@ void TimeTrackingWindow::slotEditPreferences(bool) CONFIGURATION.warnUnuploadedTimesheets = dialog.warnUnuploadedTimesheets(); CONFIGURATION.requestEventComment = dialog.requestEventComment(); CONFIGURATION.enableCommandInterface = dialog.enableCommandInterface(); + CONFIGURATION.numberOfTaskSelectorEntries = dialog.numberOfTaskSelectorEntries(); emit saveConfiguration(); } } @@ -328,9 +342,9 @@ void TimeTrackingWindow::slotActivityReport() delete m_activityReportDialog; m_activityReportDialog = new ActivityReportConfigurationDialog(this); m_activityReportDialog->setAttribute(Qt::WA_DeleteOnClose); - connect(m_activityReportDialog, SIGNAL(finished(int)), - this, SLOT(slotActivityReportPreview(int))); - m_activityReportDialog->show(); + connect(m_activityReportDialog, &ActivityReportConfigurationDialog::finished, + this, &TimeTrackingWindow::slotActivityReportPreview); + m_activityReportDialog->open(); } void TimeTrackingWindow::resetWeeklyTimesheetDialog() @@ -338,14 +352,14 @@ void TimeTrackingWindow::resetWeeklyTimesheetDialog() delete m_weeklyTimesheetDialog; m_weeklyTimesheetDialog = new WeeklyTimesheetConfigurationDialog(this); m_weeklyTimesheetDialog->setAttribute(Qt::WA_DeleteOnClose); - connect(m_weeklyTimesheetDialog, SIGNAL(finished(int)), - this, SLOT(slotWeeklyTimesheetPreview(int))); + connect(m_weeklyTimesheetDialog, &WeeklyTimesheetConfigurationDialog::finished, + this, &TimeTrackingWindow::slotWeeklyTimesheetPreview); } void TimeTrackingWindow::slotWeeklyTimesheetReport() { resetWeeklyTimesheetDialog(); - m_weeklyTimesheetDialog->show(); + m_weeklyTimesheetDialog->open(); } void TimeTrackingWindow::resetMonthlyTimesheetDialog() @@ -353,14 +367,14 @@ void TimeTrackingWindow::resetMonthlyTimesheetDialog() delete m_monthlyTimesheetDialog; m_monthlyTimesheetDialog = new MonthlyTimesheetConfigurationDialog(this); m_monthlyTimesheetDialog->setAttribute(Qt::WA_DeleteOnClose); - connect(m_monthlyTimesheetDialog, SIGNAL(finished(int)), - this, SLOT(slotMonthlyTimesheetPreview(int))); + connect(m_monthlyTimesheetDialog, &MonthlyTimesheetConfigurationDialog::finished, + this, &TimeTrackingWindow::slotMonthlyTimesheetPreview); } void TimeTrackingWindow::slotMonthlyTimesheetReport() { resetMonthlyTimesheetDialog(); - m_monthlyTimesheetDialog->show(); + m_monthlyTimesheetDialog->open(); } void TimeTrackingWindow::slotWeeklyTimesheetPreview(int result) @@ -449,7 +463,12 @@ void TimeTrackingWindow::slotSyncTasks(VerboseMode mode) { if (ApplicationCore::instance().state() != Connected) return; - GetProjectCodesJob *client = new GetProjectCodesJob(this); + Lotsofcake::Configuration configuration; + + auto client = new GetProjectCodesJob(this); + client->setUsername(configuration.username()); + client->setDownloadUrl(configuration.projectCodeDownloadUrl()); + if (mode == Verbose) { HttpJobProgressDialog *dialog = new HttpJobProgressDialog(client, this); dialog->setWindowTitle(tr("Downloading")); @@ -457,14 +476,19 @@ void TimeTrackingWindow::slotSyncTasks(VerboseMode mode) client->setVerbose(false); } - connect(client, SIGNAL(finished(HttpJob*)), this, SLOT(slotTasksDownloaded(HttpJob*))); + connect(client, &GetProjectCodesJob::finished, + this, &TimeTrackingWindow::slotTasksDownloaded); client->start(); } +void TimeTrackingWindow::slotSyncTasksVerbose() +{ + slotSyncTasks(Verbose); +} + void TimeTrackingWindow::slotSyncTasksAutomatic() { - // check if HttpJob is possible - if (HttpJob::credentialsAvailable() && !HttpJob::lastAuthenticationFailed()) + if (Lotsofcake::Configuration().isConfigured()) slotSyncTasks(Silent); } @@ -555,7 +579,7 @@ void TimeTrackingWindow::slotBillGone(int result) case BillDialog::AsYouWish: resetWeeklyTimesheetDialog(); m_weeklyTimesheetDialog->setDefaultWeek(m_billDialog->year(), m_billDialog->week()); - m_weeklyTimesheetDialog->show(); + m_weeklyTimesheetDialog->open(); break; case BillDialog::Later: break; @@ -578,10 +602,9 @@ void TimeTrackingWindow::slotCheckForUpdatesManual() void TimeTrackingWindow::startCheckForUpdates(VerboseMode mode) { CheckForUpdatesJob *checkForUpdates = new CheckForUpdatesJob(this); - connect(checkForUpdates, SIGNAL(finished(CheckForUpdatesJob::JobData)), this, - SLOT(slotCheckForUpdates(CheckForUpdatesJob::JobData))); - const QString urlString = QStringLiteral(UPDATE_CHECK_URL); - checkForUpdates->setUrl(QUrl(urlString)); + connect(checkForUpdates, &CheckForUpdatesJob::finished, + this, &TimeTrackingWindow::slotCheckForUpdates); + checkForUpdates->setUrl(QUrl(CharmUpdateCheckUrl())); if (mode == Verbose) checkForUpdates->setVerbose(true); checkForUpdates->start(); @@ -603,7 +626,7 @@ void TimeTrackingWindow::slotCheckForUpdates(CheckForUpdatesJob::JobData data) if ((skipVersion == releaseVersion) && !data.verbose) return; - if (Charm::versionLessThan(QStringLiteral(CHARM_VERSION), releaseVersion)) { + if (Charm::versionLessThan(CharmVersion(), releaseVersion)) { informUserAboutNewRelease(releaseVersion, data.link, data.releaseInformationLink); } else { if (data.verbose) @@ -615,7 +638,7 @@ void TimeTrackingWindow::slotCheckForUpdates(CheckForUpdatesJob::JobData data) void TimeTrackingWindow::informUserAboutNewRelease(const QString &releaseVersion, const QUrl &link, const QString &releaseInfoLink) { - QString localVersion = QStringLiteral(CHARM_VERSION); + QString localVersion = CharmVersion(); localVersion.truncate(releaseVersion.length()); CharmNewReleaseDialog dialog(this); dialog.setVersion(releaseVersion, localVersion); @@ -624,6 +647,35 @@ void TimeTrackingWindow::informUserAboutNewRelease(const QString &releaseVersion dialog.exec(); } +void TimeTrackingWindow::handleIdleEvents(IdleDetector *detector, bool restart) +{ + EventIdList activeEvents = DATAMODEL->activeEvents(); + DATAMODEL->endAllEventsRequested(); + // FIXME with this option, we can only change the events to + // the start time of one idle period, I chose to use the last + // one: + const auto periods = detector->idlePeriods(); + const IdleDetector::IdlePeriod period = periods.last(); + + Q_FOREACH (EventId eventId, activeEvents) { + Event event = DATAMODEL->eventForId(eventId); + if (event.isValid()) { + Event old = event; + QDateTime start = period.first; // initializes a valid QDateTime + event.setEndDateTime(qMax(event.startDateTime(), start)); + Q_ASSERT(event.isValid()); + auto cmd = new CommandModifyEvent(event, old, this); + emit emitCommand(cmd); + if (restart) { + Task task; + task.setId(event.taskId()); + if (task.isValid()) + DATAMODEL->startEventRequested(task); + } + } + } +} + void TimeTrackingWindow::maybeIdle(IdleDetector *detector) { Q_ASSERT(detector); @@ -644,25 +696,12 @@ void TimeTrackingWindow::maybeIdle(IdleDetector *detector) break; case IdleCorrectionDialog::Idle_EndEvent: { - EventIdList activeEvents = DATAMODEL->activeEvents(); - DATAMODEL->endAllEventsRequested(); - // FIXME with this option, we can only change the events to - // the start time of one idle period, I chose to use the last - // one: - const auto periods = detector->idlePeriods(); - const IdleDetector::IdlePeriod period = periods.last(); - - Q_FOREACH (EventId eventId, activeEvents) { - Event event = DATAMODEL->eventForId(eventId); - if (event.isValid()) { - Event old = event; - QDateTime start = period.first; // initializes a valid QDateTime - event.setEndDateTime(qMax(event.startDateTime(), start)); - Q_ASSERT(event.isValid()); - auto cmd = new CommandModifyEvent(event, old, this); - emit emitCommand(cmd); - } - } + handleIdleEvents(detector, false); + break; + } + case IdleCorrectionDialog::Idle_RestartEvent: + { + handleIdleEvents(detector, true); break; } default: @@ -671,15 +710,6 @@ void TimeTrackingWindow::maybeIdle(IdleDetector *detector) detector->clear(); } -static void setValueIfNotNull(QSettings *s, const QString &key, const QString &value) -{ - if (!value.isNull()) { - s->setValue(key, value); - } else { - s->remove(key); - } -} - void TimeTrackingWindow::importTasksFromDeviceOrFile(QIODevice *device, const QString &filename, bool verbose) { @@ -719,34 +749,17 @@ void TimeTrackingWindow::importTasksFromDeviceOrFile(QIODevice *device, const QS } } - QSettings settings; - settings.beginGroup(QStringLiteral("httpconfig")); - const QString userName = settings.value(QStringLiteral("username")).toString(); - setValueIfNotNull(&settings, QStringLiteral("username"), - exporter.metadata(QStringLiteral("username"))); - const QString currentUserName = settings.value(QStringLiteral("username")).toString(); - setValueIfNotNull(&settings, QStringLiteral("portalUrl"), - exporter.metadata(QStringLiteral("portal-url"))); - setValueIfNotNull(&settings, QStringLiteral("loginUrl"), - exporter.metadata(QStringLiteral("login-url"))); - setValueIfNotNull(&settings, QStringLiteral("timesheetUploadUrl"), - exporter.metadata(QStringLiteral("timesheet-upload-url"))); - setValueIfNotNull(&settings, QStringLiteral("projectCodeDownloadUrl"), - exporter.metadata(QStringLiteral("project-code-download-url"))); - settings.endGroup(); - settings.beginGroup(QStringLiteral("users")); - setValueIfNotNull(&settings, QStringLiteral("portalUrl"), - exporter.metadata(QStringLiteral("portal-url"))); - setValueIfNotNull(&settings, QStringLiteral("loginUrl"), - exporter.metadata(QStringLiteral("login-url"))); - settings.setValue(QStringLiteral("userInfoDownloadUrl"), - QLatin1String("https://lotsofcake.kdab.com/KdabHome/rest/user")); - settings.endGroup(); - - ApplicationCore::instance().setHttpActionsVisible(true); + Lotsofcake::Configuration lotsofcakeConfig; + const auto oldUserName = lotsofcakeConfig.username(); + + lotsofcakeConfig.importFromTaskExport(exporter); + + const auto newUserName = lotsofcakeConfig.username(); + + ApplicationCore::instance().setHttpActionsVisible(lotsofcakeConfig.isConfigured()); // update user info in case the user name has changed - if (!currentUserName.isEmpty() && (currentUserName != userName)) + if (!oldUserName.isEmpty() && oldUserName != newUserName) slotGetUserInfo(); } catch (const CharmException &e) { const QString title = tr("Invalid Task Definitions"); @@ -764,26 +777,83 @@ void TimeTrackingWindow::importTasksFromDeviceOrFile(QIODevice *device, const QS } } +void TimeTrackingWindow::uploadStagedTimesheet() +{ + try { + if (m_uploadingStagedTimesheet) + return; + + const Lotsofcake::Configuration configuration; + if (!configuration.isConfigured()) + return; + + const auto today = QDate::currentDate(); + const auto lastUpload = configuration.lastStagedTimesheetUpload(); + + if (lastUpload.isValid() && lastUpload >= today) + return; + + const auto thisWeek = TimeSpans().thisWeek(); + const auto weekStart = thisWeek.timespan.first; + const auto yesterday = TimeSpans().yesterday().timespan.second; + + if (yesterday < weekStart) + return; + + int year = 0; + const auto weekNumber = today.weekNumber(&year); + WeeklyTimesheetXmlWriter timesheet; + timesheet.setDataModel(DATAMODEL); + timesheet.setYear(year); + timesheet.setWeekNumber(weekNumber); + timesheet.setIncludeTaskList(false); + + const auto matchingEventIds = DATAMODEL->eventsThatStartInTimeFrame(weekStart, yesterday); + EventList events; + events.reserve(matchingEventIds.size()); + Q_FOREACH (const EventId &id, matchingEventIds) + events.append(DATAMODEL->eventForId(id)); + timesheet.setEvents(events); + + QScopedPointer job(new UploadTimesheetJob); + connect(job.data(), &HttpJob::finished, this, [this](HttpJob *job) { + m_uploadingStagedTimesheet = false; + if (job->error() == HttpJob::NoError) { + Lotsofcake::Configuration configuration; + configuration.setLastStagedTimesheetUpload(QDate::currentDate()); + } + }); + + job->setUsername(configuration.username()); + job->setUploadUrl(configuration.timesheetUploadUrl()); + job->setStatus(UploadTimesheetJob::Staged); + job->setPayload(timesheet.saveToXml()); + job.take()->start(); + m_uploadingStagedTimesheet = true; + } catch (const XmlSerializationException &e) { + QMessageBox::critical(this, tr("Error generating the staged timesheet"), e.what()); + } +} + void TimeTrackingWindow::slotGetUserInfo() { - if (!HttpJob::credentialsAvailable()) + Lotsofcake::Configuration configuration; + if (!configuration.isConfigured()) return; - QSettings settings; - settings.beginGroup(QStringLiteral("httpconfig")); - const QString userName = settings.value(QStringLiteral("username")).toString(); - settings.endGroup(); - - settings.beginGroup(QStringLiteral("users")); - settings.setValue(QStringLiteral("userInfoDownloadUrl"), - QStringLiteral("https://lotsofcake.kdab.com/KdabHome/rest/user?user=%1").arg( - userName)); - settings.endGroup(); + const auto restUrl = configuration.restUrl(); + const auto userName = configuration.username(); - GetUserInfoJob *client = new GetUserInfoJob(this, QStringLiteral("users")); - client->setSchema(userName); - connect(client, SIGNAL(finished(HttpJob*)), this, SLOT(slotUserInfoDownloaded(HttpJob*))); - client->start(); + auto url = QUrl(restUrl); + url.setPath(url.path() + QLatin1String("user")); + QUrlQuery query; + query.addQueryItem(QLatin1String("user"), userName); + url.setQuery(query); + auto job = new RestJob(this); + job->setUsername(userName); + job->setUrl(url); + connect(job, &RestJob::finished, this, &TimeTrackingWindow::slotUserInfoDownloaded); + job->start(); } void TimeTrackingWindow::slotUserInfoDownloaded(HttpJob *job_) @@ -791,7 +861,7 @@ void TimeTrackingWindow::slotUserInfoDownloaded(HttpJob *job_) // getUserInfo done -> sync task slotSyncTasksAutomatic(); - auto job = qobject_cast(job_); + auto job = qobject_cast(job_); Q_ASSERT(job); if (job->error() == HttpJob::Canceled) return; @@ -802,7 +872,7 @@ void TimeTrackingWindow::slotUserInfoDownloaded(HttpJob *job_) return; } - const auto readData = job->userInfo(); + const auto readData = job->resultData(); QJsonParseError parseError; const auto doc = QJsonDocument::fromJson(readData, &parseError); diff --git a/Charm/Widgets/TimeTrackingWindow.h b/Charm/Widgets/TimeTrackingWindow.h index 7b6dcee7..17bdb6c3 100644 --- a/Charm/Widgets/TimeTrackingWindow.h +++ b/Charm/Widgets/TimeTrackingWindow.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -90,6 +90,7 @@ public Q_SLOTS: void slotExportToXml(); void slotImportFromXml(); void slotSyncTasks(VerboseMode mode = Verbose); + void slotSyncTasksVerbose(); void slotImportTasks(); void slotExportTasks(); void maybeIdle(IdleDetector *idleDetector); @@ -119,8 +120,10 @@ private Q_SLOTS: void emitCommand(CharmCommand *) override; void emitCommandRollback(CharmCommand *) override; void showNotification(const QString &title, const QString &message); + void taskMenuChanged(); private: + void uploadStagedTimesheet(); void resetWeeklyTimesheetDialog(); void resetMonthlyTimesheetDialog(); void showPreview(ReportConfigurationDialog *, int result); @@ -130,6 +133,7 @@ private Q_SLOTS: void startCheckForUpdates(VerboseMode mode = Silent); void informUserAboutNewRelease(const QString &releaseVersion, const QUrl &link, const QString &releaseInfoLink); + void handleIdleEvents(IdleDetector *detector, bool restart); WeeklyTimesheetConfigurationDialog *m_weeklyTimesheetDialog = nullptr; MonthlyTimesheetConfigurationDialog *m_monthlyTimesheetDialog = nullptr; @@ -141,6 +145,7 @@ private Q_SLOTS: QTimer m_updateUserInfoAndTasksDefinitionsTimer; BillDialog *m_billDialog; bool m_idleCorrectionDialogVisible = false; + bool m_uploadingStagedTimesheet = false; }; #endif diff --git a/Charm/Widgets/Timesheet.cpp b/Charm/Widgets/Timesheet.cpp index 0241feae..7ef9e999 100644 --- a/Charm/Widgets/Timesheet.cpp +++ b/Charm/Widgets/Timesheet.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -66,7 +66,7 @@ void TimeSheetReport::slotSaveToXml() if (fileinfo.suffix().isEmpty()) filename += QLatin1String(".charmreport"); - QByteArray payload = saveToXml(); + QByteArray payload = saveToXml(IncludeTaskList); if (payload.isEmpty()) return; // Error should have been already displayed by saveToXml() diff --git a/Charm/Widgets/Timesheet.h b/Charm/Widgets/Timesheet.h index b5227299..ee91778c 100644 --- a/Charm/Widgets/Timesheet.h +++ b/Charm/Widgets/Timesheet.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -41,11 +41,15 @@ class TimeSheetReport : public ReportPreviewWindow bool activeTasksOnly); protected: + enum SaveToXmlMode { + IncludeTaskList, + ExcludeTaskList + }; virtual QString suggestedFileName() const = 0; virtual void update() = 0; virtual QByteArray saveToText() = 0; - virtual QByteArray saveToXml() = 0; + virtual QByteArray saveToXml(SaveToXmlMode mode) = 0; protected: diff --git a/Charm/Widgets/TrayIcon.cpp b/Charm/Widgets/TrayIcon.cpp index a705c5e8..17589d94 100644 --- a/Charm/Widgets/TrayIcon.cpp +++ b/Charm/Widgets/TrayIcon.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -28,9 +28,7 @@ TrayIcon::TrayIcon(QObject *parent) : QSystemTrayIcon(parent) { - connect(this, - SIGNAL(activated(QSystemTrayIcon::ActivationReason)), - SLOT(slotActivated(QSystemTrayIcon::ActivationReason))); + connect(this, &QSystemTrayIcon::activated, this, &TrayIcon::slotActivated); } TrayIcon::~TrayIcon() diff --git a/Charm/Widgets/TrayIcon.h b/Charm/Widgets/TrayIcon.h index 9adaad9c..bdc9eade 100644 --- a/Charm/Widgets/TrayIcon.h +++ b/Charm/Widgets/TrayIcon.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Charm/Widgets/WeeklyTimesheet.cpp b/Charm/Widgets/WeeklyTimesheet.cpp index 4e2e4154..dcbaf180 100644 --- a/Charm/Widgets/WeeklyTimesheet.cpp +++ b/Charm/Widgets/WeeklyTimesheet.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -34,6 +34,7 @@ #include "DateEntrySyncer.h" #include "HttpClient/UploadTimesheetJob.h" +#include "Lotsofcake/Configuration.h" #include "Widgets/HttpJobProgressDialog.h" #include "SelectTaskDialog.h" @@ -113,23 +114,24 @@ WeeklyTimesheetConfigurationDialog::WeeklyTimesheetConfigurationDialog(QWidget * m_ui->setupUi(this); m_ui->dateEditDay->calendarWidget()->setFirstDayOfWeek(Qt::Monday); m_ui->dateEditDay->calendarWidget()->setVerticalHeaderFormat(QCalendarWidget::ISOWeekNumbers); - connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept())); - connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + connect(m_ui->buttonBox, &QDialogButtonBox::accepted, + this, &WeeklyTimesheetConfigurationDialog::accept); + connect(m_ui->buttonBox, &QDialogButtonBox::rejected, + this, &WeeklyTimesheetConfigurationDialog::reject); connect(m_ui->comboBoxWeek, SIGNAL(currentIndexChanged(int)), SLOT(slotWeekComboItemSelected(int))); - connect(m_ui->toolButtonSelectTask, SIGNAL(clicked()), - SLOT(slotSelectTask())); - connect(m_ui->checkBoxSubTasksOnly, SIGNAL(toggled(bool)), - SLOT(slotCheckboxSubtasksOnlyChecked(bool))); + connect(m_ui->toolButtonSelectTask, &QToolButton::clicked, + this, &WeeklyTimesheetConfigurationDialog::slotSelectTask); + connect(m_ui->checkBoxSubTasksOnly, &QCheckBox::toggled, + this, &WeeklyTimesheetConfigurationDialog::slotCheckboxSubtasksOnlyChecked); m_ui->comboBoxWeek->setCurrentIndex(1); slotCheckboxSubtasksOnlyChecked(m_ui->checkBoxSubTasksOnly->isChecked()); new DateEntrySyncer(m_ui->spinBoxWeek, m_ui->spinBoxYear, m_ui->dateEditDay, 1, this); slotStandardTimeSpansChanged(); - connect(ApplicationCore::instance().dateChangeWatcher(), - SIGNAL(dateChanged()), - SLOT(slotStandardTimeSpansChanged())); + connect(ApplicationCore::instance().dateChangeWatcher(), &DateChangeWatcher::dateChanged, + this, &WeeklyTimesheetConfigurationDialog::slotStandardTimeSpansChanged); // load settings: QSettings settings; @@ -262,10 +264,10 @@ WeeklyTimeSheetReport::WeeklyTimeSheetReport(QWidget *parent) : TimeSheetReport(parent) { QPushButton *upload = uploadButton(); - connect(upload, SIGNAL(clicked()), SLOT(slotUploadTimesheet())); - connect(this, SIGNAL(anchorClicked(QUrl)), SLOT(slotLinkClicked(QUrl))); + connect(upload, &QPushButton::clicked, this, &WeeklyTimeSheetReport::slotUploadTimesheet); + connect(this, &ReportPreviewWindow::anchorClicked, this, &WeeklyTimeSheetReport::slotLinkClicked); - if (!HttpJob::credentialsAvailable()) + if (!Lotsofcake::Configuration().isConfigured()) upload->hide(); } @@ -282,12 +284,15 @@ void WeeklyTimeSheetReport::setReportProperties( void WeeklyTimeSheetReport::slotUploadTimesheet() { + const Lotsofcake::Configuration configuration; auto client = new UploadTimesheetJob(this); + client->setUsername(configuration.username()); + client->setUploadUrl(configuration.timesheetUploadUrl()); auto dialog = new HttpJobProgressDialog(client, this); dialog->setWindowTitle(tr("Uploading")); - connect(client, SIGNAL(finished(HttpJob*)), this, SLOT(slotTimesheetUploaded(HttpJob*))); + connect(client, &HttpJob::finished, this, &WeeklyTimeSheetReport::slotTimesheetUploaded); client->setFileName(suggestedFileName()); - client->setPayload(saveToXml()); + client->setPayload(saveToXml(ExcludeTaskList)); client->start(); uploadButton()->setEnabled(false); } @@ -508,7 +513,7 @@ void WeeklyTimeSheetReport::update() uploadButton()->setEnabled(true); } -QByteArray WeeklyTimeSheetReport::saveToXml() +QByteArray WeeklyTimeSheetReport::saveToXml(SaveToXmlMode mode) { try { WeeklyTimesheetXmlWriter timesheet; @@ -516,6 +521,7 @@ QByteArray WeeklyTimeSheetReport::saveToXml() timesheet.setYear(m_yearOfWeek); timesheet.setWeekNumber(m_weekNumber); timesheet.setRootTask(rootTask()); + timesheet.setIncludeTaskList(mode == IncludeTaskList); const EventIdList matchingEventIds = DATAMODEL->eventsThatStartInTimeFrame( startDate(), endDate()); EventList events; diff --git a/Charm/Widgets/WeeklyTimesheet.h b/Charm/Widgets/WeeklyTimesheet.h index cf06d796..b2a9b04b 100644 --- a/Charm/Widgets/WeeklyTimesheet.h +++ b/Charm/Widgets/WeeklyTimesheet.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2014-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2014-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld @@ -91,7 +91,7 @@ private Q_SLOTS: private: QString suggestedFileName() const override; void update() override; - QByteArray saveToXml() override; + QByteArray saveToXml(SaveToXmlMode mode) override; QByteArray saveToText() override; private: diff --git a/Charm/Widgets/WidgetUtils.cpp b/Charm/Widgets/WidgetUtils.cpp index c351a4aa..8083c818 100644 --- a/Charm/Widgets/WidgetUtils.cpp +++ b/Charm/Widgets/WidgetUtils.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2016-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2016-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Hannah von Reth diff --git a/Charm/Widgets/WidgetUtils.h b/Charm/Widgets/WidgetUtils.h index 217f2c8b..d3b52681 100644 --- a/Charm/Widgets/WidgetUtils.h +++ b/Charm/Widgets/WidgetUtils.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2016-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2016-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Hannah von Reth diff --git a/CharmCMake.h.cmake b/CharmCMake.h.cmake index c23f36b6..fafb30ae 100644 --- a/CharmCMake.h.cmake +++ b/CharmCMake.h.cmake @@ -1,13 +1,25 @@ -/* Define to the version from CMake */ +#ifndef CHARM_CMAKE_H +#define CHARM_CMAKE_H + #define CHARM_VERSION "@Charm_VERSION@" + +#include +/* Define to the version from CMake */ +static inline QString CharmVersion() { + static const auto version = QStringLiteral("@Charm_VERSION@"); + return version; +} /* Define if you have enabled the idle detection */ #cmakedefine CHARM_IDLE_DETECTION /* Defined if idle detection is available on X11 or XCB*/ #cmakedefine CHARM_IDLE_DETECTION_AVAILABLE /* Delay for idle detection, default is 360 */ -#define CHARM_IDLE_TIME @CHARM_IDLE_TIME@ +Q_CONSTEXPR static int CharmIdleTime = @CHARM_IDLE_TIME@; /* Define the url where to check for updates */ -#define UPDATE_CHECK_URL "@UPDATE_CHECK_URL@" +static inline QString CharmUpdateCheckUrl(){ + static const auto url = QStringLiteral("@UPDATE_CHECK_URL@"); + return url; +} /* Defined if command interface is enabled */ #cmakedefine CHARM_CI_SUPPORT #ifdef CHARM_CI_SUPPORT @@ -16,3 +28,5 @@ /* Defined if local socket command interface is enabled */ #cmakedefine CHARM_CI_LOCALSERVER #endif + +#endif // CHARM_CMAKE_H diff --git a/Core/CMakeLists.txt b/Core/CMakeLists.txt index c25bde6d..79bc43d1 100644 --- a/Core/CMakeLists.txt +++ b/Core/CMakeLists.txt @@ -23,6 +23,7 @@ SET( CharmCommand.cpp SmartNameCache.cpp XmlSerialization.cpp + CharmQtCompat.cpp ) ADD_LIBRARY( CharmCore STATIC ${CharmCore_SRCS} ) diff --git a/Core/CharmCommand.cpp b/Core/CharmCommand.cpp index 6756c58c..03898887 100644 --- a/Core/CharmCommand.cpp +++ b/Core/CharmCommand.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Core/CharmCommand.h b/Core/CharmCommand.h index 2dca0e9a..58fe1dc3 100644 --- a/Core/CharmCommand.h +++ b/Core/CharmCommand.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Core/CharmConstants.cpp b/Core/CharmConstants.cpp index 498a104f..48f7e632 100644 --- a/Core/CharmConstants.cpp +++ b/Core/CharmConstants.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld @@ -67,6 +67,7 @@ const QString MetaKey_Key_RequestEventComment = QStringLiteral("RequestEventComm const QString MetaKey_Key_ToolButtonStyle = QStringLiteral("ToolButtonStyle"); const QString MetaKey_Key_ShowStatusBar = QStringLiteral("ShowStatusBar"); const QString MetaKey_Key_EnableCommandInterface = QStringLiteral("EnableCommandInterface"); +const QString MetaKey_Key_NumberOfTaskSelectorEntries = QStringLiteral("NumberOfTaskSelectorEntries"); const QString TrueString(QStringLiteral("true")); const QString FalseString(QStringLiteral("false")); diff --git a/Core/CharmConstants.h b/Core/CharmConstants.h index 64482653..08be805a 100644 --- a/Core/CharmConstants.h +++ b/Core/CharmConstants.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld @@ -74,6 +74,7 @@ extern const QString MetaKey_Key_RequestEventComment; extern const QString MetaKey_Key_ToolButtonStyle; extern const QString MetaKey_Key_ShowStatusBar; extern const QString MetaKey_Key_EnableCommandInterface; +extern const QString MetaKey_Key_NumberOfTaskSelectorEntries; extern const QString TrueString; extern const QString FalseString; diff --git a/Core/CharmDataModel.cpp b/Core/CharmDataModel.cpp index 6592b030..072876f9 100644 --- a/Core/CharmDataModel.cpp +++ b/Core/CharmDataModel.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld @@ -39,6 +39,8 @@ #include #include #include +#include +#include CharmDataModel::CharmDataModel() : QObject() @@ -647,81 +649,63 @@ EventIdList CharmDataModel::activeEvents() const return m_activeEventIds; } -struct TaskWithCount { - TaskId id; - unsigned int count; - - bool operator<(const TaskWithCount &other) const - { - return count < other.count; +TaskIdList CharmDataModel::mostFrequentlyUsedTasks() const +{ + std::unordered_map mfuMap; + const EventMap& events = eventMap(); + for( auto it : events) { + mfuMap[it.second.taskId()]++; } -}; -struct TaskWithLastUseDate { - TaskId id; - QDateTime lastUse; + const auto comp = []( quint32 a, quint32 b ){ + return a > b; + }; - bool operator<(const TaskWithLastUseDate &other) const - { - return lastUse < other.lastUse; + std::map mfu( comp ); + for ( const auto kv : mfuMap ) { + mfu[kv.second] = kv.first; } -}; -TaskIdList CharmDataModel::mostFrequentlyUsedTasks() const -{ - QMap mfuMap; - const EventMap &events = eventMap(); - for (EventMap::const_iterator it = events.begin(); it != events.end(); ++it) { - const TaskId id = it->second.taskId(); - // process use count - const unsigned count = mfuMap[id] + 1; - mfuMap[id] = count; - } - std::priority_queue mfuTasks; - for (QMap::const_iterator it = mfuMap.constBegin(); it != mfuMap.constEnd(); - ++it) { - TaskWithCount t; - t.id = it.key(); - t.count = it.value(); - mfuTasks.push(t); - } - TaskIdList mfu; - while (!mfuTasks.empty()) { - const TaskWithCount t = mfuTasks.top(); - mfuTasks.pop(); - mfu.append(t.id); - } - return mfu; + TaskIdList out; + out.reserve( static_cast( mfu.size() ) ); + std::transform( mfu.cbegin(), mfu.cend(), std::inserter( out, out.begin() ), []( const std::pair &in ) { + return in.second; + }); + return out; } TaskIdList CharmDataModel::mostRecentlyUsedTasks() const { - QMap mruMap; - const EventMap &events = eventMap(); - for (EventMap::const_iterator it = events.begin(); it != events.end(); ++it) { - const TaskId id = it->second.taskId(); + std::unordered_map mruMap; + const EventMap& events = eventMap(); + for( const auto &it : events ) { + const TaskId id = it.second.taskId(); + if ( id == 0 ) + continue; // process use date // Note: for a relative order, the UTC time is sufficient and much faster - const QDateTime date = it->second.startDateTime(Qt::UTC); - mruMap[id] = qMax(mruMap[id], date); - } - std::priority_queue mruTasks; - for (QMap::const_iterator it = mruMap.constBegin(); it != mruMap.constEnd(); - ++it) { - TaskWithLastUseDate t; - t.id = it.key(); - t.lastUse = it.value(); - if (t.id != 0) mruTasks.push(t); + const QDateTime date = it.second.startDateTime( Qt::UTC ); + const auto old = mruMap.find( id ); + if ( old != mruMap.cend() ) { + mruMap[id]= qMax( old->second, date ); + } else { + mruMap[id]= date; + } } - TaskIdList mru; - while (!mruTasks.empty()) { - const TaskWithLastUseDate t = mruTasks.top(); - mruTasks.pop(); - Q_ASSERT(t.id != 0); - mru.append(t.id); + const auto comp = [] ( const QDateTime &a, const QDateTime &b ) + { + return a > b; + }; + std::map mru( comp ); + for ( const auto kv : mruMap ) { + mru[kv.second] = kv.first; } - - return mru; + TaskIdList out; + out.reserve( static_cast( mru.size() ) ); + std::transform( mru.cbegin(), mru.cend(), std::inserter( out, out.begin() ), []( const std::pair &in ) { + return in.second; + }); + return out; } bool CharmDataModel::operator==(const CharmDataModel &other) const diff --git a/Core/CharmDataModel.h b/Core/CharmDataModel.h index f239d2e7..09eac15e 100644 --- a/Core/CharmDataModel.h +++ b/Core/CharmDataModel.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Core/CharmDataModelAdapterInterface.h b/Core/CharmDataModelAdapterInterface.h index bd559473..51550930 100644 --- a/Core/CharmDataModelAdapterInterface.h +++ b/Core/CharmDataModelAdapterInterface.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Core/CharmExceptions.cpp b/Core/CharmExceptions.cpp index 9df998b3..8244d51a 100644 --- a/Core/CharmExceptions.cpp +++ b/Core/CharmExceptions.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2010-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2010-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Core/CharmExceptions.h b/Core/CharmExceptions.h index 128f4a67..f02e0bbe 100644 --- a/Core/CharmExceptions.h +++ b/Core/CharmExceptions.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Core/CharmQtCompat.cpp b/Core/CharmQtCompat.cpp new file mode 100644 index 00000000..a5a8b287 --- /dev/null +++ b/Core/CharmQtCompat.cpp @@ -0,0 +1,25 @@ +/* + CharmQtCompat.cpp + + This file is part of Charm, a task-based time tracking application. + + Copyright (C) 2017-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + + Author: Hannah von Reth + + 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "CharmQtCompat.h" + diff --git a/Core/CharmQtCompat.h b/Core/CharmQtCompat.h new file mode 100644 index 00000000..c8052408 --- /dev/null +++ b/Core/CharmQtCompat.h @@ -0,0 +1,44 @@ +/* + CharmQtCompat.h + + This file is part of Charm, a task-based time tracking application. + + Copyright (C) 2017-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + + Author: Hannah von Reth + + 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +#ifndef CHARMQTCOMPAT_H +#define CHARMQTCOMPAT_H + +#include + +#if QT_VERSION < QT_VERSION_CHECK(5, 7, 0) + +QT_BEGIN_NAMESPACE + +// this adds const to non-const objects (like std::as_const) +template +Q_DECL_CONSTEXPR typename std::add_const::type &qAsConst(T &t) Q_DECL_NOTHROW { return t; } + +// prevent rvalue arguments: +template +void qAsConst(const T &&) Q_DECL_EQ_DELETE; + +QT_END_NAMESPACE + +#endif + +#endif // CHARMQTCOMPAT_H diff --git a/Core/CommandEmitterInterface.h b/Core/CommandEmitterInterface.h index 0eeb757e..e27a5ffc 100644 --- a/Core/CommandEmitterInterface.h +++ b/Core/CommandEmitterInterface.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Core/Configuration.cpp b/Core/Configuration.cpp index 4c1207d7..f22d1231 100644 --- a/Core/Configuration.cpp +++ b/Core/Configuration.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld @@ -51,7 +51,7 @@ Configuration::Configuration(TaskPrefilteringMode _taskPrefilteringMode, DurationFormat _durationFormat, bool _detectIdling, Qt::ToolButtonStyle _buttonstyle, bool _showStatusBar, bool _warnUnuploadedTimesheets, bool _requestEventComment, - bool _enableCommandInterface) + bool _enableCommandInterface, int _numberOfTaskSelectorEntries) : taskPrefilteringMode(_taskPrefilteringMode) , timeTrackerFontSize(_timeTrackerFontSize) , durationFormat(_durationFormat) @@ -61,6 +61,7 @@ Configuration::Configuration(TaskPrefilteringMode _taskPrefilteringMode, , warnUnuploadedTimesheets(_warnUnuploadedTimesheets) , requestEventComment(_requestEventComment) , enableCommandInterface(_enableCommandInterface) + , numberOfTaskSelectorEntries(_numberOfTaskSelectorEntries) , configurationName(DEFAULT_CONFIG_GROUP) { } @@ -79,7 +80,8 @@ bool Configuration::operator==(const Configuration &other) const && configurationName == other.configurationName && installationId == other.installationId && localStorageType == other.localStorageType - && localStorageDatabase == other.localStorageDatabase; + && localStorageDatabase == other.localStorageDatabase + && numberOfTaskSelectorEntries == other.numberOfTaskSelectorEntries; } void Configuration::writeTo(QSettings &settings) @@ -94,8 +96,16 @@ void Configuration::writeTo(QSettings &settings) bool Configuration::readFrom(QSettings &settings) { bool complete = true; + bool dirty = false; if (settings.contains(MetaKey_Key_InstallationId)) { - installationId = settings.value(MetaKey_Key_InstallationId).toInt(); + bool ok; + installationId = settings.value(MetaKey_Key_InstallationId).toUInt(&ok); + if (!ok || installationId == 1) { + const auto newId = createInstallationId(); + qDebug() << "Migrating installationId" << installationId << "to" << newId; + installationId = newId; + dirty = true; + } } else { complete = false; } @@ -115,6 +125,9 @@ bool Configuration::readFrom(QSettings &settings) complete = false; } dump(QStringLiteral("(Configuration::readFrom loaded configuration)")); + if (dirty && complete) { + writeTo(settings); + } return complete; } @@ -137,5 +150,12 @@ void Configuration::dump(const QString &why) << "--> showStatusBar: " << showStatusBar << endl << "--> warnUnuploadedTimesheets: " << warnUnuploadedTimesheets << endl << "--> requestEventComment: " << requestEventComment << endl - << "--> enableCommandInterface: " << enableCommandInterface; + << "--> enableCommandInterface: " << enableCommandInterface + << "--> numberOfTaskSelectorEntries: " << numberOfTaskSelectorEntries; +} + +quint32 Configuration::createInstallationId() const +{ + qsrand(QDateTime::currentMSecsSinceEpoch()); + return qrand() + 2; } diff --git a/Core/Configuration.h b/Core/Configuration.h index a0c61b51..02b9bbd0 100644 --- a/Core/Configuration.h +++ b/Core/Configuration.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld @@ -68,6 +68,8 @@ class Configuration // helper method void dump(const QString &why = QString::null); + quint32 createInstallationId() const; + User user; // this user's id TaskPrefilteringMode taskPrefilteringMode = TaskPrefilter_ShowAll; TimeTrackerFontSize timeTrackerFontSize = TimeTrackerFont_Regular; @@ -78,10 +80,11 @@ class Configuration bool warnUnuploadedTimesheets = true; bool requestEventComment = false; bool enableCommandInterface = false; + int numberOfTaskSelectorEntries = 5; // these are stored in QSettings, since we need this information to locate and open the database: QString configurationName; - int installationId = 0; + quint32 installationId = 0; QString localStorageType; // SqLite, MySql, ... QString localStorageDatabase; // database name (path, with sqlite) bool newDatabase = false; // true if the configuration has just been created @@ -100,7 +103,7 @@ class Configuration Configuration(TaskPrefilteringMode taskPrefilteringMode, TimeTrackerFontSize, DurationFormat durationFormat, bool detectIdling, Qt::ToolButtonStyle buttonstyle, bool showStatusBar, bool warnUnuploadedTimesheets, bool _requestEventComment, - bool enableCommandInterface); + bool enableCommandInterface, int _numberOfTaskSelectorEntries); Configuration(); }; diff --git a/Core/Controller.cpp b/Core/Controller.cpp index 5220cfdc..34e7563a 100644 --- a/Core/Controller.cpp +++ b/Core/Controller.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld @@ -235,7 +235,9 @@ void Controller::persistMetaData(Configuration &configuration) { MetaKey_Key_ShowStatusBar, stringForBool(configuration.showStatusBar) }, { MetaKey_Key_EnableCommandInterface, - stringForBool(configuration.enableCommandInterface) } + stringForBool(configuration.enableCommandInterface) }, + { MetaKey_Key_NumberOfTaskSelectorEntries, + QString::number(configuration.numberOfTaskSelectorEntries) } }; int NumberOfSettings = sizeof settings / sizeof settings[0]; @@ -270,6 +272,8 @@ void Controller::provideMetaData(Configuration &configuration) loadConfigValue(MetaKey_Key_ToolButtonStyle, configuration.toolButtonStyle); loadConfigValue(MetaKey_Key_ShowStatusBar, configuration.showStatusBar); loadConfigValue(MetaKey_Key_EnableCommandInterface, configuration.enableCommandInterface); + loadConfigValue(MetaKey_Key_NumberOfTaskSelectorEntries, configuration.numberOfTaskSelectorEntries); + configuration.numberOfTaskSelectorEntries = qMax(0, configuration.numberOfTaskSelectorEntries); CONFIGURATION.dump(); } diff --git a/Core/Controller.h b/Core/Controller.h index 20b81a4a..1bb842cc 100644 --- a/Core/Controller.h +++ b/Core/Controller.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Olivier JG diff --git a/Core/Dates.cpp b/Core/Dates.cpp index 1f2c657a..cb80fbc5 100644 --- a/Core/Dates.cpp +++ b/Core/Dates.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2010-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2010-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld Author: Olivier JG diff --git a/Core/Dates.h b/Core/Dates.h index 8781d529..eecd021d 100644 --- a/Core/Dates.h +++ b/Core/Dates.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2010-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2010-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld Author: Olivier JG diff --git a/Core/Event.cpp b/Core/Event.cpp index 18afd5bc..78713180 100644 --- a/Core/Event.cpp +++ b/Core/Event.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm @@ -34,7 +34,6 @@ Event::Event() bool Event::operator ==(const Event &other) const { return other.id() == id() - && other.installationId() == installationId() && other.taskId() == taskId() && other.comment() == comment() && other.startDateTime() == startDateTime() @@ -73,19 +72,9 @@ void Event::setReportId(int reportId) m_reportid = reportId; } -void Event::setInstallationId(int instId) -{ - m_installationId = instId; -} - -int Event::installationId() const -{ - return m_installationId; -} - bool Event::isValid() const { // negative values are allowed and indicate calculated values - return id() != 0 && m_installationId != 0; + return id() != 0; } TaskId Event::taskId() const @@ -163,7 +152,6 @@ void dumpEvents(const EventList &events) const QString EventElement(QStringLiteral("event")); const QString EventIdAttribute(QStringLiteral("eventid")); -const QString EventInstallationIdAttribute(QStringLiteral("installationid")); const QString EventTaskIdAttribute(QStringLiteral("taskid")); const QString EventUserIdAttribute(QStringLiteral("userid")); const QString EventReportIdAttribute(QStringLiteral("reportid")); @@ -174,7 +162,6 @@ QDomElement Event::toXml(QDomDocument document) const { QDomElement element = document.createElement(EventElement); element.setAttribute(EventIdAttribute, QString().setNum(id())); - element.setAttribute(EventInstallationIdAttribute, QString().setNum(installationId())); element.setAttribute(EventTaskIdAttribute, QString().setNum(taskId())); element.setAttribute(EventUserIdAttribute, QString().setNum(userId())); element.setAttribute(EventReportIdAttribute, QString().setNum(reportId())); @@ -204,8 +191,6 @@ Event Event::fromXml(const QDomElement &element, int databaseSchemaVersion) event.setComment(element.text()); event.setId(element.attribute(EventIdAttribute).toInt(&ok)); if (!ok) throw XmlSerializationException(QObject::tr("Event::fromXml: invalid event id")); - event.setInstallationId(element.attribute(EventInstallationIdAttribute).toInt(&ok)); - if (!ok) throw XmlSerializationException(QObject::tr("Event::fromXml: invalid installation id")); event.setTaskId(element.attribute(EventTaskIdAttribute).toInt(&ok)); if (!ok) throw XmlSerializationException(QObject::tr("Event::fromXml: invalid task id")); diff --git a/Core/Event.h b/Core/Event.h index 2f817767..3b6ad0aa 100644 --- a/Core/Event.h +++ b/Core/Event.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm @@ -63,10 +63,6 @@ class Event void setReportId(int userId); - void setInstallationId(int instId); - - int installationId() const; - bool isValid() const; TaskId taskId() const; @@ -102,8 +98,6 @@ class Event * if the event is imported from a report. */ int m_reportid = {}; - /** The installation-unique id of the event. */ - int m_installationId = {}; int m_id = {}; /** The task this event belongs to. */ TaskId m_taskId = {}; diff --git a/Core/EventModelInterface.h b/Core/EventModelInterface.h index c4791c1a..eadff228 100644 --- a/Core/EventModelInterface.h +++ b/Core/EventModelInterface.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Core/MySqlStorage.cpp b/Core/MySqlStorage.cpp index dacaac85..5829f32a 100644 --- a/Core/MySqlStorage.cpp +++ b/Core/MySqlStorage.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld @@ -174,11 +174,6 @@ bool MySqlStorage::disconnect() return false; // not implemented } -int MySqlStorage::installationId() const -{ - return -1; // not implemented -} - bool MySqlStorage::createDatabase(Configuration &) { return createDatabaseTables(); diff --git a/Core/MySqlStorage.h b/Core/MySqlStorage.h index 987ddfa2..0e5581b3 100644 --- a/Core/MySqlStorage.h +++ b/Core/MySqlStorage.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm @@ -52,7 +52,6 @@ class MySqlStorage : public SqlStorage QString description() const override; bool connect(Configuration &) override; bool disconnect() override; - int installationId() const override; bool createDatabase(Configuration &) override; bool createDatabaseTables() override; diff --git a/Core/SmartNameCache.cpp b/Core/SmartNameCache.cpp index 639f2253..03a667b2 100644 --- a/Core/SmartNameCache.cpp +++ b/Core/SmartNameCache.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2012-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2012-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Core/SmartNameCache.h b/Core/SmartNameCache.h index e56155cd..60de8a46 100644 --- a/Core/SmartNameCache.h +++ b/Core/SmartNameCache.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2012-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2012-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Core/SqLiteStorage.cpp b/Core/SqLiteStorage.cpp index 7d080fd8..eef305cb 100644 --- a/Core/SqLiteStorage.cpp +++ b/Core/SqLiteStorage.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld @@ -171,7 +171,6 @@ bool SqLiteStorage::createDatabaseTables() bool SqLiteStorage::connect(Configuration &configuration) { // make sure the database folder exits: - m_installationId = configuration.installationId; configuration.failure = true; const QFileInfo fileInfo(configuration.localStorageDatabase); // this is the full path @@ -266,11 +265,6 @@ bool SqLiteStorage::disconnect() return true; // neither of the two methods return a value } -int SqLiteStorage::installationId() const -{ - return m_installationId; -} - QSqlDatabase &SqLiteStorage::database() { return m_database; @@ -289,16 +283,5 @@ bool SqLiteStorage::createDatabase(Configuration &configuration) return false; } - // make an installation: - // FIXME make a useful name for it - QString installationName = QStringLiteral("Unnamed Installation"); - Installation installation = createInstallation(installationName); - if (!installation.isValid()) { - qDebug() << "SqLiteStorage::createDatabase: cannot create default installation id"; - return false; - } else { - configuration.installationId = installation.id(); - } - return true; } diff --git a/Core/SqLiteStorage.h b/Core/SqLiteStorage.h index 01c42e1d..cf337c10 100644 --- a/Core/SqLiteStorage.h +++ b/Core/SqLiteStorage.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Mike McQuaid @@ -43,7 +43,6 @@ class SqLiteStorage : public SqlStorage bool disconnect() override; QSqlDatabase &database() override; - int installationId() const override; protected: bool createDatabase(Configuration &) override; @@ -53,7 +52,6 @@ class SqLiteStorage : public SqlStorage private: QSqlDatabase m_database; - int m_installationId = 0; }; #endif diff --git a/Core/SqlRaiiTransactor.cpp b/Core/SqlRaiiTransactor.cpp index dc3ae36e..395900c8 100644 --- a/Core/SqlRaiiTransactor.cpp +++ b/Core/SqlRaiiTransactor.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2010-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2010-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Core/SqlRaiiTransactor.h b/Core/SqlRaiiTransactor.h index 2654b3dd..586d5d8c 100644 --- a/Core/SqlRaiiTransactor.h +++ b/Core/SqlRaiiTransactor.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Core/SqlStorage.cpp b/Core/SqlStorage.cpp index 0be6b34e..7db5cbc2 100644 --- a/Core/SqlStorage.cpp +++ b/Core/SqlStorage.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld @@ -229,7 +229,6 @@ Event SqlStorage::makeEventFromRecord(const QSqlRecord &record) Event event; int idField = record.indexOf(QStringLiteral("event_id")); - int instIdField = record.indexOf(QStringLiteral("installation_id")); int userIdField = record.indexOf(QStringLiteral("user_id")); int reportIdField = record.indexOf(QStringLiteral("report_id")); int taskField = record.indexOf(QStringLiteral("task")); @@ -240,7 +239,6 @@ Event SqlStorage::makeEventFromRecord(const QSqlRecord &record) event.setId(record.field(idField).value().toInt()); event.setUserId(record.field(userIdField).value().toInt()); event.setReportId(record.field(reportIdField).value().toInt()); - event.setInstallationId(record.field(instIdField).value().toInt()); event.setTaskId(record.field(taskField).value().toInt()); event.setComment(record.field(commentField).value().toString()); if (!record.field(startField).isNull()) { @@ -298,7 +296,6 @@ Event SqlStorage::makeEvent(const SqlRaiiTransactor &) if (result && query.next()) { int indexField = query.record().indexOf(QStringLiteral("id")); event.setId(query.value(indexField).toInt()); - event.setInstallationId(installationId()); Q_ASSERT(event.id() > 0); } else { Q_ASSERT_X(false, Q_FUNC_INFO, @@ -312,7 +309,7 @@ Event SqlStorage::makeEvent(const SqlRaiiTransactor &) query.prepare(QLatin1String("UPDATE Events SET event_id = :event_id, " "installation_id = :installation_id, report_id = :report_id WHERE id = :id;")); query.bindValue(QStringLiteral(":event_id"), event.id()); - query.bindValue(QStringLiteral(":installation_id"), event.installationId()); + query.bindValue(QStringLiteral(":installation_id"), 1); query.bindValue(QStringLiteral(":report_id"), event.reportId()); query.bindValue(QStringLiteral(":id"), event.id()); result = runQuery(query); @@ -576,99 +573,6 @@ bool SqlStorage::deleteSubscription(User user, Task task) return runQuery(query); } -Installation SqlStorage::createInstallation(const QString &name) -{ - SqlRaiiTransactor transactor(database()); - bool result; - - Installation installation; - { // insert a new record in the database - QSqlQuery query(database()); - query.prepare(QStringLiteral( - "INSERT into Installations values ( NULL, NULL, NULL, :name );")); - query.bindValue(QStringLiteral(":name"), name); - result = runQuery(query); - Q_ASSERT(result); - Q_UNUSED(result); // this has to succeed - } - if (result) { - // retrieve the AUTOINCREMENT id value of it - const QString statement = QStringLiteral("SELECT * from Installations WHERE id = %1();") - .arg(lastInsertRowFunction()); - QSqlQuery query(database()); - query.prepare(statement); - result = runQuery(query); - if (result && query.next()) { - int indexField = query.record().indexOf(QStringLiteral("id")); - int nameField = query.record().indexOf(QStringLiteral("name")); - installation.setId(query.value(indexField).toInt()); - installation.setName(query.value(nameField).toString()); - Q_ASSERT(installation.id() > 0); - } else { - Q_ASSERT_X(false, Q_FUNC_INFO, - "database implementation error (SELECT)"); - } - } - if (result) { - // modify the created record to make sure event_id is unique - // within the installation: - QSqlQuery query(database()); - query.prepare(QStringLiteral("UPDATE Installations SET inst_id = :inst_id WHERE id = :id;")); - query.bindValue(QStringLiteral(":inst_id"), installation.id()); - query.bindValue(QStringLiteral(":id"), installation.id()); - result = runQuery(query); - Q_ASSERT_X(result, Q_FUNC_INFO, - "database implementation error (UPDATE)"); - Q_UNUSED(result); - } - - if (result) - transactor.commit(); - - return installation; -} - -Installation SqlStorage::getInstallation(int installationId) -{ - QSqlQuery query(database()); - query.prepare(QStringLiteral("SELECT * FROM Installations WHERE inst_id = :id;")); - query.bindValue(QStringLiteral(":id"), installationId); - - if (runQuery(query) && query.next()) { - Installation installation; - int idField = query.record().indexOf(QStringLiteral("inst_id")); - int nameField = query.record().indexOf(QStringLiteral("name")); - int userIdField = query.record().indexOf(QStringLiteral("user_id")); - installation.setId(query.value(idField).toInt()); - installation.setName(query.value(nameField).toString()); - installation.setUserId(query.value(userIdField).toInt()); - Q_ASSERT(installation.isValid()); - return installation; - } else { - return Installation(); - } -} - -bool SqlStorage::modifyInstallation(const Installation &installation) -{ - QSqlQuery query(database()); - query.prepare(QStringLiteral( - "UPDATE Installations SET name = :name, user_id = :user WHERE inst_id = :id;")); - query.bindValue(QStringLiteral(":name"), installation.name()); - query.bindValue(QStringLiteral(":user"), installation.userId()); - query.bindValue(QStringLiteral(":id"), installation.id()); - - return runQuery(query); -} - -bool SqlStorage::deleteInstallation(const Installation &installation) -{ - QSqlQuery query(database()); - query.prepare(QStringLiteral("DELETE from Installations WHERE inst_id = :id;")); - query.bindValue(QStringLiteral(":id"), installation.id()); - return runQuery(query); -} - bool SqlStorage::setMetaData(const QString &key, const QString &value) { SqlRaiiTransactor transactor(database()); diff --git a/Core/SqlStorage.h b/Core/SqlStorage.h index cd12b49b..a4eef4ad 100644 --- a/Core/SqlStorage.h +++ b/Core/SqlStorage.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm @@ -30,7 +30,6 @@ #include "User.h" #include "State.h" #include "Event.h" -#include "Installation.h" #include "CharmExceptions.h" class QSqlDatabase; @@ -54,21 +53,9 @@ class SqlStorage virtual QSqlDatabase &database() = 0; - // installation id table: - // get the id of this installation - virtual int installationId() const = 0; - // application: void stateChanged(State previous); - // installation id handling - Installation createInstallation(const QString &name); - - // create an installation id - Installation getInstallation(int installationId); - bool modifyInstallation(const Installation &); - bool deleteInstallation(const Installation &); - // user database functions: User getUser(int userid); User makeUser(const QString &name); diff --git a/Core/State.cpp b/Core/State.cpp index b301801e..ae1a6ef4 100644 --- a/Core/State.cpp +++ b/Core/State.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Core/State.h b/Core/State.h index 3ce50281..52b8bdb8 100644 --- a/Core/State.h +++ b/Core/State.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Core/Task.cpp b/Core/Task.cpp index c346feb6..c5acd053 100644 --- a/Core/Task.cpp +++ b/Core/Task.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Core/Task.h b/Core/Task.h index 97a217fe..f78ebb7c 100644 --- a/Core/Task.h +++ b/Core/Task.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Core/TaskListMerger.cpp b/Core/TaskListMerger.cpp index aea30abd..c03e1abd 100644 --- a/Core/TaskListMerger.cpp +++ b/Core/TaskListMerger.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Core/TaskListMerger.h b/Core/TaskListMerger.h index 53ea6aa9..0e19cc1f 100644 --- a/Core/TaskListMerger.h +++ b/Core/TaskListMerger.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Core/TaskModelInterface.h b/Core/TaskModelInterface.h index deee7f0e..668d7a98 100644 --- a/Core/TaskModelInterface.h +++ b/Core/TaskModelInterface.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Core/TaskTreeItem.cpp b/Core/TaskTreeItem.cpp index 98795a83..cfbd6414 100644 --- a/Core/TaskTreeItem.cpp +++ b/Core/TaskTreeItem.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Core/TaskTreeItem.h b/Core/TaskTreeItem.h index b80d22b3..f5791a70 100644 --- a/Core/TaskTreeItem.h +++ b/Core/TaskTreeItem.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Core/TimeSpans.cpp b/Core/TimeSpans.cpp index 3f71c843..ba0fb66e 100644 --- a/Core/TimeSpans.cpp +++ b/Core/TimeSpans.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Core/TimeSpans.h b/Core/TimeSpans.h index 57baacea..c39f193f 100644 --- a/Core/TimeSpans.h +++ b/Core/TimeSpans.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Core/UIStateInterface.h b/Core/UIStateInterface.h index 0b6592e1..30d99024 100644 --- a/Core/UIStateInterface.h +++ b/Core/UIStateInterface.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Core/User.h b/Core/User.h index 646243fc..121e669d 100644 --- a/Core/User.h +++ b/Core/User.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Core/XmlSerialization.cpp b/Core/XmlSerialization.cpp index f6545df5..52cb4f5c 100644 --- a/Core/XmlSerialization.cpp +++ b/Core/XmlSerialization.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Core/XmlSerialization.h b/Core/XmlSerialization.h index 2f8d31a9..48283f27 100644 --- a/Core/XmlSerialization.h +++ b/Core/XmlSerialization.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/ReadMe.markdown b/ReadMe.markdown deleted file mode 120000 index 3cefeef2..00000000 --- a/ReadMe.markdown +++ /dev/null @@ -1 +0,0 @@ -ReadMe.txt \ No newline at end of file diff --git a/ReadMe.txt b/ReadMe.md similarity index 93% rename from ReadMe.txt rename to ReadMe.md index dc4d7884..1dcb7fa4 100644 --- a/ReadMe.txt +++ b/ReadMe.md @@ -1,4 +1,4 @@ -Charm - the Cross-Platform Time Tracker +Charm - the Cross-Platform Time Tracker [![Windows Build status](https://ci.appveyor.com/api/projects/status/cxr8oijfuya778c8/branch/master?svg=true)](https://ci.appveyor.com/project/KDAB/charm/branch/master) ====================================== Whether you are a busy professional who needs to keep track time spent on projects or a student who wants to plan their studies: knowing how your diff --git a/Tests/BackendIntegrationTests.cpp b/Tests/BackendIntegrationTests.cpp index 3d340af1..3110ff4b 100644 --- a/Tests/BackendIntegrationTests.cpp +++ b/Tests/BackendIntegrationTests.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm @@ -51,7 +51,6 @@ void BackendIntegrationTests::initialValuesTest() QVERIFY(controller()->storage()->getAllTasks().isEmpty()); QVERIFY(controller()->storage()->getAllEvents().isEmpty()); QVERIFY(controller()->storage()->getUser(testUserId()).isValid()); - QVERIFY(controller()->storage()->getInstallation(testInstallationId()).isValid()); // model: QVERIFY(model()->taskTreeItem(0).childCount() == 0); } diff --git a/Tests/BackendIntegrationTests.h b/Tests/BackendIntegrationTests.h index bb09256b..80832f09 100644 --- a/Tests/BackendIntegrationTests.h +++ b/Tests/BackendIntegrationTests.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Tests/CharmDataModelTests.cpp b/Tests/CharmDataModelTests.cpp index 35946836..c94006ee 100644 --- a/Tests/CharmDataModelTests.cpp +++ b/Tests/CharmDataModelTests.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Tests/CharmDataModelTests.h b/Tests/CharmDataModelTests.h index 3517e096..b7c8ce61 100644 --- a/Tests/CharmDataModelTests.h +++ b/Tests/CharmDataModelTests.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Tests/ControllerTests.cpp b/Tests/ControllerTests.cpp index f3e25441..23720230 100644 --- a/Tests/ControllerTests.cpp +++ b/Tests/ControllerTests.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld @@ -81,15 +81,15 @@ void ControllerTests:: persistProvideMetaDataTest() Configuration configs[] = { Configuration(Configuration::TaskPrefilter_ShowAll, Configuration::TimeTrackerFont_Small, Configuration::Minutes, true, Qt::ToolButtonIconOnly, true, true, true, - false), + false, 5), Configuration(Configuration::TaskPrefilter_CurrentOnly, Configuration::TimeTrackerFont_Regular, Configuration::Minutes, false, Qt::ToolButtonTextOnly, false, false, false, - false), + false, 5), Configuration(Configuration::TaskPrefilter_SubscribedAndCurrentOnly, Configuration::TimeTrackerFont_Large, Configuration::Minutes, true, Qt::ToolButtonTextBesideIcon, true, true, true, - false), + false, 5), }; const int NumberOfConfigurations = sizeof configs / sizeof configs[0]; diff --git a/Tests/ControllerTests.h b/Tests/ControllerTests.h index 698ae27e..186adc1b 100644 --- a/Tests/ControllerTests.h +++ b/Tests/ControllerTests.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Tests/DatesTests.cpp b/Tests/DatesTests.cpp index df6b8d62..08174b14 100644 --- a/Tests/DatesTests.cpp +++ b/Tests/DatesTests.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2010-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2010-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld Author: Olivier JG diff --git a/Tests/DatesTests.h b/Tests/DatesTests.h index 317c5cca..a22937eb 100644 --- a/Tests/DatesTests.h +++ b/Tests/DatesTests.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2010-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2010-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld Author: Olivier JG diff --git a/Tests/EventModelFilterTests.cpp b/Tests/EventModelFilterTests.cpp index 8925ad6d..4f3c3610 100644 --- a/Tests/EventModelFilterTests.cpp +++ b/Tests/EventModelFilterTests.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2012-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2012-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Michel Boyer de la Giroday diff --git a/Tests/EventModelFilterTests.h b/Tests/EventModelFilterTests.h index 8299e2fc..f0f3e269 100644 --- a/Tests/EventModelFilterTests.h +++ b/Tests/EventModelFilterTests.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2012-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2012-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Michel Boyer de la Giroday diff --git a/Tests/ImportExportTests.cpp b/Tests/ImportExportTests.cpp index 09af531f..f9813e66 100644 --- a/Tests/ImportExportTests.cpp +++ b/Tests/ImportExportTests.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Tests/ImportExportTests.h b/Tests/ImportExportTests.h index 5a870d31..bb56f5d1 100644 --- a/Tests/ImportExportTests.h +++ b/Tests/ImportExportTests.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Tests/SmartNameCacheTests.cpp b/Tests/SmartNameCacheTests.cpp index 32aafb8b..1f0fdefc 100644 --- a/Tests/SmartNameCacheTests.cpp +++ b/Tests/SmartNameCacheTests.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2012-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2012-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Tests/SmartNameCacheTests.h b/Tests/SmartNameCacheTests.h index 1c395f96..cea84005 100644 --- a/Tests/SmartNameCacheTests.h +++ b/Tests/SmartNameCacheTests.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2012-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2012-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Tests/SqLiteStorageTests.cpp b/Tests/SqLiteStorageTests.cpp index c693041f..0127df36 100644 --- a/Tests/SqLiteStorageTests.cpp +++ b/Tests/SqLiteStorageTests.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm @@ -25,7 +25,6 @@ #include "Core/User.h" #include "Core/CharmConstants.h" -#include "Core/Installation.h" #include "Core/SqLiteStorage.h" #include @@ -67,41 +66,6 @@ void SqLiteStorageTests::connectAndCreateDatabaseTest() QVERIFY(result); } -void SqLiteStorageTests::makeModifyDeleteInstallationTest() -{ - int userId = 42; - // make two installation ids: - QString name1 = QStringLiteral("Installation-1"); - Installation installation1 = m_storage->createInstallation(name1); - installation1.setUserId(userId); - QVERIFY(installation1.isValid()); - QVERIFY(installation1.name() == name1); - QString name2 = QStringLiteral("Installation-2"); - Installation installation2 = m_storage->createInstallation(name2); - installation1.setUserId(userId); - QVERIFY(installation2.isValid()); - QVERIFY(installation2.name() == name2); - // modify installation 1: - QString newName = QStringLiteral("1-Installation"); - installation1.setName(newName); - QVERIFY(m_storage->modifyInstallation(installation1)); - - // verify installation 1 database entry: - Installation installation1_1 = m_storage->getInstallation(installation1.id()); - QVERIFY(installation1.id() == installation1_1.id()); - QVERIFY(installation1.userId() == installation1_1.userId()); - QVERIFY(installation1_1.name() == newName); - - // delete installation 1 - QVERIFY(m_storage->deleteInstallation(installation1)); - // verify installation 1 is gone - installation1 = m_storage->getInstallation(installation1.id()); - QVERIFY(!installation1.isValid()); - // verify installation 2 is still there - installation2 = m_storage->getInstallation(installation2.id()); - QVERIFY(installation2.isValid()); -} - void SqLiteStorageTests::makeModifyDeleteUserTest() { // make two user accounts diff --git a/Tests/SqLiteStorageTests.h b/Tests/SqLiteStorageTests.h index 10ef3dd9..2de6d3ba 100644 --- a/Tests/SqLiteStorageTests.h +++ b/Tests/SqLiteStorageTests.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm @@ -46,8 +46,6 @@ private Q_SLOTS: void connectAndCreateDatabaseTest(); - void makeModifyDeleteInstallationTest(); - void makeModifyDeleteUserTest(); void makeModifyDeleteTasksTest(); diff --git a/Tests/SqlTransactionTests.cpp b/Tests/SqlTransactionTests.cpp index b77c244b..1e50e01e 100644 --- a/Tests/SqlTransactionTests.cpp +++ b/Tests/SqlTransactionTests.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2010-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2010-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Tests/SqlTransactionTests.h b/Tests/SqlTransactionTests.h index e590d69e..832badda 100644 --- a/Tests/SqlTransactionTests.h +++ b/Tests/SqlTransactionTests.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2010-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2010-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Tests/TaskStructureTests.cpp b/Tests/TaskStructureTests.cpp index 7aefe5b5..80511482 100644 --- a/Tests/TaskStructureTests.cpp +++ b/Tests/TaskStructureTests.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Tests/TaskStructureTests.h b/Tests/TaskStructureTests.h index 13e4a57d..20313032 100644 --- a/Tests/TaskStructureTests.h +++ b/Tests/TaskStructureTests.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Tests/TestApplication.cpp b/Tests/TestApplication.cpp index 23b75a98..f4270a7f 100644 --- a/Tests/TestApplication.cpp +++ b/Tests/TestApplication.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2010-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2010-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Tests/TestApplication.h b/Tests/TestApplication.h index 040a0bca..b7d05c44 100644 --- a/Tests/TestApplication.h +++ b/Tests/TestApplication.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2010-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2010-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Tests/TestHelpers.h b/Tests/TestHelpers.h index 8866f351..cb2e151a 100644 --- a/Tests/TestHelpers.h +++ b/Tests/TestHelpers.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Tests/TimeSheetProcessorTests.cpp b/Tests/TimeSheetProcessorTests.cpp index 124444d9..4c286754 100644 --- a/Tests/TimeSheetProcessorTests.cpp +++ b/Tests/TimeSheetProcessorTests.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2015-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2015-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Franck Arrecot @@ -37,7 +37,7 @@ TimeSheetProcessorTests::TimeSheetProcessorTests() : m_idTimeSheet(0) , m_adminId(43) - , m_reportPath(":/timeSheetProcessorTest/Data/test-timesheet-report.charmreport") + , m_reportPath(QStringLiteral(":/timeSheetProcessorTest/Data/test-timesheet-report.charmreport")) { } @@ -60,16 +60,16 @@ void TimeSheetProcessorTests::testAddRemoveTimeSheet() QVERIFY(storage.database().open()); QSqlQuery query(storage.database()); - query.prepare( - "SELECT id, date_time_uploaded from timesheets where filename=:file AND userid=:user"); - query.bindValue("file", m_reportPath); - query.bindValue("user", m_adminId); + query.prepare(QStringLiteral( + "SELECT id, date_time_uploaded from timesheets where filename=:file AND userid=:user")); + query.bindValue(QStringLiteral("file"), m_reportPath); + query.bindValue(QStringLiteral("user"), m_adminId); QVERIFY(storage.runQuery(query)); QVERIFY(query.next()); QSqlRecord record = query.record(); - m_idTimeSheet = record.value(record.indexOf("id")).toInt(); - uint dateTimeUploaded = record.value(record.indexOf("date_time_uploaded")).toInt(); + m_idTimeSheet = record.value(record.indexOf(QStringLiteral("id"))).toInt(); + uint dateTimeUploaded = record.value(record.indexOf(QStringLiteral("date_time_uploaded"))).toInt(); uint nowTimeStamp = (QDateTime::currentMSecsSinceEpoch()/1000);// seconds since 1970-01-01 QVERIFY(m_idTimeSheet > 0); @@ -89,10 +89,10 @@ void TimeSheetProcessorTests::testAddRemoveTimeSheet() QVERIFY(storageRemove.database().open()); QSqlQuery queryRemove(storageRemove.database()); - queryRemove.prepare( - "SELECT id, date_time_uploaded from timesheets where filename=:file AND userid=:user"); - queryRemove.bindValue("file", m_reportPath); - queryRemove.bindValue("user", m_adminId); + queryRemove.prepare(QStringLiteral( + "SELECT id, date_time_uploaded from timesheets where filename=:file AND userid=:user")); + queryRemove.bindValue(QStringLiteral("file"), m_reportPath); + queryRemove.bindValue(QStringLiteral("user"), m_adminId); QVERIFY(storageRemove.runQuery(queryRemove)); QVERIFY(!queryRemove.next()); // not retrievable since it was deleted, must return false } diff --git a/Tests/TimeSheetProcessorTests.h b/Tests/TimeSheetProcessorTests.h index 6d2b02ff..e3fe4fed 100644 --- a/Tests/TimeSheetProcessorTests.h +++ b/Tests/TimeSheetProcessorTests.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2015-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2015-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Franck Arrecot @@ -33,7 +33,7 @@ class TimeSheetProcessorTests : public QObject public: explicit TimeSheetProcessorTests(); -private slots: +private Q_SLOTS: void testAddRemoveTimeSheet(); private: diff --git a/Tests/TimeSpanTests.cpp b/Tests/TimeSpanTests.cpp index eba7e5f4..1131c581 100644 --- a/Tests/TimeSpanTests.cpp +++ b/Tests/TimeSpanTests.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2012-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2012-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Tests/TimeSpanTests.h b/Tests/TimeSpanTests.h index 08eaa48c..ebb04612 100644 --- a/Tests/TimeSpanTests.h +++ b/Tests/TimeSpanTests.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2012-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2012-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Tests/UpdateCheckerTests.cpp b/Tests/UpdateCheckerTests.cpp index 34d032b1..896d24af 100644 --- a/Tests/UpdateCheckerTests.cpp +++ b/Tests/UpdateCheckerTests.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2010-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2010-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Tests/UpdateCheckerTests.h b/Tests/UpdateCheckerTests.h index 6263605b..eace22dc 100644 --- a/Tests/UpdateCheckerTests.h +++ b/Tests/UpdateCheckerTests.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2010-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2010-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Frank Osterfeld diff --git a/Tests/XmlSerializationTests.cpp b/Tests/XmlSerializationTests.cpp index 5f503490..5de34aa4 100644 --- a/Tests/XmlSerializationTests.cpp +++ b/Tests/XmlSerializationTests.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Frank Osterfeld diff --git a/Tests/XmlSerializationTests.h b/Tests/XmlSerializationTests.h index 26dbac41..d8f66823 100644 --- a/Tests/XmlSerializationTests.h +++ b/Tests/XmlSerializationTests.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2007-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2007-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Tools/Anonymizer/Anonymizer.cpp b/Tools/Anonymizer/Anonymizer.cpp index 3396da50..b3727a09 100644 --- a/Tools/Anonymizer/Anonymizer.cpp +++ b/Tools/Anonymizer/Anonymizer.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Tools/TimesheetGenerator/Exceptions.h b/Tools/TimesheetGenerator/Exceptions.h index 7036c02f..2e23e421 100644 --- a/Tools/TimesheetGenerator/Exceptions.h +++ b/Tools/TimesheetGenerator/Exceptions.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2009-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2009-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Tools/TimesheetGenerator/Options.cpp b/Tools/TimesheetGenerator/Options.cpp index eb88492f..e3b74989 100644 --- a/Tools/TimesheetGenerator/Options.cpp +++ b/Tools/TimesheetGenerator/Options.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2009-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2009-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm @@ -64,7 +64,7 @@ Options::Options(int argc, char **argv) case 'd': { const QString text = QString::fromLocal8Bit(optarg); - QDate date = QDate::fromString(text, "yyyy-MM-dd"); + QDate date = QDate::fromString(text, QStringLiteral("yyyy-MM-dd")); if (date.isValid()) { mDate = date; } else { diff --git a/Tools/TimesheetGenerator/Options.h b/Tools/TimesheetGenerator/Options.h index 7c418298..edeeef12 100644 --- a/Tools/TimesheetGenerator/Options.h +++ b/Tools/TimesheetGenerator/Options.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2009-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2009-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Tools/TimesheetGenerator/main.cpp b/Tools/TimesheetGenerator/main.cpp index f33a8416..9f3ad387 100644 --- a/Tools/TimesheetGenerator/main.cpp +++ b/Tools/TimesheetGenerator/main.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2009-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2009-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm @@ -64,7 +64,7 @@ int main(int argc, char **argv) for (QDomElement child = docElem.firstChildElement(timesheetTagName); !child.isNull(); child = child.nextSiblingElement(timesheetTagName)) { - const QString userIdString = child.attributes().namedItem("userid").nodeValue(); + const QString userIdString = child.attributes().namedItem(QStringLiteral("userid")).nodeValue(); bool ok; const int userId = userIdString.toInt(&ok); if (!ok) @@ -86,7 +86,7 @@ int main(int argc, char **argv) } } // now create the time sheet: - QDomDocument document = XmlSerialization::createXmlTemplate("weekly-timesheet"); + QDomDocument document = XmlSerialization::createXmlTemplate(QStringLiteral("weekly-timesheet")); // find metadata and report element: QDomElement root = document.documentElement(); @@ -101,12 +101,12 @@ int main(int argc, char **argv) const int week = start.date().weekNumber(&year); { - QDomElement yearElement = document.createElement("year"); + QDomElement yearElement = document.createElement(QStringLiteral("year")); metadata.appendChild(yearElement); QDomText text = document.createTextNode(QString::number(year)); yearElement.appendChild(text); - QDomElement weekElement = document.createElement("serial-number"); - weekElement.setAttribute("semantics", "week-number"); + QDomElement weekElement = document.createElement(QStringLiteral("serial-number")); + weekElement.setAttribute(QStringLiteral("semantics"), QStringLiteral("week-number")); metadata.appendChild(weekElement); QDomText weektext = document.createTextNode(QString::number(week)); weekElement.appendChild(weektext); @@ -114,7 +114,7 @@ int main(int argc, char **argv) { // effort // make effort element: - QDomElement effort = document.createElement("effort"); + QDomElement effort = document.createElement(QStringLiteral("effort")); report.appendChild(effort); // create elements: Q_FOREACH (Event event, events) { diff --git a/Tools/TimesheetProcessor/CommandLine.cpp b/Tools/TimesheetProcessor/CommandLine.cpp index fbab0c84..53ebbf58 100644 --- a/Tools/TimesheetProcessor/CommandLine.cpp +++ b/Tools/TimesheetProcessor/CommandLine.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm @@ -175,7 +175,7 @@ CommandLine::CommandLine(int argc, char **argv) QString msg; for (int index = optind; index < argc; index++) { msg += QObject::tr("Unknown extra argument \"%1\"\n").arg( - argv[index]); + QString::fromLatin1(argv[index])); } throw UsageException(msg); } diff --git a/Tools/TimesheetProcessor/CommandLine.h b/Tools/TimesheetProcessor/CommandLine.h index 54d6ec94..df6c40ff 100644 --- a/Tools/TimesheetProcessor/CommandLine.h +++ b/Tools/TimesheetProcessor/CommandLine.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Tools/TimesheetProcessor/Database.cpp b/Tools/TimesheetProcessor/Database.cpp index 6b6a5334..05e16cbd 100644 --- a/Tools/TimesheetProcessor/Database.cpp +++ b/Tools/TimesheetProcessor/Database.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm @@ -49,30 +49,29 @@ void Database::checkUserid(int id) throw (TimesheetProcessorException) { User user = m_storage.getUser(id); if (!user.isValid()) - throw TimesheetProcessorException("No such user"); + throw TimesheetProcessorException(QStringLiteral("No such user")); } User Database::getOrCreateUserByName(QString name) throw (TimesheetProcessorException) { User user; QSqlQuery query(database()); - const char *statement = "SELECT user_id from Users WHERE name = :user_name;"; - query.prepare(statement); - query.bindValue(":user_name", name); + query.prepare(QStringLiteral("SELECT user_id from Users WHERE name = :user_name;")); + query.bindValue(QStringLiteral(":user_name"), name); bool result = query.exec(); if (result) { if (query.next()) { - int userIdPosition = query.record().indexOf("user_id"); + int userIdPosition = query.record().indexOf(QStringLiteral("user_id")); Q_ASSERT(userIdPosition != -1); int userId = query.value(userIdPosition).toInt(); user = m_storage.getUser(userId); } else { // user with this name does not exist: user = m_storage.makeUser(name); // that should work if (!user.isValid()) - throw TimesheetProcessorException("Cannot create the new user"); + throw TimesheetProcessorException(QStringLiteral("Cannot create the new user")); } } else { - throw TimesheetProcessorException("Cannot execute query for user name"); + throw TimesheetProcessorException(QStringLiteral("Cannot execute query for user name")); } return user; } @@ -128,12 +127,12 @@ void Database::initializeDatabase() throw (TimesheetProcessorException) try { QStringList tables = m_storage.database().tables(); if (!tables.empty()) { - throw TimesheetProcessorException("The database is not empty. Only " - "empty databases can be automatically initialized."); + throw TimesheetProcessorException(QStringLiteral("The database is not empty. Only " + "empty databases can be automatically initialized.")); } if (!m_storage.createDatabaseTables()) - throw TimesheetProcessorException( - "Cannot create database contents, please double-check permissions."); + throw TimesheetProcessorException(QStringLiteral( + "Cannot create database contents, please double-check permissions.")); } catch (UnsupportedDatabaseVersionException &e) { throw TimesheetProcessorException(e.what()); } @@ -146,7 +145,7 @@ void Database::addEvent(const Event &event, const SqlRaiiTransactor &t) newEvent = event; newEvent.setId(id); if (!m_storage.modifyEvent(newEvent, t)) - throw TimesheetProcessorException("Cannot add event"); + throw TimesheetProcessorException(QStringLiteral("Cannot add event")); } void Database::deleteEventsForReport(int userid, int index) @@ -156,9 +155,9 @@ void Database::deleteEventsForReport(int userid, int index) "DELETE FROM Events WHERE report_id = :index and user_id = :userid"); QSqlQuery query(m_storage.database()); query.prepare(statement); - query.bindValue(":index", index); - query.bindValue(":userid", userid); + query.bindValue(QStringLiteral(":index"), index); + query.bindValue(QStringLiteral(":userid"), userid); bool result = query.exec(); if (!result) - throw TimesheetProcessorException("Failed to delete report"); + throw TimesheetProcessorException(QStringLiteral("Failed to delete report")); } diff --git a/Tools/TimesheetProcessor/Database.h b/Tools/TimesheetProcessor/Database.h index a31b414b..03eed26b 100644 --- a/Tools/TimesheetProcessor/Database.h +++ b/Tools/TimesheetProcessor/Database.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Tools/TimesheetProcessor/Exceptions.h b/Tools/TimesheetProcessor/Exceptions.h index 67054b8b..d1d464b4 100644 --- a/Tools/TimesheetProcessor/Exceptions.h +++ b/Tools/TimesheetProcessor/Exceptions.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Tools/TimesheetProcessor/Operations.cpp b/Tools/TimesheetProcessor/Operations.cpp index 6bf9689a..4259c93c 100644 --- a/Tools/TimesheetProcessor/Operations.cpp +++ b/Tools/TimesheetProcessor/Operations.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm Author: Sebastian Sauer @@ -81,7 +81,7 @@ void addTimesheet(const CommandLine &cmd) QString msg = QObject::tr("Cannot open file %1 for reading.").arg(cmd.filename()); throw TimesheetProcessorException(msg); } - QDomDocument doc("timesheet"); + QDomDocument doc(QStringLiteral("timesheet")); if (!doc.setContent(&file)) { QString msg = QObject::tr("Cannot read file %1.").arg(cmd.filename()); throw TimesheetProcessorException(msg); @@ -89,14 +89,14 @@ void addTimesheet(const CommandLine &cmd) // add it to the database: // 1) make a list of all the events: EventList events; - QDomElement charmReportElement = doc.firstChildElement("charmreport"); - QDomElement metadataElement = charmReportElement.firstChildElement("metadata"); - QDomElement yearElement = metadataElement.firstChildElement("year"); + QDomElement charmReportElement = doc.firstChildElement(QStringLiteral("charmreport")); + QDomElement metadataElement = charmReportElement.firstChildElement(QStringLiteral("metadata")); + QDomElement yearElement = metadataElement.firstChildElement(QStringLiteral("year")); QString year = yearElement.text().simplified(); - QDomElement weekElement = metadataElement.firstChildElement("serial-number"); + QDomElement weekElement = metadataElement.firstChildElement(QStringLiteral("serial-number")); QString week = weekElement.text().simplified(); - QDomElement reportElement = charmReportElement.firstChildElement("report"); - QDomElement effortElement = reportElement.firstChildElement("effort"); + QDomElement reportElement = charmReportElement.firstChildElement(QStringLiteral("report")); + QDomElement effortElement = reportElement.firstChildElement(QStringLiteral("effort")); if (effortElement.isNull()) { QString msg = QObject::tr("Invalid structure in file %1.").arg(cmd.filename()); throw TimesheetProcessorException(msg); @@ -133,14 +133,14 @@ void addTimesheet(const CommandLine &cmd) // add time sheet to time sheets list { QSqlQuery query(database.database()); - query.prepare( - "INSERT into timesheets VALUES( 0, :filename, :original_filename, :year, :week, :total, :userid, 0, :date_time_uploaded)"); + query.prepare(QStringLiteral( + "INSERT into timesheets VALUES( 0, :filename, :original_filename, :year, :week, :total, :userid, 0, :date_time_uploaded)")); query.bindValue(QString::fromLatin1(":filename"), cmd.filename()); query.bindValue(QString::fromLatin1(":original_filename"), cmd.userComment()); query.bindValue(QString::fromLatin1(":year"), year); query.bindValue(QString::fromLatin1(":week"), week); query.bindValue(QString::fromLatin1(":total"), totalSeconds); - query.bindValue(":userid", cmd.userid()); + query.bindValue(QString::fromLatin1(":userid"), cmd.userid()); query.bindValue(QString::fromLatin1(":date_time_uploaded"), dateTimeUploaded); if (!query.exec()) { QString msg = QObject::tr("Error adding time sheet %1.").arg(cmd.filename()); @@ -151,14 +151,14 @@ void addTimesheet(const CommandLine &cmd) // retrieve index { QSqlQuery query(database.database()); - if (!query.exec("SELECT id from timesheets WHERE id = last_insert_id()")) { + if (!query.exec(QStringLiteral("SELECT id from timesheets WHERE id = last_insert_id()"))) { QString msg = QObject::tr("SQL error retrieving index for time sheet %1.").arg( cmd.filename()); throw TimesheetProcessorException(msg); } if (query.next()) { - const int idField = query.record().indexOf("id"); + const int idField = query.record().indexOf(QStringLiteral("id")); index = query.value(idField).toInt(); } else { QString msg = QObject::tr("Error retrieving index for time sheet %1.").arg( @@ -198,10 +198,10 @@ void addTimesheet(const CommandLine &cmd) // the transction should be rollback() and there should be no item with id=index in the // Charm/timesheets table any longer... QSqlQuery query(database.database()); - if (query.exec(QString("SELECT id from timesheets WHERE id = %1").arg(index))) { + if (query.exec(QStringLiteral("SELECT id from timesheets WHERE id = %1").arg(index))) { if (query.next()) { //WTF, if that happens that something went wrong with the transaction QSqlQuery deletequery(database.database()); - deletequery.exec(QString("DELETE FROM timesheets WHERE id = %1").arg(index)); + deletequery.exec(QStringLiteral("DELETE FROM timesheets WHERE id = %1").arg(index)); qDebug() << "CRITICAL ERROR: A database transaction did not roll back as expected. " "Please report this to the administrators. The time sheet with index " @@ -225,7 +225,7 @@ void removeTimesheet(const CommandLine &cmd) { QSqlQuery query(database.database()); - if (!query.prepare("DELETE from timesheets WHERE id = :index")) { + if (!query.prepare(QStringLiteral("DELETE from timesheets WHERE id = :index"))) { QString msg = QObject::tr("Error prepare to remove timesheet %1.").arg(cmd.index()); throw TimesheetProcessorException(msg); } diff --git a/Tools/TimesheetProcessor/Operations.h b/Tools/TimesheetProcessor/Operations.h index 783aa6bc..4d503b31 100644 --- a/Tools/TimesheetProcessor/Operations.h +++ b/Tools/TimesheetProcessor/Operations.h @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/Tools/TimesheetProcessor/main.cpp b/Tools/TimesheetProcessor/main.cpp index 6b05a93b..90d92f87 100644 --- a/Tools/TimesheetProcessor/main.cpp +++ b/Tools/TimesheetProcessor/main.cpp @@ -3,7 +3,7 @@ This file is part of Charm, a task-based time tracking application. - Copyright (C) 2008-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com + Copyright (C) 2008-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Mirko Boehm diff --git a/appveyor.ini b/appveyor.ini new file mode 100644 index 00000000..fd541300 --- /dev/null +++ b/appveyor.ini @@ -0,0 +1,65 @@ +[General] +Branch = master +ShallowClone = True +Command = craft + +# Variables defined here override the default value +# The variable names are casesensitive +[Variables] +#Root = D:\qt-sdk + +#Values need to be overwritten to create a cache +UseCache = True +CreateCache = True +Msys = C:\msys64\ +APPVEYOR_BUILD_FOLDER = ${Variables:Root} + + +# Settings applicable for all Crafts matrices +# Settings are Category/key=value +# Category is case sensitive +[GeneralSettings] +General/EMERGE_PKGDSTDIR=${Variables:APPVEYOR_BUILD_FOLDER}/binaries +Paths/python = C:\Python36 +Paths/python27 = C:\Python27 +Paths/Msys = ${Variables:Msys} +Paths/DownloadDir = ${Variables:Root}/downloads +ShortPath/Enabled = False +ShortPath/EnableJunctions = True +ShortPath/JunctionDir = ${Variables:Root}/csp +Packager/UseCache = ${Variables:UseCache} +Packager/CreateCache = ${Variables:CreateCache} +Packager/CacheDir = ${Variables:APPVEYOR_BUILD_FOLDER}/cache +Packager/RepositoryUrl = http://downloads.kdab.com/ci/cache/gammaray/cache +ContinuousIntegration/RepositoryUrl = http://downloads.kdab.com/ci/cache/gammaray/binary +ContinuousIntegration/UpdateRepository = True +Compile/BuildType = Release +ContinuousIntegration/Enabled=True +QtSDK/Version=5.10.1 +QtSDK/Path=C:\Qt +QtSDK/Enabled=True +Blueprints/BlueprintRoot = ${Variables:Root}/blueprints + +[BlueprintSettings] +/.buildTests = False + +qt-apps/gammaray.version = master +qt-apps/charm.version = master + +libs/openssl.version = 1.0.2o + +libs/icu.ignored = True +binary/mysql.ignored = True +libs/dbus.ignored = True + +[windows-msvc2015_32-cl] +QtSDK/Compiler = msvc2015 +General/ABI = windows-msvc2015_32-cl + +[windows-mingw_32-gcc] +QtSDK/Compiler = mingw53_32 +General/ABI = windows-mingw_32-gcc + +[windows-msvc2017_64-cl] +QtSDK/Compiler = msvc2017_64 +General/ABI = windows-msvc2017_64-cl diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 00000000..95115399 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,52 @@ +version: '{build}-{branch}' + +branches: + # whitelist + only: + - master + +# don't enable for charm +#clone_depth: 50 + + +init: +- ps: | + function craft() { + & "C:\python36\python.exe" "C:\CraftMaster\CraftMaster\CraftMaster.py" --config "$env:APPVEYOR_BUILD_FOLDER\appveyor.ini" --variables "APPVEYOR_BUILD_FOLDER=$env:APPVEYOR_BUILD_FOLDER" --target $env:TARGET -c $args + if($LASTEXITCODE -ne 0) {exit $LASTEXITCODE} + } + +install: +- ps: | + #use cmd to silence powershell behaviour for stderr + & cmd /C "git clone -q --depth=1 git://anongit.kde.org/craftmaster.git C:\CraftMaster\CraftMaster 2>&1" + craft craft + craft nsis + craft --install-deps charm + +build_script: +- ps: | + craft --no-cache --src-dir $env:APPVEYOR_BUILD_FOLDER charm + +after_build: +- ps: | + craft --no-cache --src-dir $env:APPVEYOR_BUILD_FOLDER --package charm + +test_script: +- ps: | + craft --no-cache --src-dir $env:APPVEYOR_BUILD_FOLDER --test charm + +environment: + matrix: + - TARGET: windows-msvc2015_32-cl + - TARGET: windows-mingw_32-gcc + - TARGET: windows-msvc2017_64-cl + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + +artifacts: + - path: cache\**\.* + - path: binaries\* + +deploy: + - provider: Environment + name: GammaRay diff --git a/charmtimetracker.spec b/charmtimetracker.spec index 1d2abed4..1e1a7aa1 100644 --- a/charmtimetracker.spec +++ b/charmtimetracker.spec @@ -41,6 +41,8 @@ Authors: -------- Mirko Boehm +%define debug_package %{nil} +%global __debug_install_post %{nil} %prep %setup -T -c %{__tar} -zxf %{SOURCE0} --strip-components=1 @@ -67,9 +69,9 @@ cmake . -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release -DCharm_VERSION=% %{_prefix}/bin/charmtimetracker %changelog -* Wed Nov 01 2016 Steffen Hansen 1.11.4 +* Tue Nov 01 2016 Steffen Hansen 1.11.4 - 1.11.4 release -* Wed Nov 01 2016 Steffen Hansen 1.11.3 +* Tue Nov 01 2016 Steffen Hansen 1.11.3 - 1.11.3 release * Sat Apr 30 2016 Allen Winter 1.11.1 - 1.11.1 release diff --git a/cmake/ECM/kde-modules/KDECMakeSettings.cmake b/cmake/ECM/kde-modules/KDECMakeSettings.cmake index 523271a1..ac1212cc 100644 --- a/cmake/ECM/kde-modules/KDECMakeSettings.cmake +++ b/cmake/ECM/kde-modules/KDECMakeSettings.cmake @@ -15,10 +15,11 @@ # # The default runtime path (used on Unix systems to search for # dynamically-linked libraries) is set to include the location that libraries -# will be installed to (as set in LIB_INSTALL_DIR), and also the linker search -# path. +# will be installed to (as set in LIB_INSTALL_DIR or, if the former is not set, +# KDE_INSTALL_LIBDIR), and also the linker search path. # -# Note that ``LIB_INSTALL_DIR`` needs to be set before including this module. +# Note that ``LIB_INSTALL_DIR`` or alternatively ``KDE_INSTALL_LIBDIR`` needs +# to be set before including this module. # Typically, this is done by including the :kde-module:`KDEInstallDirs` module. # # This section can be disabled by setting ``KDE_SKIP_RPATH_SETTINGS`` to TRUE @@ -63,13 +64,26 @@ # warnings on Qt-related code. # # If clang is not being used, this won't have an effect. -# See https://quickgit.kde.org/?p=clazy.git&a=blob&f=README&o=plain +# See https://commits.kde.org/clazy?path=README.md # # Since 5.17.0 # # - Uninstall target functionality since 1.7.0. # - ``APPLE_FORCE_X11`` option since 5.14.0 (detecting X11 was previously the default behavior) # - ``APPLE_SUPPRESS_X11_WARNING`` option since 5.14.0 +# +# Translations +# ~~~~~~~~~~~~ +# A fetch-translations target will be set up that will download translations +# for projects using l10n.kde.org. +# +# ``KDE_L10N_BRANCH`` will be responsible for choosing which l10n branch to use +# for the translations. +# +# ``KDE_L10N_AUTO_TRANSLATIONS`` (OFF by default) will indicate whether translations +# should be downloaded when building the project. +# +# Since 5.34.0 #============================================================================= # Copyright 2014 Alex Merry @@ -109,11 +123,17 @@ if(NOT KDE_SKIP_RPATH_SETTINGS) # Set the default RPATH to point to useful locations, namely where the # libraries will be installed and the linker search path + # First look for the old LIB_INSTALL_DIR, then fallback to newer KDE_INSTALL_LIBDIR if(NOT LIB_INSTALL_DIR) - message(FATAL_ERROR "LIB_INSTALL_DIR not set. This is necessary for using the RPATH settings.") + if(NOT KDE_INSTALL_LIBDIR) + message(FATAL_ERROR "Neither KDE_INSTALL_LIBDIR nor LIB_INSTALL_DIR is set. Setting one is necessary for using the RPATH settings.") + else() + set(_abs_LIB_INSTALL_DIR "${KDE_INSTALL_LIBDIR}") + endif() + else() + set(_abs_LIB_INSTALL_DIR "${LIB_INSTALL_DIR}") endif() - set(_abs_LIB_INSTALL_DIR "${LIB_INSTALL_DIR}") if (NOT IS_ABSOLUTE "${_abs_LIB_INSTALL_DIR}") set(_abs_LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}") endif() @@ -144,9 +164,9 @@ endif() find_program(APPSTREAMCLI appstreamcli) function(appstreamtest) - if(APPSTREAMCLI AND NOT _done) - set(_done TRUE) - add_test(NAME appstreamtest COMMAND cmake -DAPPSTREAMCLI=${APPSTREAMCLI} -DINSTALL_FILES=${CMAKE_BINARY_DIR}/install_manifest.txt -P ${CMAKE_CURRENT_LIST_DIR}/appstreamtest.cmake) + if(APPSTREAMCLI AND NOT appstreamtest_added) + set(appstreamtest_added TRUE PARENT_SCOPE) + add_test(NAME appstreamtest COMMAND ${CMAKE_COMMAND} -DAPPSTREAMCLI=${APPSTREAMCLI} -DINSTALL_FILES=${CMAKE_BINARY_DIR}/install_manifest.txt -P ${CMAKE_CURRENT_LIST_DIR}/appstreamtest.cmake) else() message(STATUS "Could not set up the appstream test. appstreamcli is missing.") endif() @@ -230,22 +250,23 @@ if(NOT KDE_SKIP_BUILD_SETTINGS) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") endif() - # Disable detection of X11 and related package on OS X because when using - # brew or macports, X11 can be installed and thus is detected. - option(APPLE_FORCE_X11 "Force enable X11 related detection on OS X" OFF) - option(APPLE_SUPPRESS_X11_WARNING "Suppress X11 and related technologies search disabling warning on OS X" OFF) - - if(APPLE AND NOT APPLE_FORCE_X11) - if (NOT APPLE_SUPPRESS_X11_WARNING) - message(WARNING "Searching for X11 and related technologies is disabled on Apple systems. Set APPLE_FORCE_X11 to ON to change this behaviour. Set APPLE_SUPPRESS_X11_WARNING to ON to hide this warning.") - endif() - - set(CMAKE_DISABLE_FIND_PACKAGE_X11 true) - set(CMAKE_DISABLE_FIND_PACKAGE_XCB true) - set(CMAKE_DISABLE_FIND_PACKAGE_Qt5X11Extras true) - endif() + if (APPLE) + # Disable detection of X11 and related package on OS X because when using + # brew or macports, X11 can be installed and thus is detected. + option(APPLE_FORCE_X11 "Force enable X11 related detection on OS X" OFF) + option(APPLE_SUPPRESS_X11_WARNING "Suppress X11 and related technologies search disabling warning on OS X" OFF) + + if(NOT APPLE_FORCE_X11) + if (NOT APPLE_SUPPRESS_X11_WARNING) + message(WARNING "Searching for X11 and related technologies is disabled on Apple systems. Set APPLE_FORCE_X11 to ON to change this behaviour. Set APPLE_SUPPRESS_X11_WARNING to ON to hide this warning.") + endif() + set(CMAKE_DISABLE_FIND_PACKAGE_X11 true) + set(CMAKE_DISABLE_FIND_PACKAGE_XCB true) + set(CMAKE_DISABLE_FIND_PACKAGE_Qt5X11Extras true) + endif() + endif() - option(KDE_SKIP_UNINSTALL_TARGET "Prevent an \"uninstall\" target from being generated." OFF) + option(KDE_SKIP_UNINSTALL_TARGET "Prevent an \"uninstall\" target from being generated." OFF) if(NOT KDE_SKIP_UNINSTALL_TARGET) include("${ECM_MODULE_DIR}/ECMUninstallTarget.cmake") endif() @@ -256,8 +277,68 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") option(ENABLE_CLAZY "Enable Clazy warnings" OFF) if(ENABLE_CLAZY) - set(CMAKE_CXX_COMPILE_OBJECT "${CMAKE_CXX_COMPILE_OBJECT} -Xclang -load -Xclang ClangLazy.so -Xclang -add-plugin -Xclang clang-lazy") + set(CMAKE_CXX_COMPILE_OBJECT "${CMAKE_CXX_COMPILE_OBJECT} -Xclang -load -Xclang ClangLazy${CMAKE_SHARED_LIBRARY_SUFFIX} -Xclang -add-plugin -Xclang clang-lazy") endif() endif() ################################################################### +# Download translations + +function(_repository_name reponame dir) + execute_process(COMMAND git config --get remote.origin.url + OUTPUT_VARIABLE giturl + RESULT_VARIABLE exitCode + WORKING_DIRECTORY "${dir}") + + if(exitCode EQUAL 0) + string(REGEX MATCHALL ".+[:\\/]([-A-Za-z\\d]+)(.git)?\\s*" "" ${giturl}) + set(${reponame} ${CMAKE_MATCH_1}) + endif() + + if(NOT ${reponame}) + set(${reponame} ${CMAKE_PROJECT_NAME}) + endif() + set(${reponame} ${${reponame}} PARENT_SCOPE) +endfunction() + +if(NOT EXISTS ${CMAKE_SOURCE_DIR}/po AND NOT TARGET fetch-translations) + option(KDE_L10N_AUTO_TRANSLATIONS "Automatically 'make fetch-translations`" OFF) + set(KDE_L10N_BRANCH "trunk" CACHE STRING "Branch from l10n.kde.org to fetch from: trunk | stable | lts | trunk_kde4 | stable_kde4") + + if(KDE_L10N_AUTO_TRANSLATIONS) + set(_EXTRA_ARGS "ALL") + else() + set(_EXTRA_ARGS) + endif() + + set(_reponame "") + _repository_name(_reponame "${CMAKE_SOURCE_DIR}") + + add_custom_command( + OUTPUT "${CMAKE_BINARY_DIR}/releaseme" + COMMAND git clone --depth 1 "https://anongit.kde.org/releaseme.git" + COMMENT "Fetching releaseme scripts to download translations..." + ) + + set(_l10n_po_dir "${CMAKE_BINARY_DIR}/po") + set(_l10n_poqm_dir "${CMAKE_BINARY_DIR}/poqm") + + if(CMAKE_VERSION VERSION_GREATER 3.2) + set(extra BYPRODUCTS ${_l10n_po_dir} ${_l10n_poqm_dir}) + endif() + + add_custom_target(fetch-translations ${_EXTRA_ARGS} + COMMENT "Downloading translations for ${_reponame} branch ${KDE_L10N_BRANCH}..." + COMMAND git -C "${CMAKE_BINARY_DIR}/releaseme" pull + COMMAND cmake -E remove_directory ${_l10n_po_dir} + COMMAND cmake -E remove_directory ${_l10n_poqm_dir} + COMMAND ruby "${CMAKE_BINARY_DIR}/releaseme/fetchpo.rb" + --origin ${KDE_L10N_BRANCH} + --project "${_reponame}" + --output-dir "${_l10n_po_dir}" + --output-poqm-dir "${_l10n_poqm_dir}" + "${CMAKE_CURRENT_SOURCE_DIR}" + ${extra} + DEPENDS "${CMAKE_BINARY_DIR}/releaseme" + ) +endif() diff --git a/cmake/ECM/kde-modules/KDECompilerSettings.cmake b/cmake/ECM/kde-modules/KDECompilerSettings.cmake index dfa29f7e..ae5b50b4 100644 --- a/cmake/ECM/kde-modules/KDECompilerSettings.cmake +++ b/cmake/ECM/kde-modules/KDECompilerSettings.cmake @@ -100,7 +100,7 @@ elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") else() _kde_compiler_min_version("4.5") endif() -elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") +elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") _kde_compiler_min_version("3.1") else() message(WARNING "${CMAKE_CXX_COMPILER_ID} is not a supported C++ compiler.") @@ -120,8 +120,8 @@ macro (_KDE_ADD_PLATFORM_DEFINITIONS) set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} ${ARGV}) endmacro() -include(CheckSymbolExists) -check_symbol_exists("__GLIBC__" "stdlib.h" LIBC_IS_GLIBC) +include(CheckCXXSymbolExists) +check_cxx_symbol_exists("__GLIBC__" "stdlib.h" LIBC_IS_GLIBC) if (LIBC_IS_GLIBC) # Enable everything in GNU libc. Any code using non-portable features # needs to perform feature tests, but this ensures that any such features @@ -189,12 +189,12 @@ endif() # Pick sensible versions of the C and C++ standards. # Note that MSVC does not have equivalent flags; the features are either # supported or they are not. -if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") +if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") # We use the C89 standard because that is what is common to all our # compilers (in particular, MSVC 2010 does not support C99) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=iso9899:1990") endif() -if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") +if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Intel" AND NOT WIN32) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") @@ -206,11 +206,19 @@ endif() # See https://www.ibm.com/developerworks/community/blogs/zTPF/entry/benefits_of_the_fnocommon_compile_option_peter_lemieszewski?lang=en # Note that this only applies to C code; C++ already behaves like this. if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR - CMAKE_C_COMPILER_ID STREQUAL "Clang" OR + CMAKE_C_COMPILER_ID MATCHES "Clang" OR (CMAKE_C_COMPILER_ID STREQUAL "Intel" AND NOT WIN32)) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-common") endif() +# Do not treat the operator name keywords and, bitand, bitor, compl, not, or and xor as synonyms as keywords. +# They're not supported under Visual Studio out of the box thus using them limits the portability of code +if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR + CMAKE_C_COMPILER_ID MATCHES "Clang" OR + (CMAKE_C_COMPILER_ID STREQUAL "Intel" AND NOT WIN32)) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-operator-names") +endif() + # Default to hidden visibility for symbols set(CMAKE_C_VISIBILITY_PRESET hidden) set(CMAKE_CXX_VISIBILITY_PRESET hidden) @@ -221,7 +229,7 @@ if (POLICY CMP0063) cmake_policy(SET CMP0063 NEW) endif() -if (UNIX AND NOT APPLE) +if (UNIX AND NOT APPLE AND NOT CYGWIN) # Enable adding DT_RUNPATH, which means that LD_LIBRARY_PATH takes precedence # over the built-in rPath set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--enable-new-dtags ${CMAKE_SHARED_LINKER_FLAGS}") @@ -255,7 +263,7 @@ endif() # Turn off exceptions by default if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions") -elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") +elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions") elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Intel" AND NOT WIN32) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions") @@ -277,7 +285,7 @@ macro(_kdecompilersettings_append_exception_flag VAR) endif() elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") set(${VAR} "${${VAR}} -fexceptions") - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(${VAR} "${${VAR}} -fexceptions") endif() string(STRIP "${${VAR}}" ${VAR}) @@ -306,7 +314,7 @@ function(KDE_TARGET_ENABLE_EXCEPTIONS target mode) target_compile_options(${target} ${mode} "$<$:-fexceptions>") endif() target_compile_options(${target} ${mode} - "$<$,$>:-fexceptions>") + "$<$,$,$>:-fexceptions>") endfunction() function(KDE_ENABLE_EXCEPTIONS) @@ -332,7 +340,7 @@ endfunction() # Better diagnostics (warnings, errors) ############################################################ -if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR +if ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT APPLE) OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT APPLE) OR (CMAKE_CXX_COMPILER_ID STREQUAL "Intel" AND NOT WIN32)) # Linker warnings should be treated as errors @@ -345,16 +353,36 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR endif() set(_KDE_GCC_COMMON_WARNING_FLAGS "-Wall -Wextra -Wcast-align -Wchar-subscripts -Wformat-security -Wno-long-long -Wpointer-arith -Wundef") -if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + # -Wgnu-zero-variadic-macro-arguments (part of -pedantic) is triggered by every qCDebug() call and therefore results + # in a lot of noise. This warning is only notifying us that clang is emulating the GCC behaviour + # instead of the exact standard wording so we can safely ignore it + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-gnu-zero-variadic-macro-arguments") +endif() +if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_KDE_GCC_COMMON_WARNING_FLAGS} -Wmissing-format-attribute -Wwrite-strings") # Make some warnings errors set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=implicit-function-declaration") endif() -if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${_KDE_GCC_COMMON_WARNING_FLAGS} -Wnon-virtual-dtor -Woverloaded-virtual") # Make some warnings errors set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=return-type") endif() +if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR + (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5)) + # -Wvla: use of variable-length arrays (an extension to C++) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wvla") +endif() +if ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0) OR + (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5)) + include(CheckCXXCompilerFlag) + check_cxx_compiler_flag(-Wdate-time HAVE_DATE_TIME) + if (HAVE_DATE_TIME) + # -Wdate-time: warn if we use __DATE__ or __TIME__ (we want to be able to reproduce the exact same binary) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wdate-time") + endif() +endif() # -w1 turns on warnings and errors # FIXME: someone needs to have a closer look at the Intel compiler options @@ -458,5 +486,13 @@ if (MINGW AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--export-all-symbols") endif() +if (CMAKE_GENERATOR STREQUAL "Ninja" AND + ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) OR + (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5))) + # Force colored warnings in Ninja's output, if the compiler has -fdiagnostics-color support. + # Rationale in https://github.com/ninja-build/ninja/issues/814 + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=always") +endif() + include("${ECM_MODULE_DIR}/ECMEnableSanitizers.cmake") include("${ECM_MODULE_DIR}/ECMCoverageOption.cmake") diff --git a/cmake/ECM/kde-modules/KDEFrameworkCompilerSettings.cmake b/cmake/ECM/kde-modules/KDEFrameworkCompilerSettings.cmake index 038ddc3b..7d30ec66 100644 --- a/cmake/ECM/kde-modules/KDEFrameworkCompilerSettings.cmake +++ b/cmake/ECM/kde-modules/KDEFrameworkCompilerSettings.cmake @@ -61,11 +61,12 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug") add_definitions(-DQT_STRICT_ITERATORS) endif() -if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") +if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic") -elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - # -Wgnu-zero-variadic-macro-arguments is triggered by every qCDebug() call and therefore results - # in a lot of noise. This warning is only notifying us that clang is emulating the GCC behaviour - # instead of the exact standard wording so we can safely ignore it - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic -Wno-gnu-zero-variadic-macro-arguments") +endif() + +if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.0.0") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsuggest-override" ) + endif() endif() diff --git a/cmake/ECM/kde-modules/KDEInstallDirs.cmake b/cmake/ECM/kde-modules/KDEInstallDirs.cmake index 7f5e4477..cd004dd3 100644 --- a/cmake/ECM/kde-modules/KDEInstallDirs.cmake +++ b/cmake/ECM/kde-modules/KDEInstallDirs.cmake @@ -90,7 +90,7 @@ # desktop wallpaper images (``DATAROOTDIR/wallpapers``) # [``WALLPAPER_INSTALL_DIR``] # ``APPDIR`` -# application desktop files (``DATAROOTDIR/applications``) +# application desktop files (``DATAROOTDIR/applications``) Since 1.1.0. # [``XDG_APPS_INSTALL_DIR``] # ``DESKTOPDIR`` # desktop directories (``DATAROOTDIR/desktop-directories``) @@ -100,6 +100,10 @@ # [``XDG_MIME_INSTALL_DIR``] # ``METAINFODIR`` # AppStream component metadata files (``DATAROOTDIR/metainfo``) +# ``QTQCHDIR`` +# documentation bundles in QCH format for Qt-extending libraries (``DATAROOTDIR/doc/qch``) Since 5.36.0. +# ``QCHDIR`` +# documentation bundles in QCH format (``DATAROOTDIR/doc/qch``) Since 5.36.0. # ``MANDIR`` # man documentation (``DATAROOTDIR/man``) [``MAN_INSTALL_DIR``] # ``INFODIR`` @@ -174,8 +178,8 @@ # # Since pre-1.0.0. # -# NB: The variables starting ``KDE_INSTALL_`` are only available since 1.6.0. -# The ``APPDIR`` install variable is available since 1.1.0. +# NB: The variables starting ``KDE_INSTALL_`` are available since 1.6.0, +# unless otherwise noted with the variable. #============================================================================= # Copyright 2014-2015 Alex Merry @@ -448,7 +452,7 @@ if(NOT DEFINED KDE_INSTALL_USE_QT_SYS_PATHS) endif() endif() -option (KDE_INSTALL_USE_QT_SYS_PATHS "Install mkspecs files, Plugins and Imports to the Qt 5 install dir" "${_default_KDE_INSTALL_USE_QT_SYS_PATHS}") +option (KDE_INSTALL_USE_QT_SYS_PATHS "Install mkspecs files, QCH files for Qt-based libs, Plugins and Imports to the Qt 5 install dir" "${_default_KDE_INSTALL_USE_QT_SYS_PATHS}") if(KDE_INSTALL_USE_QT_SYS_PATHS) # Qt-specific vars query_qmake(qt_plugins_dir QT_INSTALL_PLUGINS) @@ -520,6 +524,18 @@ if(NOT KDE_INSTALL_DIRS_NO_DEPRECATED) set(KF5_DATA_INSTALL_DIR "${CMAKE_INSTALL_DATADIR_KF5}") endif() +# Qt-specific data vars +if(KDE_INSTALL_USE_QT_SYS_PATHS) + query_qmake(qt_docs_dir QT_INSTALL_DOCS) + + _define_absolute(QTQCHDIR ${qt_docs_dir} + "documentation bundles in QCH format for Qt-extending libraries") +else() + _define_relative(QTQCHDIR DATAROOTDIR "doc/qch" + "documentation bundles in QCH format for Qt-extending libraries") +endif() + + # KDE Framework-specific things _define_relative(DOCBUNDLEDIR DATAROOTDIR "doc/HTML" "documentation bundles generated using kdoctools" @@ -572,6 +588,8 @@ _define_relative(MIMEDIR DATAROOTDIR "mime/packages" XDG_MIME_INSTALL_DIR) _define_relative(METAINFODIR DATAROOTDIR "metainfo" "AppStream component metadata") +_define_relative(QCHDIR DATAROOTDIR "doc/qch" + "documentation bundles in QCH format") _define_relative(MANDIR DATAROOTDIR "man" "man documentation" MAN_INSTALL_DIR) diff --git a/cmake/ECM/modules/ECMEnableSanitizers.cmake b/cmake/ECM/modules/ECMEnableSanitizers.cmake index 9c8a4dee..06cc0b66 100644 --- a/cmake/ECM/modules/ECMEnableSanitizers.cmake +++ b/cmake/ECM/modules/ECMEnableSanitizers.cmake @@ -145,18 +145,29 @@ macro (enable_sanitizer_flags sanitize_option) endif () endmacro () -# for each element of the ECM_ENABLE_SANITIZERS list -foreach ( CUR_SANITIZER ${ECM_ENABLE_SANITIZERS} ) - # lowercase filter - string(TOLOWER ${CUR_SANITIZER} CUR_SANITIZER) - # check option and enable appropriate flags - enable_sanitizer_flags ( ${CUR_SANITIZER} ) - set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${XSAN_COMPILE_FLAGS}" ) - if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") - link_libraries(${XSAN_LINKER_FLAGS}) +if (ECM_ENABLE_SANITIZERS) + if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + # for each element of the ECM_ENABLE_SANITIZERS list + foreach ( CUR_SANITIZER ${ECM_ENABLE_SANITIZERS} ) + # lowercase filter + string(TOLOWER ${CUR_SANITIZER} CUR_SANITIZER) + # check option and enable appropriate flags + enable_sanitizer_flags ( ${CUR_SANITIZER} ) + # TODO: GCC will not link pthread library if enabled ASan + if(CMAKE_C_COMPILER_ID MATCHES "Clang") + set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${XSAN_COMPILE_FLAGS}" ) + endif() + set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${XSAN_COMPILE_FLAGS}" ) + if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + link_libraries(${XSAN_LINKER_FLAGS}) + endif() + if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + string(REPLACE "-Wl,--no-undefined" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") + string(REPLACE "-Wl,--no-undefined" "" CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}") + endif () + endforeach() + else() + message(STATUS "Tried to enable sanitizers (-DECM_ENABLE_SANITIZERS=${ECM_ENABLE_SANITIZERS}), \ +but compiler (${CMAKE_CXX_COMPILER_ID}) does not have sanitizer support") endif() - if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") - string(REPLACE "-Wl,--no-undefined" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") - string(REPLACE "-Wl,--no-undefined" "" CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}") - endif () -endforeach () +endif() diff --git a/scripts/NullsoftInstaller.nsi b/scripts/NullsoftInstaller.nsi index ab32e3fc..b917942d 100644 --- a/scripts/NullsoftInstaller.nsi +++ b/scripts/NullsoftInstaller.nsi @@ -1,6 +1,6 @@ ; basic script template for NullsoftInstallerPackager ; -; Copyright 2016-2017 Hannnah von Reth +; Copyright 2016-2018 Hannnah von Reth ; Copyright 2010 Patrick Spendrin diff --git a/scripts/create-win-installer.py b/scripts/create-win-installer.py index 57a89003..bb0cb5be 100644 --- a/scripts/create-win-installer.py +++ b/scripts/create-win-installer.py @@ -3,7 +3,7 @@ # # This file is part of Charm, a task-based time tracking application. # -# Copyright (C) 2016-2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com +# Copyright (C) 2016-2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com # # Author: Hannah von Reth # @@ -65,12 +65,12 @@ def cleanImage(self): shutil.rmtree(self.deployImage) os.makedirs(self.deployImage) - def _locateDll(self, dllName): + def _locateDll(self, dllName, fatal=True): pathext = os.environ.get("PATHEXT") os.environ["PATHEXT"] = ".dll" found = shutil.which(dllName, path=os.pathsep.join([self.deployImage, os.environ.get("PATH")])) os.environ["PATHEXT"] = pathext - if not found: + if not found and fatal: self._die("Unable to locate %s" % dllName) return found @@ -88,9 +88,17 @@ def deploy(self): self._copyToImage(f) if self.args.deployOpenSSL: - self._copyToImage(os.path.join(self.args.deployOpenSSL, "libeay32.dll" ), deploy=False) - self._copyToImage(os.path.join(self.args.deployOpenSSL, "libssl32.dll" ), deploy=False) - self._copyToImage(os.path.join(self.args.deployOpenSSL, "ssleay32.dll" ), deploy=False) + foundSomething = False + for dll in ["libeay32.dll", "libssl32.dll", "ssleay32.dll" ]: + src = os.path.join(self.args.deployOpenSSL, dll ) + if not os.path.exists(src): + src = self._locateDll(dll, fatal=False) + if src: + foundSomething = True + print(src) + self._copyToImage(src, deploy=False) + if not foundSomething: + self._die("Failed to deploy openssl") if self.args.sign: for f in glob.glob(os.path.join(self.deployImage, "**/*.exe"), recursive=True): @@ -126,7 +134,7 @@ def makeInstaller(self): for key in defines: definestring += " /D%s=\"%s\"" % (key, defines[key]) - command = "makensis.exe /NOCD %s %s" %\ + command = "makensis /NOCD %s %s" %\ (definestring, os.path.join(os.path.dirname(__file__), "NullsoftInstaller.nsi")) self._logExec(command) installer = os.path.realpath(self.args.installerName) @@ -150,7 +158,7 @@ def makeInstaller(self): parser.add_argument("--deployDlls", action = "store" ) parser.add_argument("--deployOpenSSL", action = "store" ) - parser.add_argument("--sign", action = "store_true", default="False") + parser.add_argument("--sign", action = "store_true", default=False) args = parser.parse_args()