├── logo.png ├── .krazy ├── icons ├── 128-apps-kronometer.png ├── 48-apps-kronometer.png ├── 64-apps-kronometer.png ├── sc-apps-kronometer.svgz └── CMakeLists.txt ├── autotests ├── gui │ ├── CMakeLists.txt │ ├── testtimedisplay.h │ └── testtimedisplay.cpp ├── CMakeLists.txt └── core │ ├── CMakeLists.txt │ ├── teststopwatch.h │ ├── testlap.h │ ├── testsession.h │ ├── testtimeformat.h │ ├── teststopwatch.cpp │ ├── testlap.cpp │ ├── testtimeformat.cpp │ └── testsession.cpp ├── .gitignore ├── src ├── gui │ ├── kronometerui.qrc │ ├── settings.kcfgc │ ├── fontsettings.cpp │ ├── colorsettings.cpp │ ├── fontsettings.h │ ├── colorsettings.h │ ├── generalsettings.h │ ├── CMakeLists.txt │ ├── lapitemdelegate.h │ ├── generalsettings.cpp │ ├── lapitemdelegate.cpp │ ├── colorsettings.ui │ ├── sessiondialog.h │ ├── timedisplay.ui │ ├── kronometerui.rc │ ├── sessiondialog.ui │ ├── digitdisplay.h │ ├── kronometer.kcfg │ ├── timedisplay.h │ ├── digitdisplay.cpp │ ├── sessiondialog.cpp │ ├── timedisplay.cpp │ ├── mainwindow.h │ └── fontsettings.ui ├── models │ ├── CMakeLists.txt │ ├── lapmodel.h │ ├── sessionmodel.h │ ├── lapmodel.cpp │ └── sessionmodel.cpp ├── core │ ├── CMakeLists.txt │ ├── lap.cpp │ ├── session.cpp │ ├── lap.h │ ├── stopwatch.cpp │ ├── session.h │ ├── timeformat.cpp │ ├── stopwatch.h │ └── timeformat.h ├── Mainpage.dox ├── CMakeLists.txt └── main.cpp ├── Messages.sh ├── desktop ├── CMakeLists.txt └── org.kde.kronometer.desktop ├── README.md ├── doc ├── CMakeLists.txt ├── man-kronometer.1.docbook └── index.docbook ├── .gitlab-ci.yml ├── .kde-ci.yml ├── .flatpak-manifest.json ├── flatpak └── org.kde.kronometer.json ├── CMakeLists.txt ├── po ├── sv │ └── docs │ │ └── kronometer │ │ ├── man-kronometer.1.docbook │ │ └── index.docbook ├── it │ └── docs │ │ └── kronometer │ │ └── man-kronometer.1.docbook ├── nl │ └── docs │ │ └── kronometer │ │ ├── man-kronometer.1.docbook │ │ └── index.docbook ├── de │ └── docs │ │ └── kronometer │ │ └── man-kronometer.1.docbook ├── pt │ └── docs │ │ └── kronometer │ │ └── man-kronometer.1.docbook ├── pt_BR │ └── docs │ │ └── kronometer │ │ └── man-kronometer.1.docbook ├── ca │ └── docs │ │ └── kronometer │ │ └── man-kronometer.1.docbook ├── es │ └── docs │ │ └── kronometer │ │ └── man-kronometer.1.docbook └── uk │ └── docs │ └── kronometer │ └── man-kronometer.1.docbook ├── CMakePresets.json ├── CHANGELOG └── LICENSES └── CC0-1.0.txt /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KDE/kronometer/HEAD/logo.png -------------------------------------------------------------------------------- /.krazy: -------------------------------------------------------------------------------- 1 | EXTRA camelcase,defines,multiclasses,null,qenums,qmath 2 | EXCLUDE postfixop 3 | -------------------------------------------------------------------------------- /icons/128-apps-kronometer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KDE/kronometer/HEAD/icons/128-apps-kronometer.png -------------------------------------------------------------------------------- /icons/48-apps-kronometer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KDE/kronometer/HEAD/icons/48-apps-kronometer.png -------------------------------------------------------------------------------- /icons/64-apps-kronometer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KDE/kronometer/HEAD/icons/64-apps-kronometer.png -------------------------------------------------------------------------------- /icons/sc-apps-kronometer.svgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KDE/kronometer/HEAD/icons/sc-apps-kronometer.svgz -------------------------------------------------------------------------------- /autotests/gui/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ecm_add_tests( 2 | testtimedisplay.cpp 3 | LINK_LIBRARIES Qt::Test gui) 4 | 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *build*/ 2 | CMakeLists.txt.user 3 | *.kdev4 4 | cmake-build-debug/ 5 | .idea/ 6 | .vscode/ 7 | compile_commands.json 8 | .cache 9 | -------------------------------------------------------------------------------- /src/gui/kronometerui.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | kronometerui.rc 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/gui/settings.kcfgc: -------------------------------------------------------------------------------- 1 | File=kronometer.kcfg 2 | ClassName=KronometerConfig 3 | Singleton=true 4 | Mutators=true 5 | UseEnumTypes=true 6 | GenerateProperties=true 7 | -------------------------------------------------------------------------------- /autotests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(ECMAddTests) 2 | 3 | find_package(Qt6Test ${QT_MIN_VERSION} REQUIRED NO_MODULE) 4 | 5 | add_subdirectory(core) 6 | add_subdirectory(gui) 7 | -------------------------------------------------------------------------------- /autotests/core/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ecm_add_tests( 2 | testlap.cpp 3 | testsession.cpp 4 | teststopwatch.cpp 5 | testtimeformat.cpp 6 | LINK_LIBRARIES Qt::Test core) 7 | -------------------------------------------------------------------------------- /Messages.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | $EXTRACTRC `find . -name \*.rc -o -name \*.kcfg -o -name \*.ui` >> rc.cpp || exit 11 3 | $XGETTEXT `find . -name \*.h -o -name \*.cpp` -o $podir/kronometer.pot 4 | -------------------------------------------------------------------------------- /desktop/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | install(FILES org.kde.kronometer.appdata.xml 2 | DESTINATION ${KDE_INSTALL_METAINFODIR}) 3 | install(PROGRAMS org.kde.kronometer.desktop 4 | DESTINATION ${KDE_INSTALL_APPDIR}) 5 | -------------------------------------------------------------------------------- /icons/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ecm_install_icons( 2 | ICONS 3 | 48-apps-kronometer.png 4 | 64-apps-kronometer.png 5 | 128-apps-kronometer.png 6 | sc-apps-kronometer.svgz 7 | DESTINATION ${KDE_INSTALL_ICONDIR}) 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Kronometer 2 | ========== 3 | 4 | Kronometer is a simple stopwatch application. 5 | 6 | Homepage: https://userbase.kde.org/Kronometer 7 | 8 | Installation 9 | ============ 10 | 11 | See https://userbase.kde.org/Kronometer#Installation 12 | -------------------------------------------------------------------------------- /src/models/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(models_SRCS 2 | lapmodel.cpp lapmodel.h 3 | sessionmodel.cpp sessionmodel.h) 4 | 5 | add_library(models STATIC ${models_SRCS}) 6 | target_link_libraries(models 7 | Qt::Core 8 | KF6::I18n 9 | core) 10 | -------------------------------------------------------------------------------- /src/core/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(core_SRCS 2 | lap.cpp 3 | session.cpp 4 | stopwatch.cpp 5 | timeformat.cpp 6 | lap.h 7 | session.h 8 | stopwatch.h 9 | timeformat.h) 10 | 11 | add_library(core STATIC ${core_SRCS}) 12 | target_link_libraries(core Qt::Core) 13 | -------------------------------------------------------------------------------- /src/Mainpage.dox: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | @mainpage Kronometer 4 | 5 | Here you can browse the Doxygen documentation for the [Kronometer](https://userbase.kde.org/Kronometer "Kronometer homepage") source code. 6 | 7 | @licenses @gpl 8 | 9 | */ 10 | 11 | // What is this? 12 | // DOXYGEN_SET_PROJECT_NAME = Kronometer 13 | -------------------------------------------------------------------------------- /doc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Create and install documentation files 2 | 3 | kdoctools_create_handbook(index.docbook 4 | INSTALL_DESTINATION ${KDE_INSTALL_DOCBUNDLEDIR}/en 5 | SUBDIR kronometer) 6 | kdoctools_create_manpage(man-kronometer.1.docbook 7 | 1 8 | INSTALL_DESTINATION 9 | ${KDE_INSTALL_MANDIR}) 10 | -------------------------------------------------------------------------------- /src/gui/fontsettings.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2016 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "fontsettings.h" 8 | 9 | FontSettings::FontSettings(QWidget *parent) : QWidget(parent) 10 | { 11 | setupUi(this); 12 | } 13 | 14 | #include "moc_fontsettings.cpp" 15 | -------------------------------------------------------------------------------- /src/gui/colorsettings.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2016 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "colorsettings.h" 8 | 9 | ColorSettings::ColorSettings(QWidget *parent) : QWidget(parent) 10 | { 11 | setupUi(this); 12 | } 13 | 14 | #include "moc_colorsettings.cpp" 15 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: None 2 | # SPDX-License-Identifier: CC0-1.0 3 | 4 | include: 5 | - project: sysadmin/ci-utilities 6 | file: 7 | - /gitlab-templates/flatpak.yml 8 | - /gitlab-templates/linux-qt6.yml 9 | - /gitlab-templates/linux-qt6-next.yml 10 | - /gitlab-templates/freebsd-qt6.yml 11 | - /gitlab-templates/windows-qt6.yml 12 | - /gitlab-templates/documentation.yml 13 | -------------------------------------------------------------------------------- /src/gui/fontsettings.h: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2014 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef FONTSETTINGS_H 8 | #define FONTSETTINGS_H 9 | 10 | #include "ui_fontsettings.h" 11 | 12 | class FontSettings : public QWidget, public Ui::FontSettings 13 | { 14 | Q_OBJECT 15 | 16 | public: 17 | explicit FontSettings(QWidget *parent = nullptr); 18 | }; 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /src/gui/colorsettings.h: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2014 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef COLORSETTINGS_H 8 | #define COLORSETTINGS_H 9 | 10 | #include "ui_colorsettings.h" 11 | 12 | class ColorSettings : public QWidget, public Ui::ColorSettings 13 | { 14 | Q_OBJECT 15 | 16 | public: 17 | explicit ColorSettings(QWidget *parent = nullptr); 18 | }; 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /autotests/gui/testtimedisplay.h: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2016 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef TESTTIMEDISPLAY_H 8 | #define TESTTIMEDISPLAY_H 9 | 10 | #include 11 | 12 | class TestTimeDisplay : public QObject 13 | { 14 | Q_OBJECT 15 | 16 | private Q_SLOTS: 17 | 18 | void testDefaultWidget(); 19 | void testSetBackgroundColor(); 20 | void testSetTextColor(); 21 | }; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /autotests/core/teststopwatch.h: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2015 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef TESTSTOPWATCH_H 8 | #define TESTSTOPWATCH_H 9 | 10 | #include 11 | 12 | class TestStopwatch : public QObject 13 | { 14 | Q_OBJECT 15 | 16 | private Q_SLOTS: 17 | 18 | void testInactive(); 19 | void testRunning(); 20 | void testPaused(); 21 | void testReset(); 22 | void testInitialize(); 23 | }; 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /autotests/core/testlap.h: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2015 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef TESTLAP_H 8 | #define TESTLAP_H 9 | 10 | #include 11 | 12 | class TestLap : public QObject 13 | { 14 | Q_OBJECT 15 | 16 | private Q_SLOTS: 17 | 18 | void testDefaultLap(); 19 | void testLapTime(); 20 | void testRelativeTime(); 21 | void testAbsoluteTime(); 22 | void testNote(); 23 | void testRawData(); 24 | void testTimeTo(); 25 | }; 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /.kde-ci.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: None 2 | # SPDX-License-Identifier: CC0-1.0 3 | 4 | Dependencies: 5 | - 'on': ['Linux', 'FreeBSD', 'Windows'] 6 | 'require': 7 | 'frameworks/extra-cmake-modules': '@latest-kf6' 8 | 'frameworks/kconfig': '@latest-kf6' 9 | 'frameworks/kcoreaddons': '@latest-kf6' 10 | 'frameworks/kcrash': '@latest-kf6' 11 | 'frameworks/kdoctools': '@latest-kf6' 12 | 'frameworks/ki18n': '@latest-kf6' 13 | 'frameworks/kwidgetsaddons': '@latest-kf6' 14 | 'frameworks/kxmlgui': '@latest-kf6' 15 | 16 | Options: 17 | require-passing-tests-on: ['Linux', 'FreeBSD', 'Windows'] 18 | -------------------------------------------------------------------------------- /autotests/core/testsession.h: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2015 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef TESTSESSION_H 8 | #define TESTSESSION_H 9 | 10 | #include 11 | 12 | class TestSession : public QObject 13 | { 14 | Q_OBJECT 15 | 16 | private Q_SLOTS: 17 | 18 | void testDefaultSession(); 19 | void testTime(); 20 | void testName(); 21 | void testNote(); 22 | void testDate(); 23 | void testLaps(); 24 | void testEquality(); 25 | void testInequality(); 26 | void testJson(); 27 | }; 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(core) 2 | add_subdirectory(gui) 3 | add_subdirectory(models) 4 | 5 | include_directories(${CMAKE_BINARY_DIR}) # for version.h generated by cmake 6 | add_executable(kronometer main.cpp) 7 | 8 | if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") 9 | target_compile_options(kronometer PRIVATE -pedantic) 10 | endif() 11 | 12 | target_link_libraries(kronometer 13 | KF6::CoreAddons 14 | KF6::Crash 15 | gui) 16 | 17 | install(TARGETS kronometer ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) 18 | install(FILES gui/kronometer.kcfg 19 | DESTINATION ${KDE_INSTALL_KCFGDIR}) 20 | -------------------------------------------------------------------------------- /autotests/core/testtimeformat.h: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2015 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef TESTTIMEFORMAT_H 8 | #define TESTTIMEFORMAT_H 9 | 10 | #include 11 | 12 | class TestTimeFormat : public QObject 13 | { 14 | Q_OBJECT 15 | 16 | private Q_SLOTS: 17 | 18 | void testDefaultFormat(); 19 | void testFullFormat(); 20 | void testMinimalFormat(); 21 | void testNoDividers(); 22 | void testEquality(); 23 | void testInequality(); 24 | void testOverrideHours(); 25 | void testOverrideMinutes(); 26 | }; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/gui/generalsettings.h: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2014 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef GENERALSETTINGS_H 8 | #define GENERALSETTINGS_H 9 | 10 | #include "ui_generalsettings.h" 11 | 12 | class GeneralSettings : public QWidget, public Ui::GeneralSettings 13 | { 14 | Q_OBJECT 15 | 16 | public: 17 | explicit GeneralSettings(QWidget *parent = nullptr); 18 | 19 | private Q_SLOTS: 20 | 21 | void showFractionsToggled(bool toggled); 22 | void showLapFractionsToggled(bool toggled); 23 | void enableLapsToggled(bool toggled); 24 | }; 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /.flatpak-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "org.kde.kronometer", 3 | "branch": "master", 4 | "runtime": "org.kde.Platform", 5 | "runtime-version": "6.10", 6 | "sdk": "org.kde.Sdk", 7 | "command": "kronometer", 8 | "tags": ["nightly"], 9 | "desktop-file-name-suffix": " (Nightly)", 10 | "finish-args": ["--share=ipc", "--socket=fallback-x11", "--socket=wayland" ], 11 | "modules": [ 12 | { 13 | "name": "kronometer", 14 | "buildsystem": "cmake-ninja", 15 | "config-opts": [ "-DBUILD_WITH_QT6=ON" ], 16 | "sources": [ 17 | { "type": "dir", "path": "." } 18 | ] 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /flatpak/org.kde.kronometer.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "org.kde.kronometer", 3 | "branch": "master", 4 | "rename-icon": "kronometer", 5 | "runtime": "org.kde.Platform", 6 | "runtime-version": "5.15-24.08", 7 | "sdk": "org.kde.Sdk", 8 | "command": "kronometer", 9 | "tags": [ 10 | "nightly" 11 | ], 12 | "desktop-file-name-prefix": "(Nightly) ", 13 | "finish-args": [ 14 | "--device=dri", 15 | "--share=ipc", 16 | "--socket=session-bus", 17 | "--socket=wayland", 18 | "--socket=x11-fallback" 19 | ], 20 | "modules": [ 21 | { 22 | "name": "kronometer", 23 | "buildsystem": "cmake-ninja", 24 | "sources": [ 25 | { 26 | "type": "dir", 27 | "path": "." 28 | } 29 | ] 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /src/gui/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(gui_SRCS 2 | colorsettings.cpp 3 | digitdisplay.cpp 4 | fontsettings.cpp 5 | generalsettings.cpp 6 | lapitemdelegate.cpp 7 | mainwindow.cpp 8 | sessiondialog.cpp 9 | timedisplay.cpp 10 | colorsettings.h 11 | digitdisplay.h 12 | fontsettings.h 13 | generalsettings.h 14 | lapitemdelegate.h 15 | mainwindow.h 16 | sessiondialog.h 17 | timedisplay.h 18 | ) 19 | 20 | ki18n_wrap_ui(gui_SRCS 21 | colorsettings.ui 22 | fontsettings.ui 23 | generalsettings.ui 24 | sessiondialog.ui 25 | timedisplay.ui) 26 | 27 | qt_add_resources(gui_SRCS kronometerui.qrc) 28 | kconfig_add_kcfg_files(gui_SRCS settings.kcfgc GENERATE_MOC) 29 | 30 | add_library(gui STATIC ${gui_SRCS}) 31 | target_link_libraries(gui 32 | Qt::Core 33 | Qt::Widgets 34 | KF6::I18n 35 | KF6::WidgetsAddons 36 | KF6::XmlGui 37 | core 38 | models) 39 | -------------------------------------------------------------------------------- /src/gui/lapitemdelegate.h: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2022 Johnny Jazeix 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef LAPITEMDELEGATE_H 8 | #define LAPITEMDELEGATE_H 9 | 10 | #include 11 | 12 | class MainWindow; 13 | /** 14 | * @brief ItemDelegate to block the Return key press creating a new line 15 | * when editing a line. 16 | */ 17 | class LapItemDelegate : public QItemDelegate { 18 | Q_OBJECT 19 | 20 | public: 21 | explicit LapItemDelegate(MainWindow *window); 22 | QWidget* createEditor(QWidget *parent, 23 | const QStyleOptionViewItem &option, 24 | const QModelIndex &index) const override; 25 | 26 | void onCloseEditor(QWidget *, 27 | QAbstractItemDelegate::EndEditHint) const; 28 | 29 | private: 30 | MainWindow *m_window; 31 | }; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/gui/generalsettings.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2015 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "generalsettings.h" 8 | 9 | #include 10 | 11 | GeneralSettings::GeneralSettings(QWidget *parent) : QWidget(parent) 12 | { 13 | setupUi(this); 14 | 15 | connect(kcfg_showSecondFractions, &QCheckBox::toggled, this, &GeneralSettings::showFractionsToggled); 16 | connect(kcfg_showLapSecondFractions, &QCheckBox::toggled, this, &GeneralSettings::showLapFractionsToggled); 17 | connect(kcfg_isLapsRecordingEnabled, &QCheckBox::toggled, this, &GeneralSettings::enableLapsToggled); 18 | } 19 | 20 | void GeneralSettings::showFractionsToggled(bool toggled) 21 | { 22 | kcfg_fractionsType->setEnabled(toggled); 23 | } 24 | 25 | void GeneralSettings::showLapFractionsToggled(bool toggled) 26 | { 27 | kcfg_lapFractionsType->setEnabled(toggled); 28 | } 29 | 30 | void GeneralSettings::enableLapsToggled(bool toggled) 31 | { 32 | lapSettings->setVisible(toggled); 33 | } 34 | 35 | #include "moc_generalsettings.cpp" 36 | -------------------------------------------------------------------------------- /src/gui/lapitemdelegate.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2022 Johnny Jazeix 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "lapitemdelegate.h" 8 | #include "mainwindow.h" 9 | 10 | #include 11 | #include 12 | 13 | LapItemDelegate::LapItemDelegate(MainWindow *window) : QItemDelegate(window), 14 | m_window{window} 15 | { 16 | connect(this, &QItemDelegate::closeEditor, this, &LapItemDelegate::onCloseEditor); 17 | } 18 | 19 | QWidget* LapItemDelegate::createEditor(QWidget *parent, 20 | const QStyleOptionViewItem &option, 21 | const QModelIndex &index) const 22 | { 23 | m_window->enableLapShortcuts(false); 24 | return QItemDelegate::createEditor(parent, option, index); 25 | } 26 | void LapItemDelegate::onCloseEditor(QWidget *, 27 | QAbstractItemDelegate::EndEditHint) const 28 | { 29 | m_window->enableLapShortcuts(true); 30 | } 31 | 32 | #include "moc_lapitemdelegate.cpp" 33 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | project(kronometer) 3 | 4 | set(QT_MIN_VERSION "6.5.0") 5 | set(KF_MIN_VERSION "6.0.0") 6 | 7 | set(PROJECT_VERSION 2.3.70) 8 | 9 | set(CMAKE_CXX_STANDARD 17) 10 | set(CXX_STANDARD_REQUIRED ON) 11 | 12 | find_package(ECM ${KF_MIN_VERSION} REQUIRED NO_MODULE) 13 | set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH}) 14 | 15 | include(KDEInstallDirs) 16 | include(KDECMakeSettings) 17 | include(KDECompilerSettings NO_POLICY_SCOPE) 18 | include(ECMInstallIcons) 19 | include(ECMSetupVersion) 20 | include(FeatureSummary) 21 | include(ECMDeprecationSettings) 22 | 23 | find_package(Qt6 ${QT_MIN_VERSION} REQUIRED 24 | COMPONENTS 25 | Core 26 | Gui 27 | Widgets) 28 | 29 | find_package(KF6 ${KF_MIN_VERSION} REQUIRED 30 | COMPONENTS 31 | CoreAddons 32 | Config 33 | Crash 34 | DocTools 35 | I18n 36 | WidgetsAddons 37 | XmlGui) 38 | 39 | ecm_setup_version(${PROJECT_VERSION} 40 | VARIABLE_PREFIX KRONOMETER 41 | VERSION_HEADER version.h) 42 | 43 | add_definitions( 44 | -DQT_NO_CAST_FROM_ASCII 45 | -DQT_NO_CAST_TO_ASCII 46 | -DQT_USE_QSTRINGBUILDER) 47 | 48 | ecm_set_disabled_deprecation_versions(QT 5.15.2 49 | KF 5.102 50 | ) 51 | 52 | add_subdirectory(desktop) 53 | add_subdirectory(src) 54 | add_subdirectory(icons) 55 | add_subdirectory(autotests) 56 | 57 | ki18n_install(po) 58 | if(KF6DocTools_FOUND) 59 | add_subdirectory(doc) 60 | kdoctools_install(po) 61 | endif() 62 | 63 | feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) 64 | -------------------------------------------------------------------------------- /autotests/core/teststopwatch.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2015 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "teststopwatch.h" 8 | #include "stopwatch.h" 9 | 10 | void TestStopwatch::testInactive() 11 | { 12 | Stopwatch stopwatch; 13 | 14 | QVERIFY(!stopwatch.isRunning()); 15 | QVERIFY(!stopwatch.isPaused()); 16 | QVERIFY(stopwatch.isInactive()); 17 | } 18 | 19 | void TestStopwatch::testRunning() 20 | { 21 | Stopwatch stopwatch; 22 | 23 | stopwatch.start(); 24 | 25 | QVERIFY(stopwatch.isRunning()); 26 | QVERIFY(!stopwatch.isPaused()); 27 | QVERIFY(!stopwatch.isInactive()); 28 | } 29 | 30 | void TestStopwatch::testPaused() 31 | { 32 | Stopwatch stopwatch; 33 | 34 | stopwatch.pause(); 35 | 36 | QVERIFY(!stopwatch.isRunning()); 37 | QVERIFY(stopwatch.isPaused()); 38 | QVERIFY(!stopwatch.isInactive()); 39 | } 40 | 41 | void TestStopwatch::testReset() 42 | { 43 | Stopwatch stopwatch; 44 | 45 | stopwatch.reset(); 46 | 47 | QVERIFY(!stopwatch.isRunning()); 48 | QVERIFY(!stopwatch.isPaused()); 49 | QVERIFY(stopwatch.isInactive()); 50 | } 51 | 52 | void TestStopwatch::testInitialize() 53 | { 54 | Stopwatch s1, s2; 55 | 56 | s1.start(); 57 | QTest::qSleep(100); 58 | s1.pause(); 59 | int t = s1.raw(); 60 | 61 | QVERIFY(s2.initialize(t)); 62 | QVERIFY(s2.isPaused()); 63 | QCOMPARE(s2.raw(), t); 64 | } 65 | 66 | QTEST_MAIN(TestStopwatch) 67 | 68 | #include "moc_teststopwatch.cpp" 69 | -------------------------------------------------------------------------------- /autotests/gui/testtimedisplay.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2016 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "testtimedisplay.h" 8 | #include "timedisplay.h" 9 | 10 | #include "digitdisplay.h" 11 | 12 | #include 13 | 14 | void TestTimeDisplay::testDefaultWidget() 15 | { 16 | TimeDisplay timeDisplay; 17 | 18 | const auto groupBoxes = timeDisplay.findChildren(); 19 | QCOMPARE(groupBoxes.size(), 4); 20 | 21 | for (auto group : groupBoxes) { 22 | QCOMPARE(group->findChildren().size(), 1); 23 | QVERIFY(!group->title().isEmpty()); 24 | } 25 | } 26 | 27 | void TestTimeDisplay::testSetBackgroundColor() 28 | { 29 | const auto color = qApp->palette().base().color(); 30 | 31 | TimeDisplay timeDisplay; 32 | timeDisplay.setBackgroundColor(color); 33 | 34 | const auto groupBoxes = timeDisplay.findChildren(); 35 | for (auto group : groupBoxes) { 36 | QCOMPARE(group->palette().color(group->backgroundRole()), color); 37 | } 38 | } 39 | 40 | void TestTimeDisplay::testSetTextColor() 41 | { 42 | const auto color = qApp->palette().text().color(); 43 | 44 | TimeDisplay timeDisplay; 45 | timeDisplay.setTextColor(color); 46 | 47 | const auto groupBoxes = timeDisplay.findChildren(); 48 | for (auto group : groupBoxes) { 49 | QCOMPARE(group->palette().color(group->foregroundRole()), color); 50 | } 51 | } 52 | 53 | QTEST_MAIN(TestTimeDisplay) 54 | 55 | #include "moc_testtimedisplay.cpp" 56 | -------------------------------------------------------------------------------- /autotests/core/testlap.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2015 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "testlap.h" 8 | #include "lap.h" 9 | 10 | #include 11 | 12 | void TestLap::testDefaultLap() 13 | { 14 | Lap lap; 15 | 16 | QCOMPARE(lap.time(), QTime(0, 0)); 17 | QCOMPARE(lap.raw(), 0); 18 | QVERIFY(lap.relativeTime().isEmpty()); 19 | QVERIFY(lap.absoluteTime().isEmpty()); 20 | } 21 | 22 | void TestLap::testLapTime() 23 | { 24 | QTime time {1, 30}; 25 | Lap lap {time}; 26 | 27 | QCOMPARE(lap.time(), time); 28 | } 29 | 30 | void TestLap::testRelativeTime() 31 | { 32 | Lap lap; 33 | auto test = QLatin1String("test"); 34 | 35 | lap.setRelativeTime(test); 36 | 37 | QCOMPARE(lap.relativeTime(), test); 38 | } 39 | 40 | void TestLap::testAbsoluteTime() 41 | { 42 | Lap lap; 43 | auto test = QLatin1String("test"); 44 | 45 | lap.setAbsoluteTime(test); 46 | 47 | QCOMPARE(lap.absoluteTime(), test); 48 | } 49 | 50 | void TestLap::testNote() 51 | { 52 | Lap lap; 53 | auto test = QLatin1String("test"); 54 | 55 | lap.setNote(test); 56 | 57 | QCOMPARE(lap.note(), test); 58 | } 59 | 60 | void TestLap::testRawData() 61 | { 62 | int t = 1000; 63 | Lap lap = Lap::fromRawData(t); 64 | 65 | QCOMPARE(lap.raw(), t); 66 | } 67 | 68 | void TestLap::testTimeTo() 69 | { 70 | int t1 = 50; 71 | int t2 = 100; 72 | 73 | Lap lap1 = Lap::fromRawData(t1); 74 | Lap lap2 = Lap::fromRawData(t2); 75 | 76 | QCOMPARE(lap1.timeTo(lap2).msec(), t2 - t1); 77 | } 78 | 79 | QTEST_MAIN(TestLap) 80 | 81 | #include "moc_testlap.cpp" 82 | -------------------------------------------------------------------------------- /src/gui/colorsettings.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | ColorSettings 4 | 5 | 6 | 7 | 0 8 | 0 9 | 1077 10 | 487 11 | 12 | 13 | 14 | 15 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 16 | 17 | 18 | 19 | 20 | Display Background: 21 | 22 | 23 | 24 | 25 | 26 | 27 | Background color of the stopwatch display 28 | 29 | 30 | 31 | 32 | 33 | 34 | Display Digits: 35 | 36 | 37 | 38 | 39 | 40 | 41 | Color of the stopwatch display digits 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | KColorButton 50 | QPushButton 51 |
kcolorbutton.h
52 |
53 |
54 | 55 | 56 |
57 | -------------------------------------------------------------------------------- /src/gui/sessiondialog.h: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2015 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef SESSIONDIALOG_H 8 | #define SESSIONDIALOG_H 9 | 10 | #include "ui_sessiondialog.h" 11 | #include "session.h" 12 | 13 | #include 14 | 15 | class SessionModel; 16 | 17 | class KMessageWidget; 18 | 19 | class QDialogButtonBox; 20 | class QSortFilterProxyModel; 21 | class QTableView; 22 | 23 | /** 24 | * @brief Dialog for sessions interaction. 25 | */ 26 | class SessionDialog : public QDialog, public Ui::SessionDialog 27 | { 28 | Q_OBJECT 29 | 30 | public: 31 | 32 | explicit SessionDialog(SessionModel *sessionModel, QWidget *parent = nullptr); 33 | 34 | Session selectedSession() const; 35 | 36 | public Q_SLOTS: 37 | 38 | virtual void accept() override; 39 | 40 | protected: 41 | 42 | virtual void keyPressEvent(QKeyEvent *event) override; 43 | 44 | private Q_SLOTS: 45 | 46 | /** 47 | * Call accept() if the selection's column is not editable. 48 | * @param index The selected index. 49 | */ 50 | void slotDoubleClicked(const QModelIndex& index); 51 | 52 | /** 53 | * Disable the OK button if no session is selected. 54 | */ 55 | void slotSelectionChanged(); 56 | 57 | /** 58 | * Enable the OK button after the first session is added. 59 | */ 60 | void slotSessionAdded(); 61 | 62 | /** 63 | * Disable the OK button if no session is available. 64 | */ 65 | void slotEmptyModel(); 66 | 67 | private: 68 | 69 | SessionModel *m_sessionModel; 70 | QSortFilterProxyModel *m_proxyModel; 71 | Session m_selectedSession; 72 | 73 | /** 74 | * @return The actual selected index in the view. 75 | */ 76 | QModelIndex selectedIndex(); 77 | 78 | /** 79 | * Ask confirm to the user before removing a session. 80 | */ 81 | void removeDialog(); 82 | 83 | Q_DISABLE_COPY(SessionDialog) 84 | }; 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /src/core/lap.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2014 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "lap.h" 8 | 9 | #include 10 | 11 | Lap::Lap(const QTime& lap) : 12 | m_time {lap} 13 | {} 14 | 15 | QTime Lap::time() const 16 | { 17 | return m_time; 18 | } 19 | 20 | QTime Lap::timeTo(const Lap& lap) const 21 | { 22 | if (lap.time() < m_time) 23 | return {0, 0}; 24 | 25 | const auto zero = QTime {0, 0}; 26 | return zero.addMSecs(m_time.msecsTo(lap.time())); 27 | } 28 | 29 | void Lap::setRelativeTime(const QString& rel) 30 | { 31 | m_relativeTime = rel; 32 | } 33 | 34 | QString Lap::relativeTime() const 35 | { 36 | return m_relativeTime; 37 | } 38 | 39 | void Lap::setAbsoluteTime(const QString& abs) 40 | { 41 | m_absoluteTime = abs; 42 | } 43 | 44 | QString Lap::absoluteTime() const 45 | { 46 | return m_absoluteTime; 47 | } 48 | 49 | void Lap::setNote(const QString& note) 50 | { 51 | m_note = note; 52 | } 53 | 54 | QString Lap::note() const 55 | { 56 | return m_note; 57 | } 58 | 59 | int Lap::raw() const 60 | { 61 | const auto zero = QTime {0, 0}; 62 | return zero.msecsTo(m_time); 63 | } 64 | 65 | void Lap::write(QJsonObject& json) const 66 | { 67 | json[QStringLiteral("time")] = raw(); 68 | json[QStringLiteral("reltime")] = m_relativeTime; 69 | json[QStringLiteral("abstime")] = m_absoluteTime; 70 | json[QStringLiteral("note")] = m_note; 71 | } 72 | 73 | Lap Lap::fromJson(const QJsonObject& json) 74 | { 75 | auto lap = fromRawData(json[QStringLiteral("time")].toInt()); 76 | lap.m_relativeTime = json[QStringLiteral("reltime")].toString(); 77 | lap.m_absoluteTime = json[QStringLiteral("abstime")].toString(); 78 | lap.m_note = json[QStringLiteral("note")].toString(); 79 | 80 | return lap; 81 | } 82 | 83 | Lap Lap::fromRawData(int rawData) 84 | { 85 | if (rawData < 0) { 86 | return Lap {}; 87 | } 88 | 89 | const auto zero = QTime {0, 0}; 90 | return Lap {zero.addMSecs(rawData)}; 91 | } 92 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2014 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "sessionmodel.h" 8 | #include "mainwindow.h" 9 | #include "version.h" 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | int main (int argc, char **argv) 21 | { 22 | QApplication app {argc, argv}; 23 | KLocalizedString::setApplicationDomain("kronometer"); 24 | 25 | KCrash::initialize(); 26 | 27 | auto aboutData = KAboutData { 28 | QStringLiteral("kronometer"), // componentName 29 | i18nc("KAboutData display name", "Kronometer"), 30 | QStringLiteral(KRONOMETER_VERSION_STRING), 31 | i18n("Kronometer is a simple stopwatch application"), // shortDescription 32 | KAboutLicense::GPL_V2, // licenseType 33 | i18n("Copyright (C) 2014-2016 Elvis Angelaccio"), // copyrightStatement 34 | {}, // otherText 35 | QStringLiteral("https://userbase.kde.org/Kronometer") // homePageAddress 36 | }; 37 | 38 | aboutData.addAuthor( 39 | i18n("Elvis Angelaccio"), 40 | i18n("Maintainer"), 41 | QStringLiteral("elvis.angelaccio@kde.org"), 42 | QStringLiteral("https://eang.it") 43 | ); 44 | 45 | aboutData.addCredit( 46 | i18n("Ken Vermette"), 47 | i18n("Kronometer icon"), 48 | QStringLiteral("vermette@gmail.com") 49 | ); 50 | 51 | KAboutData::setApplicationData(aboutData); 52 | app.setWindowIcon(QIcon::fromTheme(QStringLiteral("kronometer"))); 53 | 54 | // Make sure that the local data directory is available. 55 | auto appdata = QFileInfo {QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)}; 56 | if (!appdata.exists()) { 57 | auto dir = QDir {appdata.absolutePath()}; 58 | dir.mkdir(appdata.fileName()); 59 | } 60 | 61 | SessionModel sessionModel; 62 | auto window = new MainWindow {&sessionModel}; 63 | window->show(); 64 | 65 | return app.exec(); 66 | } 67 | -------------------------------------------------------------------------------- /src/gui/timedisplay.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | TimeDisplay 4 | 5 | 6 | 7 | 0 8 | 9 | 10 | 0 11 | 12 | 13 | 0 14 | 15 | 16 | 17 | 18 | Hours 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | Minutes 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | Seconds 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | Hundredths 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | DigitDisplay 68 | QWidget 69 |
digitdisplay.h
70 | 1 71 |
72 |
73 | 74 | 75 |
76 | -------------------------------------------------------------------------------- /src/gui/kronometerui.rc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | &File 8 | 9 | 10 | 11 | &Kronometer 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | Kronometer Toolbar 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /src/gui/sessiondialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | SessionDialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 400 10 | 300 11 | 12 | 13 | 14 | Open Session 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | QAbstractItemView::SingleSelection 24 | 25 | 26 | QAbstractItemView::SelectRows 27 | 28 | 29 | Qt::DotLine 30 | 31 | 32 | true 33 | 34 | 35 | true 36 | 37 | 38 | false 39 | 40 | 41 | 42 | 43 | 44 | 45 | Qt::Horizontal 46 | 47 | 48 | QDialogButtonBox::Cancel|QDialogButtonBox::Ok 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | KMessageWidget 57 | QFrame 58 |
kmessagewidget.h
59 |
60 |
61 | 62 | 63 | 64 | m_buttonBox 65 | accepted() 66 | SessionDialog 67 | accept() 68 | 69 | 70 | 248 71 | 254 72 | 73 | 74 | 157 75 | 274 76 | 77 | 78 | 79 | 80 | m_buttonBox 81 | rejected() 82 | SessionDialog 83 | reject() 84 | 85 | 86 | 316 87 | 260 88 | 89 | 90 | 286 91 | 274 92 | 93 | 94 | 95 | 96 |
97 | -------------------------------------------------------------------------------- /doc/man-kronometer.1.docbook: -------------------------------------------------------------------------------- 1 | 2 | 4 | ]> 5 | 6 | 7 | 8 | 2016-04-10 9 | kronometer 2.0 10 | 11 | 12 | 13 | kronometer 14 | 1 15 | April 2016 16 | KRONOMETER 2.1.0 17 | 18 | 19 | kronometer 20 | stopwatch application 21 | 22 | 23 | 24 | 25 | kronometer 26 | 27 | 28 | 29 | DESCRIPTION 30 | Kronometer is a stopwatch (timer/chronometer) application. 31 | 32 | Kronometer’s main features are the following: 33 |
34 | 35 | 36 | Start/pause/resume the stopwatch widget; 37 | 38 | 39 | Laps recording: you can capture the stopwatch time when you want; 40 | 41 | 42 | Lap times sorting: you can easily find the shortest lap time or the 43 | longest one; 44 | 45 | 46 | Reset the stopwatch widget and the lap times; 47 | 48 | 49 | Time format settings: you can choose the stopwatch granularity; 50 | 51 | 52 | Times saving and resuming: you can save the stopwatch status and 53 | resume it later; 54 | 55 | 56 | Font customization: you can choose the fonts for each of the stopwatch 57 | digits; 58 | 59 | 60 | Color customization: you can choose the color for the stopwatch digits 61 | and the stopwatch background; 62 | 63 | 64 | Lap times export: you can export the lap times on a file using the JSON 65 | or CSV format. 66 | 67 | 68 |
69 |
70 | 71 | AUTHOR 72 | The KRONOMETER was written by Elvis Angelaccio <elvis.angelaccio@kde.org>. 73 | 74 | This manual page was written by Joao Eriberto Mota Filho <eriberto@debian.org> 75 | for the Debian project (but may be used by others). 76 | 77 |
78 | 79 | -------------------------------------------------------------------------------- /autotests/core/testtimeformat.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2015 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "testtimeformat.h" 8 | #include "timeformat.h" 9 | 10 | #include 11 | 12 | void TestTimeFormat::testDefaultFormat() 13 | { 14 | TimeFormat timeFormat; 15 | QTime t {0, 0}; 16 | 17 | QCOMPARE(timeFormat.format(t), QStringLiteral("00:00.00")); 18 | QCOMPARE(timeFormat.secondFractions(), TimeFormat::UpToHundredths); 19 | QVERIFY(!timeFormat.hasHours()); 20 | QVERIFY(timeFormat.hasMinutes()); 21 | QVERIFY(timeFormat.hasFractions()); 22 | } 23 | 24 | void TestTimeFormat::testFullFormat() 25 | { 26 | TimeFormat timeFormat {true, true, TimeFormat::UpToMilliseconds}; 27 | QTime t {0, 0}; 28 | 29 | QCOMPARE(timeFormat.format(t), QStringLiteral("00:00:00.000")); 30 | QCOMPARE(timeFormat.secondFractions(), TimeFormat::UpToMilliseconds); 31 | QVERIFY(timeFormat.hasHours()); 32 | QVERIFY(timeFormat.hasMinutes()); 33 | QVERIFY(timeFormat.hasFractions()); 34 | } 35 | 36 | void TestTimeFormat::testMinimalFormat() 37 | { 38 | TimeFormat timeFormat {false, false, TimeFormat::NoFractions}; 39 | QTime t {0, 0}; 40 | 41 | QCOMPARE(timeFormat.format(t), QStringLiteral("00")); 42 | QCOMPARE(timeFormat.secondFractions(), TimeFormat::NoFractions); 43 | QVERIFY(!timeFormat.hasHours()); 44 | QVERIFY(!timeFormat.hasMinutes()); 45 | QVERIFY(!timeFormat.hasFractions()); 46 | } 47 | 48 | void TestTimeFormat::testNoDividers() 49 | { 50 | TimeFormat timeFormat; 51 | QTime t {0, 0}; 52 | 53 | timeFormat.showDividers(false); 54 | 55 | QCOMPARE(timeFormat.format(t), QStringLiteral("000000")); 56 | } 57 | 58 | void TestTimeFormat::testEquality() 59 | { 60 | TimeFormat timeFormat1; 61 | TimeFormat timeFormat2; 62 | 63 | QCOMPARE(timeFormat1, timeFormat2); 64 | } 65 | 66 | void TestTimeFormat::testInequality() 67 | { 68 | TimeFormat timeFormat1; 69 | TimeFormat timeFormat2 {true, false}; 70 | 71 | QVERIFY(timeFormat1 != timeFormat2); 72 | } 73 | 74 | void TestTimeFormat::testOverrideHours() 75 | { 76 | TimeFormat timeFormat {false, true, TimeFormat::NoFractions}; 77 | QTime t {0, 0}; 78 | 79 | QCOMPARE(timeFormat.format(t), QStringLiteral("00:00")); 80 | 81 | timeFormat.overrideHours(); 82 | 83 | QCOMPARE(timeFormat.format(t), QStringLiteral("00:00:00")); 84 | } 85 | 86 | void TestTimeFormat::testOverrideMinutes() 87 | { 88 | TimeFormat timeFormat {false, false, TimeFormat::UpToTenths}; 89 | QTime t {0, 0}; 90 | 91 | QCOMPARE(timeFormat.format(t), QStringLiteral("00.0")); 92 | 93 | timeFormat.overrideMinutes(); 94 | 95 | QCOMPARE(timeFormat.format(t), QStringLiteral("00:00.0")); 96 | } 97 | 98 | QTEST_MAIN(TestTimeFormat) 99 | 100 | #include "moc_testtimeformat.cpp" 101 | -------------------------------------------------------------------------------- /src/models/lapmodel.h: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2014 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef LAPMODEL_H 8 | #define LAPMODEL_H 9 | 10 | #include "lap.h" 11 | #include "timeformat.h" 12 | 13 | #include 14 | 15 | class QTime; 16 | 17 | /** 18 | * @brief A LapModel is a Model for lap times. 19 | * A LapModel holds a list of times. Every time is meant to be the absolute time of a lap. 20 | * The model can also show the relative time of the lap, computing the difference between two consecutive absolute times. 21 | */ 22 | class LapModel : public QAbstractTableModel 23 | { 24 | Q_OBJECT 25 | 26 | public: 27 | 28 | enum class Roles 29 | { 30 | LapIdRole = Qt::UserRole, 31 | RelativeTimeRole, 32 | AbsoluteTimeRole, 33 | NoteRole, 34 | LapRole 35 | }; 36 | 37 | explicit LapModel(QObject *parent = nullptr); 38 | 39 | int rowCount(const QModelIndex& parent = {}) const override; 40 | int columnCount(const QModelIndex& parent = {}) const override; 41 | QVariant data(const QModelIndex& index, int role) const override; 42 | QVariant headerData(int section, Qt::Orientation orientation, int role) const override; 43 | bool setData(const QModelIndex& index, const QVariant& value, int role) override; 44 | Qt::ItemFlags flags(const QModelIndex& index) const override; 45 | 46 | /** 47 | * Update the lap times format used by the model. 48 | * @param format The times format to be used. 49 | */ 50 | void setTimeFormat(const TimeFormat& format); 51 | 52 | /** 53 | * Insert a new Lap object to the end of the model. 54 | * @param lap The new Lap object. 55 | */ 56 | void append(const Lap& lap); 57 | 58 | /** 59 | * @return Whether the model does not hold any lap. 60 | */ 61 | bool isEmpty() const; 62 | 63 | /** 64 | * @return The index of the column for the given role. 65 | */ 66 | int columnForRole(Roles role) const; 67 | 68 | public Q_SLOTS: 69 | 70 | /** 71 | * Add a new absolute lap time to the model. 72 | * @param lapTime The absolute time of the new lap. 73 | */ 74 | void addLap(const QTime& lapTime); 75 | 76 | /** 77 | * Clear all the model data 78 | */ 79 | void clear(); 80 | 81 | private: 82 | 83 | const QVector m_roles {Roles::LapIdRole, Roles::RelativeTimeRole, Roles::AbsoluteTimeRole, Roles::NoteRole}; 84 | 85 | QVector m_laps; /** Lap times */ 86 | TimeFormat m_timeFormat; /** Current lap times format */ 87 | 88 | /** 89 | * Reload the model data. 90 | */ 91 | void reload(); 92 | 93 | /** 94 | * @return The role for the given column. 95 | */ 96 | Roles roleForColumn(int column) const; 97 | 98 | Q_DISABLE_COPY(LapModel) 99 | }; 100 | 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /src/gui/digitdisplay.h: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2014 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef DIGITDISPLAY_H 8 | #define DIGITDISPLAY_H 9 | 10 | #include 11 | 12 | class QLabel; 13 | 14 | /** 15 | * @brief A custom widget displaying up to three digits. 16 | * This widget is meant to be used as a QLabel replacement to display the digits 17 | * of a timer component (minutes, seconds, etc.). By default a QLabel displays 18 | * a single text and if the font is not monospace this might look bad when the 19 | * text is refreshed very quickly, as in a stopwatch timer. This widget instead 20 | * displays the text by splitting it into up to three different strings, displayed 21 | * in different QLabels within a horizontal layout. (i.e. simulating a monospace font 22 | * using adequate padding). 23 | */ 24 | class DigitDisplay : public QWidget 25 | { 26 | Q_OBJECT 27 | 28 | public: 29 | 30 | enum class Digits 31 | { 32 | One, /**< Display one digit. */ 33 | Two, /**< Display two digits. */ 34 | Three, /**< Display three digits. */ 35 | None /**< Display no digit. */ 36 | }; 37 | 38 | explicit DigitDisplay(QWidget *parent = nullptr, Digits digits = Digits::None); 39 | 40 | /** 41 | * Set the number of digits to be displayed. 42 | * @param digits The number of digits to be displayed. 43 | */ 44 | void setDigits(Digits digits); 45 | 46 | /** 47 | * The digits to be displayed. 48 | * The input string shall have a length equal to the internal digit counter. 49 | * Otherwise nothing is displayed. 50 | * @param digits The digits string to be displayed. 51 | */ 52 | void showDigits(const QString& digits) const; 53 | 54 | /** 55 | * Set a custom font for the widget labels. 56 | * @param font The custom font to set. 57 | */ 58 | void setFont(const QFont& font); 59 | 60 | virtual QSize minimumSizeHint() const override; 61 | 62 | private: 63 | 64 | QLabel *m_leftmostDigit; 65 | QLabel *m_centerDigit; 66 | QLabel *m_rightmostDigit; 67 | 68 | QFont m_displayFont; 69 | Digits m_digits; 70 | 71 | /** 72 | * @return Whether the length of @p text is consistent with the display digits. 73 | */ 74 | bool isValid(const QString& text) const; 75 | 76 | /** 77 | * Helper function to display a single digit. 78 | * @param digit The digit to be displayed. 79 | */ 80 | void showOneDigit(const QString& digit) const; 81 | 82 | /** 83 | * Helper function to display two digits. 84 | * @param digits The digits to be displayed. 85 | */ 86 | void showTwoDigits(const QString& digits) const; 87 | 88 | /** 89 | * Helper function to display three digits. 90 | * @param digits The digits to be displayed. 91 | */ 92 | void showThreeDigits(const QString& digits) const; 93 | 94 | Q_DISABLE_COPY(DigitDisplay) 95 | }; 96 | 97 | #endif 98 | -------------------------------------------------------------------------------- /src/core/session.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2015 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "session.h" 8 | 9 | #include 10 | #include 11 | 12 | Session::Session(int time, const QDateTime& date) : 13 | m_time {time}, 14 | m_date {date} 15 | {} 16 | 17 | void Session::setName(const QString& name) 18 | { 19 | m_name = name; 20 | } 21 | 22 | void Session::setNote(const QString& note) 23 | { 24 | m_note = note; 25 | } 26 | 27 | void Session::setTime(int time) 28 | { 29 | m_time = time; 30 | } 31 | 32 | void Session::setDate(const QDateTime& date) 33 | { 34 | m_date = date; 35 | } 36 | 37 | void Session::setIsOutdated(bool isOutdated) 38 | { 39 | m_isOutdated = isOutdated; 40 | } 41 | 42 | QString Session::name() const 43 | { 44 | return m_name; 45 | } 46 | 47 | QString Session::note() const 48 | { 49 | return m_note; 50 | } 51 | 52 | int Session::time() const 53 | { 54 | return m_time; 55 | } 56 | 57 | QDateTime Session::date() const 58 | { 59 | return m_date; 60 | } 61 | 62 | bool Session::isOutdated() const 63 | { 64 | return m_isOutdated; 65 | } 66 | 67 | QVector Session::laps() const 68 | { 69 | return m_laps; 70 | } 71 | 72 | bool Session::isEmpty() const 73 | { 74 | return m_time == 0; 75 | } 76 | 77 | void Session::addLap(const Lap& lap) 78 | { 79 | m_laps.append(lap); 80 | } 81 | 82 | void Session::clear() 83 | { 84 | m_time = 0; 85 | m_laps.clear(); 86 | } 87 | 88 | void Session::write(QJsonObject& json) const 89 | { 90 | json[QStringLiteral("name")] = m_name; 91 | json[QStringLiteral("note")] = m_note; 92 | json[QStringLiteral("time")] = m_time; 93 | json[QStringLiteral("date")] = m_date.toString(Qt::ISODate); 94 | 95 | auto laps = QJsonArray {}; 96 | 97 | for (const auto& lap : m_laps) { 98 | auto object = QJsonObject {}; 99 | lap.write(object); 100 | laps.append(object); 101 | } 102 | 103 | json[QStringLiteral("laps")] = laps; 104 | } 105 | 106 | Session Session::fromJson(const QJsonObject& json) 107 | { 108 | auto session = Session {}; 109 | 110 | session.m_name = json[QStringLiteral("name")].toString(); 111 | session.m_note = json[QStringLiteral("note")].toString(); 112 | session.m_time = json[QStringLiteral("time")].toInt(); 113 | session.m_date = QDateTime::fromString(json[QStringLiteral("date")].toString(), Qt::ISODate); 114 | 115 | const auto laps = json[QStringLiteral("laps")].toArray(); 116 | for (const auto& lap : laps) { 117 | session.addLap(Lap::fromJson(lap.toObject())); 118 | } 119 | 120 | return session; 121 | } 122 | 123 | bool Session::operator==(const Session& right) const 124 | { 125 | return m_date == right.m_date; 126 | } 127 | 128 | bool Session::operator!=(const Session& right) const 129 | { 130 | return !(*this == right); 131 | } 132 | 133 | -------------------------------------------------------------------------------- /po/sv/docs/kronometer/man-kronometer.1.docbook: -------------------------------------------------------------------------------- 1 | 2 | 4 | ]> 5 | 6 | 7 | 8 | 2016-04-10 10 | kronometer 2.0 12 | 13 | 14 | 15 | kronometer 17 | 1 19 | April 2016 21 | Kronometer 2.1.0 23 | 24 | 25 | kronometer 27 | Tidtagarurprogram 29 | 30 | 31 | 32 | 33 | kronometer 35 | 36 | 37 | 38 | Beskrivning 41 | Kronometer är ett tidtagarurprogram (stoppur/kronometer). 43 | 44 | Huvudfunktionerna i Kronometer är följande: 46 |
47 | 48 | 49 | Starta, pausa, återstarta tidtagarurets grafiska komponent, 51 | 52 | 53 | Varvtider: Det går att lagra tidtagarurets tid när man vill, 55 | 56 | 57 | Sortering av varvtider: Det är enkelt att hitta den kortaste eller längsta varvtiden, 59 | 60 | 61 | Nollställ tidtagarurets grafiska komponent och varvtiderna, 63 | 64 | 65 | Inställning av tidsformat: Det går att välja tidtagarurets upplösning, 67 | 68 | 69 | Spara och återstarta tider: Det går att spara tidtagarurets status och senare återstarta det, 71 | 72 | 73 | Anpassning av teckensnitt: Det går att välja teckensnitten för varje siffra i tidtagaruret, 75 | 76 | 77 | Anpassning av färger: Det går att välja färg för tidtagarurets siffror och bakgrund, 79 | 80 | 81 | Export av varvtider: Det går att exportera varvtider till en fil med JSON- eller CSV-format. 83 | 84 | 85 |
86 |
87 | 88 | Upphovsman 91 | Kronometer är skrivet av Elvis Angelaccio <elvis.angelaccio@kde.org>. 93 | 94 | Den här manualsidan är skriven av Joao Eriberto Mota Filho <eriberto@debian.org> för Debians GNU/Linux-system (men kan användas av andra). 96 | 97 |
98 | 99 | -------------------------------------------------------------------------------- /po/it/docs/kronometer/man-kronometer.1.docbook: -------------------------------------------------------------------------------- 1 | 2 | 4 | ]> 5 | 6 | 7 | 8 | 2016-04-10 10 | kronometer 2.0 12 | 13 | 14 | 15 | kronometer 17 | 1 19 | Aprile 2016 21 | KRONOMETER 2.1.0 23 | 24 | 25 | kronometer 27 | cronometro 29 | 30 | 31 | 32 | 33 | kronometer 35 | 36 | 37 | 38 | DESCRIZIONE 41 | Kronometer è un cronometro. 43 | 44 | Le principali funzionalità di Kronometer sono: 46 |
47 | 48 | 49 | Oggetto per avviare, mettere in pausa e riavviare il cronometro; 51 | 52 | 53 | Registrazione dei giri: puoi catturare il tempo del cronometro ogni volta che vuoi; 55 | 56 | 57 | Ordinamento dei tempi sul giro: puoi facilmente trovare il tempo sul giro più breve o più lungo; 59 | 60 | 61 | Oggetto per azzerare il cronometro e i tempi sul giro; 63 | 64 | 65 | Impostazioni del formato del tempo: puoi scegliere la risoluzione del cronometro; 67 | 68 | 69 | Salvataggio e ripristino dei tempi: puoi salvare lo stato del cronometro e ripristinarlo più avanti; 71 | 72 | 73 | Configurazione dei caratteri: puoi scegliere i caratteri per ciascuna cifra del cronometro; 75 | 76 | 77 | Configurazione dei colori: puoi scegliere il colore delle cifre e dello sfondo del cronometro; 79 | 80 | 81 | Esportazione dei tempi sul giro: puoi esportare i tempi sul giro su file nei formati JSON o CSV. 83 | 84 | 85 |
86 |
87 | 88 | AUTORE 91 | Kronometer è stato scritto da Elvis Angelaccio <elvis.angelaccio@kde.org>. 93 | 94 | Questa pagina di manuale è stata scritta da João Eriberto Mota Filho <eriberto@debian.org> per il progetto Debian (ma fruibile da altri). 96 | 97 |
98 | 99 | -------------------------------------------------------------------------------- /po/nl/docs/kronometer/man-kronometer.1.docbook: -------------------------------------------------------------------------------- 1 | 2 | 4 | ]> 5 | 6 | 7 | 8 | 2016-04-10 10 | kronometer 2.0 12 | 13 | 14 | 15 | kronometer 17 | 1 19 | April 2016 21 | KRONOMETER 2.1.0 23 | 24 | 25 | kronometer 27 | stopwatch-toepassing 29 | 30 | 31 | 32 | 33 | kronometer 35 | 36 | 37 | 38 | BESCHRIJVING 41 | Kronometer is een stopwatch (timer/chronometer) toepassing. 43 | 44 | De hoofdfuncties van Kronometer zijn als volgt: 46 |
47 | 48 | 49 | Start/pauzeer/hervat het stopwatch-widget; 51 | 52 | 53 | Rondetijden opnemen: u kunt de tijd van de stopwatch opnemen wanneer u wilt; 55 | 56 | 57 | Rondetijden sorteren: u kunt gemakkelijk de kortste of de langste rondetijd vinden; 59 | 60 | 61 | Reset het stopwatch-widget en de rondetijden; 63 | 64 | 65 | Instellingen van de tijdopmaak: u kunt de nauwkeurigheid van de stopwatch kiezen; 67 | 68 | 69 | Tijden opslaan en hervatten: u kunt de status van de stopwatch opslaan en deze later hervatten; 71 | 72 | 73 | Aanpassen van het lettertype: u kunt het lettertype van elk van de cijfers van de stopwatch kiezen; 75 | 76 | 77 | Aanpassen van kleur: u kunt de kleur van de cijfers en de achtergrond van de stopwatch kiezen; 79 | 80 | 81 | Exporteren van rondetijden: u kunt de rondetijden exporteren in een bestand met het JSON- of CSV-formaat. 83 | 84 | 85 |
86 |
87 | 88 | AUTEUR 91 | KRONOMETER is geschreven door Elvis Angelaccio <elvis.angelaccio@kde.org>. 93 | 94 | Deze manpagina is gemaakt door Joao Eriberto Mota Filho <eriberto@debian.org> voor het Debian GNU/Linux systeem (maar kan worden gebruikt door anderen). 96 | 97 |
98 | 99 | -------------------------------------------------------------------------------- /po/de/docs/kronometer/man-kronometer.1.docbook: -------------------------------------------------------------------------------- 1 | 2 | 4 | ]> 5 | 6 | 7 | 8 | 2016-04-10 10 | kronometer 2.0 12 | 13 | 14 | 15 | kronometer 17 | 1 19 | April 2016 21 | KRONOMETER 2.1.0 23 | 24 | 25 | kronometer 27 | Stoppuhrprogramm 29 | 30 | 31 | 32 | 33 | kronometer 35 | 36 | 37 | 38 | Beschreibung 41 | Kronometer ist eine Anwendung für die Zeitmessung (Stoppuhr). 43 | 44 | Kronometer hat folgende wichtige Funktionen: 46 |
47 | 48 | 49 | Das Stoppuhr-Miniprogramm starten/anhalten/fortsetzen 51 | 52 | 53 | Zwischenzeiten: Sie können eine Zeit festhalten, wann sie möchten 55 | 56 | 57 | Zwischenzeiten sortieren: so finden Sie einfach die schnellste oder langsamste Zeit 59 | 60 | 61 | Das Stoppuhr-Miniprogramm sowie Zwischenzeiten zurücksetzen 63 | 64 | 65 | Zeitformat einstellen: Sie können die Genauigkeit der Stoppuhr einstellen 67 | 68 | 69 | Zeiten speichern und fortsetzen: Sie können den Status der Stoppuhr speichern und später fortsetzen 71 | 72 | 73 | Eigene Schriftarten: Sie können für jede Ziffer der Stoppuhr eine Schriftart wählen 75 | 76 | 77 | Eigene Farben: Sie können für die Ziffern und den Hintergrund der Stoppuhr die Farbe wählen 79 | 80 | 81 | Zwischenzeiten-Export: Sie können die Zwischenzeiten in den Formaten JSON oder CVS in eine Datei speichern. 83 | 84 | 85 |
86 |
87 | 88 | Autor 91 | Das Programm Kronometer wurde von Elvis Angelaccio <elvis.angelaccio@kde.orgt> geschrieben. 93 | 94 | Diese Handbuchseite wurde von Joao Eriberto Mota Filho <eriberto@debian.org> für das Debian-Projekt geschrieben, darf aber auch von anderen verwendet werden. 96 | 97 |
98 | 99 | -------------------------------------------------------------------------------- /po/pt/docs/kronometer/man-kronometer.1.docbook: -------------------------------------------------------------------------------- 1 | 2 | 4 | ]> 5 | 6 | 7 | 8 | 2016-04-10 10 | kronometer 2.0 12 | 13 | 14 | 15 | kronometer 17 | 1 19 | Abril de 2016 21 | KRONOMETER 2.1.0 23 | 24 | 25 | kronometer 27 | aplicação de cronómetro 29 | 30 | 31 | 32 | 33 | kronometer 35 | 36 | 37 | 38 | DESCRIÇÃO 41 | O Kronometer é uma aplicação de cronómetros. 43 | 44 | As funcionalidades principais do Kronometer são as seguintes: 46 |
47 | 48 | 49 | Iniciar/pausar/retomar o item do cronómetro; 51 | 52 | 53 | Gravação de voltas: poderá capturar os tempos do cronómetro sempre que desejar; 55 | 56 | 57 | Ordenação dos tempos de voltas: poderá encontrar facilmente o tempo mais curto ou mais longo; 59 | 60 | 61 | Reiniciar o cronómetro e os tempos das voltas; 63 | 64 | 65 | Configuração do formato das horas: poderá escolher a granularidade do relógio; 67 | 68 | 69 | Gravação e recuperação dos tempo: poderá gravar o estado do cronómetro e retomá-lo posteriormente; 71 | 72 | 73 | Personalização dos tipos de letra: poderá escolher os tipos de letra para cada um dos números do cronómetro; 75 | 76 | 77 | Personalização de cores: poderá escolher a cor dos números do cronómetro e o fundo do mesmo; 79 | 80 | 81 | Exportação dos tempos das voltas: poderá exportar os tempos das voltas para um ficheiro no formato CSV ou JSON. 83 | 84 | 85 |
86 |
87 | 88 | AUTOR 91 | O KRONOMETER foi criado por Elvis Angelaccio <elvis.angelaccio@kde.org>. 93 | 94 | Esta página do manual foi criada por João Eriberto Mota Filho <eriberto@debian.org> para o projecto Debian (mas poderá ser usado por outros). 96 | 97 |
98 | 99 | -------------------------------------------------------------------------------- /autotests/core/testsession.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2015 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include 8 | #include "testsession.h" 9 | #include "session.h" 10 | 11 | void TestSession::testDefaultSession() 12 | { 13 | Session session; 14 | 15 | QCOMPARE(session.time(), 0); 16 | QVERIFY(session.isEmpty()); 17 | QVERIFY(!session.isOutdated()); 18 | QVERIFY(session.laps().isEmpty()); 19 | QVERIFY(session.name().isNull()); 20 | QVERIFY(session.note().isEmpty()); 21 | } 22 | 23 | void TestSession::testTime() 24 | { 25 | int time = 1000; 26 | Session session {time}; 27 | 28 | QCOMPARE(session.time(), time); 29 | } 30 | 31 | void TestSession::testName() 32 | { 33 | Session session; 34 | auto test = QLatin1String("test"); 35 | 36 | session.setName(test); 37 | 38 | QCOMPARE(session.name(), test); 39 | } 40 | 41 | void TestSession::testNote() 42 | { 43 | Session session; 44 | auto test = QLatin1String("test"); 45 | 46 | session.setNote(test); 47 | 48 | QCOMPARE(session.note(), test); 49 | } 50 | 51 | void TestSession::testDate() 52 | { 53 | auto date = QDateTime::currentDateTime(); 54 | Session session {0, date}; 55 | 56 | QCOMPARE(session.date(), date); 57 | } 58 | 59 | void TestSession::testLaps() 60 | { 61 | Session session; 62 | 63 | const auto laps = QVector {Lap {{1, 30}}, Lap {{2, 0}}, Lap {{1, 45}}}; 64 | for (const auto& lap : laps) { 65 | session.addLap(lap); 66 | } 67 | 68 | QCOMPARE(session.laps().size(), laps.size()); 69 | } 70 | 71 | void TestSession::testEquality() 72 | { 73 | auto date = QDateTime::currentDateTime(); 74 | 75 | Session session1 {0, date}; 76 | Session session2 {1000, date}; 77 | 78 | QCOMPARE(session1, session2); 79 | } 80 | 81 | void TestSession::testInequality() 82 | { 83 | Session session1 {0, QDateTime::currentDateTime()}; 84 | QTest::qSleep(100); 85 | Session session2 {0, QDateTime::currentDateTime()}; 86 | 87 | QVERIFY(session1 != session2); 88 | } 89 | 90 | void TestSession::testJson() 91 | { 92 | auto date = QDateTime::currentDateTime(); 93 | Session session1 {1000, QDateTime::fromString(date.toString(Qt::ISODate), Qt::ISODate)}; 94 | session1.setName(QStringLiteral("test-name")); 95 | session1.setNote(QStringLiteral("test-note")); 96 | 97 | const auto laps = QVector {Lap {{1, 30}}, Lap {{2, 0}}, Lap {{1, 45}}}; 98 | for (const auto& lap : laps) { 99 | session1.addLap(lap); 100 | } 101 | 102 | QJsonObject json; 103 | session1.write(json); 104 | 105 | Session session2 = Session::fromJson(json); 106 | 107 | QCOMPARE(session1, session2); 108 | QCOMPARE(session1.time(), session2.time()); 109 | QCOMPARE(session1.name(), session2.name()); 110 | QCOMPARE(session1.note(), session2.note()); 111 | QCOMPARE(session1.laps().size(), session2.laps().size()); 112 | } 113 | 114 | QTEST_MAIN(TestSession) 115 | 116 | #include "moc_testsession.cpp" 117 | -------------------------------------------------------------------------------- /po/pt_BR/docs/kronometer/man-kronometer.1.docbook: -------------------------------------------------------------------------------- 1 | 2 | 4 | ]> 5 | 6 | 7 | 8 | 10/04/2016 10 | kronometer 2.0 12 | 13 | 14 | 15 | kronometer 17 | 1 19 | April de 2016 21 | KRONOMETER 2.1.0 23 | 24 | 25 | kronometer 27 | aplicativo de cronômetro 29 | 30 | 31 | 32 | 33 | kronometer 35 | 36 | 37 | 38 | DESCRIÇÃO 41 | Kronometer é um aplicativo de cronômetro e temporizador. 43 | 44 | As principais funcionalidades do Kronometer são as seguintes: 46 |
47 | 48 | 49 | Iniciar/pausar/continuar o cronômetro; 51 | 52 | 53 | Registro de voltas: Você pode capturar o tempo do cronômetro sempre que quiser; 55 | 56 | 57 | Ordenação dos tempos das voltas: Você pode localizar facilmente o tempo mais curto ou mais longo; 59 | 60 | 61 | Reiniciar o cronômetro e os tempos das voltas; 63 | 64 | 65 | Configuração do formato dos tempos: Você pode escolher a granularidade dos cronômetros; 67 | 68 | 69 | Gravação e continuação dos tempos: Você pode salvar o status do cronômetro para continuar mais tarde; 71 | 72 | 73 | Personalização de fontes: Você pode escolher as fontes para cada um dos dígitos do cronômetro; 75 | 76 | 77 | Personalização de cores: Você pode escolher a cor dos dígitos e do fundo do cronômetro; 79 | 80 | 81 | Exportação dos tempos das voltas: Você pode exportar os tempos das voltas para um arquivo no formato JSON ou CSV. 83 | 84 | 85 |
86 |
87 | 88 | AUTOR 91 | O KRONOMETER foi criado por Elvis Angelaccio <elvis.angelaccio@kde.org>. 93 | 94 | Esta página de manual foi escrita por Joao Eriberto Mota Filho <eriberto@debian.org> para o projeto Debian (mas também pode ser usada por outros). 96 | 97 |
98 | 99 | -------------------------------------------------------------------------------- /po/ca/docs/kronometer/man-kronometer.1.docbook: -------------------------------------------------------------------------------- 1 | 2 | 4 | ]> 5 | 6 | 7 | 8 | 10 d'abril de 2016 10 | kronometer 2.0 12 | 13 | 14 | 15 | kronometer 17 | 1 19 | Abril de 2016 21 | Kronometer 2.1.0 23 | 24 | 25 | kronometer 27 | aplicació de cronòmetre 29 | 30 | 31 | 32 | 33 | kronometer 35 | 36 | 37 | 38 | Descripció 41 | El Kronometer és una aplicació de cronòmetre. 43 | 44 | Les característiques principals del Kronometer són les següents: 46 |
47 | 48 | 49 | Engega/pausa/continua el giny de cronòmetre; 51 | 52 | 53 | Enregistrament de les voltes: podeu capturar el temps del cronòmetre quan vulgueu; 55 | 56 | 57 | Ordenació dels temps per volta: podeu trobar amb facilitat els temps per volta més ràpida o més lenta; 59 | 60 | 61 | Inicialitzar el giny de cronòmetre i els temps per volta; 63 | 64 | 65 | Arranjament pel format del temps: podeu triar el nivell de detall del cronòmetre; 67 | 68 | 69 | Desament i continuació dels temps: podeu desar l'estat del cronòmetre per a continuar més tard; 71 | 72 | 73 | Personalització de les lletres: podeu triar les lletres per a cadascun dels dígits del cronòmetre; 75 | 76 | 77 | Personalització dels colors: podeu triar el color per als dígits del cronòmetre i el fons del cronòmetre; 79 | 80 | 81 | Exportació dels temps per volta: podeu exportar els temps per volta a un fitxer usant el format JSON o CSV. 83 | 84 | 85 |
86 |
87 | 88 | Autor 91 | El Kronometer ha estat escrit per l'Elvis Angelaccio <elvis.angelaccio@kde.org>. 93 | 94 | Aquesta pàgina de manual ha estat escrita per en Joao Eriberto Mota Filho <eriberto@debian.org> pel projecte Debian (però la poden emprar els altres). 96 | 97 |
98 | 99 | -------------------------------------------------------------------------------- /src/models/sessionmodel.h: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2015 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef SESSIONMODEL_H 8 | #define SESSIONMODEL_H 9 | 10 | #include "session.h" 11 | 12 | #include 13 | 14 | /** 15 | * @brief A SessionModel is a Model for sessions. 16 | */ 17 | class SessionModel : public QAbstractTableModel 18 | { 19 | Q_OBJECT 20 | 21 | public: 22 | 23 | enum class Roles 24 | { 25 | SessionIdRole = Qt::UserRole, 26 | NameRole, 27 | DateRole, 28 | NoteRole, 29 | SessionRole 30 | }; 31 | 32 | explicit SessionModel(QObject *parent = nullptr); 33 | 34 | int rowCount(const QModelIndex& parent = {}) const override; 35 | int columnCount(const QModelIndex& parent = {}) const override; 36 | QVariant data(const QModelIndex& index, int role) const override; 37 | QVariant headerData(int section, Qt::Orientation orientation, int role) const override; 38 | bool setData(const QModelIndex& index, const QVariant& value, int role) override; 39 | Qt::ItemFlags flags(const QModelIndex& index) const override; 40 | bool removeRows(int row, int count, const QModelIndex& parent) override; 41 | 42 | /** 43 | * Insert a new Session object to the end of the model. 44 | * @param session The new Session object. 45 | */ 46 | void append(const Session& session); 47 | 48 | /** 49 | * Update the given session in the model and updates its date. 50 | * If the session does not belong to the model, nothing happens. 51 | * @param session The session to be updated. 52 | */ 53 | void update(Session& session); 54 | 55 | /** 56 | * @return Whether the model does not hold any session. 57 | */ 58 | bool isEmpty() const; 59 | 60 | /** 61 | * Whether the given index refers to an editable value in the model. 62 | * @param index An index of the model. 63 | * @return True if the underlying data is editable, false otherwise. 64 | */ 65 | bool isEditable(const QModelIndex& index) const; 66 | 67 | /** 68 | * Load the model from the given JSON object. 69 | * @param json A JSON object. 70 | */ 71 | void read(const QJsonObject& json); 72 | 73 | private Q_SLOTS: 74 | 75 | /** 76 | * Update the global sessions file with the data in the model. 77 | */ 78 | void slotWriteData(); 79 | 80 | private: 81 | 82 | /** 83 | * @return The index of the column for the given role. 84 | */ 85 | int columnForRole(Roles role) const; 86 | 87 | /** 88 | * @return The role for the given column. 89 | */ 90 | Roles roleForColumn(int column) const; 91 | 92 | /** 93 | * @return The list of sessions as json array. 94 | */ 95 | QJsonArray jsonSessions() const; 96 | 97 | const QVector m_roles {Roles::SessionIdRole, Roles::NameRole, Roles::DateRole, Roles::NoteRole}; 98 | 99 | QVector m_sessionList; /** Sessions in the model. */ 100 | 101 | Q_DISABLE_COPY(SessionModel) 102 | }; 103 | 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /src/core/lap.h: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2014 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef LAP_H 8 | #define LAP_H 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | class QJsonObject; 15 | 16 | /** 17 | * @brief A Lap is a specific time instant. 18 | * This class is a wrapper for a QTime object and some strings, which are useful to describe it. 19 | */ 20 | class Lap 21 | { 22 | 23 | public: 24 | 25 | explicit Lap(const QTime& lap = {0, 0}); 26 | 27 | /** 28 | * The specific lap's time 29 | * @return The underlying lap's time object 30 | */ 31 | QTime time() const; 32 | 33 | /** 34 | * Compute the difference with the given Lap. 35 | * @param lap A Lap object. 36 | * @return QTime difference if the given Lap is "greater", otherwise a zero QTime. 37 | */ 38 | QTime timeTo(const Lap& lap) const; 39 | 40 | /** 41 | * Set the lap's relative time 42 | * @param rel The string to be set as relative time 43 | */ 44 | void setRelativeTime(const QString& rel); 45 | 46 | /** 47 | * The relative lap time 48 | * @return String representation of the relative lap time 49 | */ 50 | QString relativeTime() const; 51 | 52 | /** 53 | * Set the lap's absolute time 54 | * @param abs The string to be set as absolute lap time 55 | */ 56 | void setAbsoluteTime(const QString& abs); 57 | 58 | /** 59 | * The absolute lap time 60 | * @return String representation of the absolute lap time 61 | */ 62 | QString absoluteTime() const; 63 | 64 | /** 65 | * Set the lap's annotation 66 | * @param note The note to be set 67 | */ 68 | void setNote(const QString& note); 69 | 70 | /** 71 | * The lap's annotation 72 | * @return The lap's annotation 73 | */ 74 | QString note() const; 75 | 76 | /** 77 | * The underlying lap's raw data 78 | * @return Lap's raw data counter 79 | */ 80 | int raw() const; 81 | 82 | /** 83 | * Serialize the lap on the given JSON object. 84 | * @param json A JSON object. 85 | */ 86 | void write(QJsonObject& json) const; 87 | 88 | /** 89 | * Deserialize a lap from the given JSON object. 90 | * @param json A JSON object. 91 | * @return A deserialized lap. 92 | */ 93 | static Lap fromJson(const QJsonObject& json); 94 | 95 | /** 96 | * Create a new Lap object from raw data 97 | * @param rawData The raw data counter of the new Lap 98 | * @return A new Lap object created from the given raw data 99 | */ 100 | static Lap fromRawData(int rawData); 101 | 102 | private: 103 | 104 | QTime m_time; /** The specific lap time */ 105 | QString m_relativeTime; /** String representation of the relative lap time, i.e. compared to another lap */ 106 | QString m_absoluteTime; /** String representation of the specific (absolute) lap time */ 107 | QString m_note; /** Custom lap annotation */ 108 | }; 109 | 110 | Q_DECLARE_METATYPE(Lap) 111 | 112 | #endif 113 | -------------------------------------------------------------------------------- /po/es/docs/kronometer/man-kronometer.1.docbook: -------------------------------------------------------------------------------- 1 | 2 | 4 | ]> 5 | 6 | 7 | 8 | 2016-04-10 10 | kronometer 2.0 12 | 13 | 14 | 15 | kronometer 17 | 1 19 | Abril de 2016 21 | KRONOMETER 2.1.0 23 | 24 | 25 | kronometer 27 | aplicación de cronómetro 29 | 30 | 31 | 32 | 33 | kronometer 35 | 36 | 37 | 38 | DESCRIPCIÓN 41 | Kronometer es una aplicación de cronómetro (temporizador/cronómetro). 43 | 44 | Las funciones principales de Kronometer son las siguientes: 46 |
47 | 48 | 49 | Iniciar, pausar y continuar el elemento gráfico de cronómetro; 51 | 52 | 53 | Grabación de las vueltas: puede capturar los tiempos del cronómetro cuando quiera; 55 | 56 | 57 | Ordenación de los tiempos de las vueltas: puede encontrar con facilidad el tiempo de vuelta más corto o el más largo; 59 | 60 | 61 | Reiniciar el elemento gráfico del cronómetro y los tiempos por vuelta; 63 | 64 | 65 | Preferencias de formato de tiempos: puede escoger el nivel de detalle del cronómetro; 67 | 68 | 69 | Grabación y reanudación de tiempos: puede guardar el estado del cronómetro y reanudar dicho estado posteriormente; 71 | 72 | 73 | Personalización de tipos de letra: puede escoger los tipos de letra para los dígitos del cronómetro; 75 | 76 | 77 | Personalización de colores: puede escoger el color de los dígitos del cronómetro y de su fondo; 79 | 80 | 81 | Exportar los tiempos de las vueltas: puede exportar los tiempos de las vueltas en un archivo usando los formatos JSON o CSV. 83 | 84 | 85 |
86 |
87 | 88 | AUTOR 91 | KRONOMETER fue escrito por Elvis Angelaccio <elvis.angelaccio@kde.org>. 93 | 94 | Esta página de manual fue escrita por Joao Eriberto Mota Filho <eriberto@debian.org> para el proyecto Debian (aunque se puede usar por otros). 96 | 97 |
98 | 99 | -------------------------------------------------------------------------------- /po/uk/docs/kronometer/man-kronometer.1.docbook: -------------------------------------------------------------------------------- 1 | 2 | 4 | ]> 5 | 6 | 7 | 8 | 10 квітня 2016 року 10 | kronometer 2.0 12 | 13 | 14 | 15 | kronometer 17 | 1 19 | квітень 2016 року 21 | KRONOMETER 2.1.0 23 | 24 | 25 | kronometer 27 | програма-секундомір 29 | 30 | 31 | 32 | 33 | kronometer 35 | 36 | 37 | 38 | ОПИС 41 | Kronometer — програма-секундомір (таймер і хронометр). 43 | 44 | Основні можливості Kronometer: 46 |
47 | 48 | 49 | Віджет запуску, призупинення та поновлення відліку секундоміра. 51 | 52 | 53 | Запис даних щодо проходження кіл: ви можете записувати дані секундоміра у довільні моменти часу. 55 | 56 | 57 | Упорядковування за часом проходження кола: ви легко можете встановити найкращий і найгірший часи проходження. 59 | 60 | 61 | Скидання значення на віджеті секундоміра та скидання часу проходження кіл. 63 | 64 | 65 | Можливість зміни форматування часу: ви можете вибрати значення параметрів так, щоб було показано лише потрібні вам дані. 67 | 68 | 69 | Збереження та відновлення записаних даних щодо часу: ви можете записати стан секундоміра на диск і згодом відновити його. 71 | 72 | 73 | Можливість налаштовування шрифтів: ви можете вибрати шрифт для кожного з компонентів числових даних секундоміра. 75 | 76 | 77 | Можливість налаштовування кольорів: ви можете вибрати колір для числових даних секундоміра та колір тла. 79 | 80 | 81 | Експортування даних щодо часу проходження кіл: ви можете експортувати дані до файла у форматі JSON або CSV. 83 | 84 | 85 |
86 |
87 | 88 | Автор 91 | Програму KRONOMETER створено Elvis Angelaccio <elvis.angelaccio@kde.org>. 93 | 94 | Цю сторінку підручника створено Joao Eriberto Mota Filho <eriberto@debian.org> для проєкту Debian (її можна використовувати і у інших проєктах). 96 | 97 |
98 | 99 | -------------------------------------------------------------------------------- /src/core/stopwatch.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2014 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "stopwatch.h" 8 | 9 | #include 10 | #include 11 | 12 | Stopwatch::Stopwatch(QObject *parent) : QObject(parent) {} 13 | 14 | void Stopwatch::setGranularity(Granularity g) 15 | { 16 | m_granularity = g; 17 | 18 | // whenever granularity is changed, also apply that granularity to the timer event 19 | if (m_timerId != INACTIVE_TIMER_ID) { 20 | killTimer(m_timerId); 21 | m_timerId = startTimer(granularity()); 22 | } 23 | } 24 | 25 | bool Stopwatch::isRunning() const 26 | { 27 | return m_state == State::Running; 28 | } 29 | 30 | bool Stopwatch::isPaused() const 31 | { 32 | return m_state == State::Paused; 33 | } 34 | 35 | bool Stopwatch::isInactive() const 36 | { 37 | return m_state == State::Inactive; 38 | } 39 | 40 | int Stopwatch::raw() const 41 | { 42 | return m_accumulator; 43 | } 44 | 45 | bool Stopwatch::initialize(int rawData) 46 | { 47 | if (!isInactive() || rawData <= 0) { 48 | return false; 49 | } 50 | 51 | m_accumulator = rawData; 52 | m_state = State::Paused; 53 | Q_EMIT time(m_accumulator); // it signals that has been deserialized and can be resumed 54 | 55 | return true; 56 | } 57 | 58 | void Stopwatch::start() 59 | { 60 | if (isInactive()) { 61 | m_accumulator = 0; 62 | m_elapsedTimer.start(); 63 | 64 | if (m_timerId == INACTIVE_TIMER_ID) { 65 | m_timerId = startTimer(granularity()); 66 | } 67 | } 68 | else if (isPaused()) { 69 | m_elapsedTimer.restart(); 70 | m_timerId = startTimer(granularity()); 71 | } 72 | 73 | m_state = State::Running; 74 | Q_EMIT running(); 75 | } 76 | 77 | void Stopwatch::pause() 78 | { 79 | if (m_elapsedTimer.isValid()) { 80 | m_accumulator += m_elapsedTimer.elapsed(); 81 | } 82 | 83 | m_elapsedTimer.invalidate(); 84 | m_state = State::Paused; 85 | Q_EMIT paused(); 86 | } 87 | 88 | void Stopwatch::reset() 89 | { 90 | m_elapsedTimer.invalidate(); // if state is running, it will emit a zero time at next timerEvent() call 91 | QCoreApplication::processEvents(); 92 | m_accumulator = 0; 93 | Q_EMIT time(0); 94 | m_state = State::Inactive; 95 | Q_EMIT inactive(); 96 | } 97 | 98 | void Stopwatch::storeLap() 99 | { 100 | auto lapTime = m_accumulator; 101 | 102 | if (m_elapsedTimer.isValid()) { 103 | lapTime += m_elapsedTimer.elapsed(); 104 | } 105 | 106 | const auto zero = QTime {0, 0}; 107 | Q_EMIT lap(zero.addMSecs(lapTime)); 108 | } 109 | 110 | void Stopwatch::timerEvent(QTimerEvent *event) 111 | { 112 | if (event->timerId() != m_timerId) { // forward undesired events 113 | QObject::timerEvent(event); 114 | return; 115 | } 116 | 117 | if (m_elapsedTimer.isValid()) { 118 | Q_EMIT time(m_accumulator + m_elapsedTimer.elapsed()); 119 | } 120 | else { 121 | killTimer(m_timerId); 122 | m_timerId = INACTIVE_TIMER_ID; 123 | } 124 | } 125 | 126 | int Stopwatch::granularity() const 127 | { 128 | return static_cast(m_granularity); 129 | } 130 | 131 | #include "moc_stopwatch.cpp" 132 | -------------------------------------------------------------------------------- /src/core/session.h: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2015 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef SESSION_H 8 | #define SESSION_H 9 | 10 | #include "lap.h" 11 | 12 | #include 13 | #include 14 | 15 | /** 16 | * @brief A session represents a single Kronometer instance. 17 | * A session is made by a stopwatch time, a date timestamp and by zero or more laps. 18 | * An optional name and an optional note are also provided. 19 | */ 20 | class Session 21 | { 22 | 23 | public: 24 | 25 | explicit Session(int time = 0, const QDateTime& date = QDateTime::currentDateTime()); 26 | 27 | /** 28 | * Set the session's name. 29 | * @param name The string to be set as name. 30 | */ 31 | void setName(const QString& name); 32 | 33 | /** 34 | * Set the session's annotation. 35 | * @param note The note to be set. 36 | */ 37 | void setNote(const QString& note); 38 | 39 | /** 40 | * Set the session's stopwatch (raw) time. 41 | * @param time The stopwatch raw time. 42 | */ 43 | void setTime(int time); 44 | 45 | /** 46 | * Set the session's date (timestamp). 47 | * @param date The date to be set as timestamp. 48 | */ 49 | void setDate(const QDateTime& date); 50 | 51 | /** 52 | * Set whether the session data is outdated. 53 | * @param isOutdated Whether the session is outdated. 54 | */ 55 | void setIsOutdated(bool isOutdated); 56 | 57 | /** 58 | * @return The session name. 59 | */ 60 | QString name() const; 61 | 62 | /** 63 | * @return The session note. 64 | */ 65 | QString note() const; 66 | 67 | /** 68 | * @return The session stopwatch raw time. 69 | */ 70 | int time() const; 71 | 72 | /** 73 | * @return The session date. 74 | */ 75 | QDateTime date() const; 76 | 77 | /** 78 | * Whether the session data is outdated. 79 | * @return True if the session is outdated, false otherwise. 80 | */ 81 | bool isOutdated() const; 82 | 83 | /** 84 | * @return The session laps. 85 | */ 86 | QVector laps() const; 87 | 88 | /** 89 | * Whether the session is empty. 90 | * @return True if the session is empty, false otherwise. 91 | */ 92 | bool isEmpty() const; 93 | 94 | /** 95 | * Add a lap to the session. 96 | * @param lap The lap the be added. 97 | */ 98 | void addLap(const Lap& lap); 99 | 100 | /** 101 | * Reset the stopwatch time and remove all the laps from the session. 102 | */ 103 | void clear(); 104 | 105 | /** 106 | * Serialize the session on the given JSON object. 107 | * @param json A JSON object. 108 | */ 109 | void write(QJsonObject& json) const; 110 | 111 | /** 112 | * Deserialize a session from the given JSON object. 113 | * @param json A JSON object. 114 | * @return A deserialized session. 115 | */ 116 | static Session fromJson(const QJsonObject& json); 117 | 118 | bool operator==(const Session& right) const; 119 | bool operator!=(const Session& right) const; 120 | 121 | private: 122 | 123 | QString m_name; /** Session name. */ 124 | QString m_note; /** Custom session annotation. */ 125 | int m_time; /** Session stopwatch time. */ 126 | QDateTime m_date; /** Session date (timestamp of the last update). */ 127 | QVector m_laps; /** Session laps. */ 128 | bool m_isOutdated = false; /** Whether the session data is outdated. */ 129 | }; 130 | 131 | Q_DECLARE_METATYPE(Session) 132 | 133 | #endif 134 | -------------------------------------------------------------------------------- /src/gui/kronometer.kcfg: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | QGuiApplication 8 | QPalette 9 | QFontDatabase 10 | "timeformat.h" 11 | 12 | 13 | 14 | 15 | 16 | false 17 | 18 | 19 | false 20 | 21 | 22 | true 23 | 24 | 25 | true 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | TimeFormat::UpToHundredths 35 | 36 | 37 | true 38 | 39 | 40 | false 41 | 42 | 43 | true 44 | 45 | 46 | true 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | TimeFormat::UpToHundredths 56 | 57 | 58 | false 59 | 60 | 61 | true 62 | 63 | 64 | true 65 | 66 | 67 | 68 | 69 | 70 | 71 | QFont defaultFont(QFontDatabase::systemFont(QFontDatabase::GeneralFont).family(), 54); 72 | 73 | defaultFont 74 | 75 | 76 | defaultFont 77 | 78 | 79 | defaultFont 80 | 81 | 82 | defaultFont 83 | 84 | 85 | 86 | 87 | 88 | qApp->palette().base().color() 89 | 90 | 91 | qApp->palette().text().color() 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /src/gui/timedisplay.h: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2014 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef TIMEDISPLAY_H 8 | #define TIMEDISPLAY_H 9 | 10 | #include "ui_timedisplay.h" 11 | #include "timeformat.h" 12 | 13 | #include 14 | #include 15 | 16 | class DigitDisplay; 17 | 18 | class QGroupBox; 19 | 20 | /** 21 | * @brief A custom widget displaying a QTime 22 | * This custom widget implements a "digital" display for a time, formatted according to a certain format. 23 | * This widget can be connected to a generic "time source" producing the time to be displayed. 24 | */ 25 | class TimeDisplay : public QWidget, public Ui::TimeDisplay 26 | { 27 | Q_OBJECT 28 | 29 | public: 30 | 31 | explicit TimeDisplay(QWidget *parent = nullptr); 32 | 33 | /** 34 | * Set the internal time format of the display 35 | * @param format The format to be used as time format. 36 | */ 37 | void setTimeFormat(const TimeFormat& format); 38 | 39 | /** 40 | * Set a custom font for hours 41 | * @param font The custom font to set. 42 | */ 43 | void setHoursFont(const QFont& font); 44 | 45 | /** 46 | * Set a custom font for minutes 47 | * @param font The custom font to set. 48 | */ 49 | void setMinutesFont(const QFont& font); 50 | 51 | /** 52 | * Set a custom font for seconds 53 | * @param font The custom font to set. 54 | */ 55 | void setSecondsFont(const QFont& font); 56 | 57 | /** 58 | * Set a custom font for second fractions 59 | * @param font The custom font to set. 60 | */ 61 | void setFractionsFont(const QFont& font); 62 | 63 | /** 64 | * Set a custom color for display background. 65 | * @param color The custom color to set. 66 | */ 67 | void setBackgroundColor(const QColor& color); 68 | 69 | /** 70 | * Set a custom color for display fonts. 71 | * @param color The custom color to set. 72 | */ 73 | void setTextColor(const QColor& color); 74 | 75 | /** 76 | * Get the current time formatted with the current format. 77 | * @return Current time formatted as string. 78 | */ 79 | QString currentTime(); 80 | 81 | public Q_SLOTS: 82 | 83 | /** 84 | * Set the time to be displayed. 85 | * @param time The time to be displayed. 86 | */ 87 | void setTime(int time); 88 | 89 | /** 90 | * Reset the display to the default time format. The overridden format (if any) is lost. 91 | */ 92 | void reset(); 93 | 94 | private: 95 | 96 | static constexpr int MSECS_PER_HOUR = 3600000; 97 | static constexpr int MSECS_PER_MIN = 60000; 98 | static constexpr int MSECS_PER_SEC = 1000; 99 | static constexpr int SECS_PER_MIN = 60; 100 | 101 | QTime m_displayTime = {0, 0}; /** Current display time */ 102 | TimeFormat m_currentFormat; /** Current display time format. */ 103 | TimeFormat m_defaultFormat; /** Default time format, to be restored on reset. */ 104 | 105 | /** 106 | * Refresh the labels text implementing the display timer 107 | */ 108 | void updateTimer(); 109 | 110 | /** 111 | * Refresh the minimum width of the frames, based on current font sizes 112 | */ 113 | void updateWidth(); 114 | 115 | /** 116 | * Helper function, called when setting and overriding the time format. 117 | */ 118 | void updateTimeFormat(); 119 | 120 | /** 121 | * Helper function, called to set frame colors. 122 | */ 123 | void setGroupboxColor(QGroupBox *groupBox, QPalette::ColorRole role, const QColor& color); 124 | 125 | Q_DISABLE_COPY(TimeDisplay) 126 | }; 127 | 128 | #endif 129 | -------------------------------------------------------------------------------- /src/core/timeformat.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2014 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "timeformat.h" 8 | 9 | #include 10 | 11 | TimeFormat::TimeFormat(bool showHours, bool showMinutes, SecondFraction fractions) : 12 | m_showHours {showHours}, 13 | m_showMinutes {showMinutes}, 14 | m_fractions {fractions} 15 | { 16 | setupFormat(); 17 | } 18 | 19 | QString TimeFormat::format(const QTime& time) const 20 | { 21 | const auto h = formatHours(time); 22 | const auto m = formatMinutes(time); 23 | const auto s = formatSeconds(time); 24 | const auto f = formatFractions(time); 25 | 26 | return h + m + s + f; 27 | } 28 | 29 | QString TimeFormat::formatHours(const QTime& time) const 30 | { 31 | if (!m_showHours) { 32 | return {}; 33 | } 34 | 35 | return time.toString(m_hourFormat); 36 | } 37 | 38 | QString TimeFormat::formatMinutes(const QTime& time) const 39 | { 40 | if (!m_showMinutes) { 41 | return {}; 42 | } 43 | 44 | return time.toString(m_minFormat); 45 | } 46 | 47 | QString TimeFormat::formatSeconds(const QTime& time) const 48 | { 49 | return time.toString(m_secFormat); 50 | } 51 | 52 | QString TimeFormat::formatFractions(const QTime& time) const 53 | { 54 | auto fracFormat = QStringLiteral("zzz"); 55 | auto temp = QString {}; 56 | 57 | switch (m_fractions) { 58 | case UpToTenths: 59 | temp = time.toString(fracFormat); 60 | return temp.left(temp.size() - 2); 61 | case UpToHundredths: 62 | temp = time.toString(fracFormat); 63 | return temp.left(temp.size() - 1); 64 | case UpToMilliseconds: 65 | return time.toString(fracFormat); 66 | default: 67 | return QString(); 68 | } 69 | } 70 | 71 | void TimeFormat::overrideHours() 72 | { 73 | if (m_showHours) 74 | return; 75 | 76 | m_showHours = true; 77 | setupFormat(); 78 | } 79 | 80 | void TimeFormat::overrideMinutes() 81 | { 82 | if (m_showMinutes) 83 | return; 84 | 85 | m_showMinutes = true; 86 | setupFormat(); 87 | } 88 | 89 | bool TimeFormat::hasHours() const 90 | { 91 | return m_showHours; 92 | } 93 | 94 | bool TimeFormat::hasMinutes() const 95 | { 96 | return m_showMinutes; 97 | } 98 | 99 | bool TimeFormat::hasFractions() const 100 | { 101 | return m_fractions != NoFractions; 102 | } 103 | 104 | TimeFormat::SecondFraction TimeFormat::secondFractions() const 105 | { 106 | return m_fractions; 107 | } 108 | 109 | void TimeFormat::showDividers(bool show) 110 | { 111 | m_showDividers = show; 112 | setupFormat(); 113 | } 114 | 115 | bool TimeFormat::operator==(const TimeFormat& right) const 116 | { 117 | return m_showHours == right.m_showHours && 118 | m_showMinutes == right.m_showMinutes && 119 | m_fractions == right.m_fractions && 120 | m_showDividers == right.m_showDividers; 121 | } 122 | 123 | bool TimeFormat::operator!=(const TimeFormat& right) const 124 | { 125 | return !(*this == right); 126 | } 127 | 128 | void TimeFormat::setupFormat() 129 | { 130 | if (m_showHours) { 131 | if (m_showDividers) { 132 | m_hourFormat = QStringLiteral("hh:"); 133 | } 134 | else { 135 | m_hourFormat = QStringLiteral("hh"); 136 | } 137 | } 138 | 139 | if (m_showMinutes) { 140 | if (m_showDividers) { 141 | m_minFormat = QStringLiteral("mm:"); 142 | } 143 | else { 144 | m_minFormat = QStringLiteral("mm"); 145 | } 146 | } 147 | 148 | if (m_showDividers && m_fractions != NoFractions) { 149 | m_secFormat = QStringLiteral("ss."); 150 | } 151 | else { 152 | m_secFormat = QStringLiteral("ss"); 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /CMakePresets.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "configurePresets": [ 4 | { 5 | "name": "dev", 6 | "displayName": "Build as debug", 7 | "generator": "Ninja", 8 | "binaryDir": "${sourceDir}/build", 9 | "cacheVariables": { 10 | "CMAKE_BUILD_TYPE": "Debug", 11 | "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" 12 | } 13 | }, 14 | { 15 | "name": "dev-disable-deprecated", 16 | "displayName": "Build as without deprecated methods", 17 | "generator": "Ninja", 18 | "binaryDir": "${sourceDir}/build-disable-deprecated", 19 | "cacheVariables": { 20 | "CMAKE_BUILD_TYPE": "Debug", 21 | "CMAKE_EXPORT_COMPILE_COMMANDS": "ON", 22 | "CMAKE_CXX_FLAGS_INIT": "-DQT_DISABLE_DEPRECATED_BEFORE=0x060000 -DKF_DISABLE_DEPRECATED_BEFORE_AND_AT=0x060000" 23 | } 24 | }, 25 | { 26 | "name": "asan", 27 | "displayName": "Build with Asan support.", 28 | "generator": "Ninja", 29 | "binaryDir": "${sourceDir}/build-asan", 30 | "cacheVariables": { 31 | "CMAKE_BUILD_TYPE": "Debug", 32 | "ECM_ENABLE_SANITIZERS" : "'address;undefined'", 33 | "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" 34 | } 35 | }, 36 | { 37 | "name": "unity", 38 | "displayName": "Build with CMake unity support.", 39 | "generator": "Ninja", 40 | "binaryDir": "${sourceDir}/build-unity", 41 | "cacheVariables": { 42 | "CMAKE_BUILD_TYPE": "Debug", 43 | "CMAKE_UNITY_BUILD": "ON", 44 | "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" 45 | } 46 | }, 47 | { 48 | "name": "release", 49 | "displayName": "Build as release mode.", 50 | "generator": "Ninja", 51 | "binaryDir": "${sourceDir}/build-release", 52 | "cacheVariables": { 53 | "CMAKE_BUILD_TYPE": "Release" 54 | } 55 | }, 56 | { 57 | "name": "profile", 58 | "displayName": "profile", 59 | "generator": "Ninja", 60 | "binaryDir": "${sourceDir}/build-profile", 61 | "cacheVariables": { 62 | "CMAKE_BUILD_TYPE": "RelWithDebInfo", 63 | "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" 64 | } 65 | }, 66 | { 67 | "name": "clazy", 68 | "displayName": "clazy", 69 | "generator": "Ninja", 70 | "binaryDir": "${sourceDir}/build-clazy", 71 | "cacheVariables": { 72 | "CMAKE_BUILD_TYPE": "Debug" 73 | }, 74 | "environment": { 75 | "CXX": "clazy", 76 | "CCACHE_DISABLE": "ON" 77 | } 78 | } 79 | ], 80 | "buildPresets": [ 81 | { 82 | "name": "dev", 83 | "configurePreset": "dev" 84 | }, 85 | { 86 | "name": "asan", 87 | "configurePreset": "asan" 88 | }, 89 | { 90 | "name": "dev-disable-deprecated", 91 | "configurePreset": "dev-disable-deprecated" 92 | }, 93 | { 94 | "name": "unity", 95 | "configurePreset": "unity" 96 | }, 97 | { 98 | "name": "clazy", 99 | "configurePreset": "clazy", 100 | "environment": { 101 | "CLAZY_CHECKS" : "level0,level1,detaching-member,ifndef-define-typo,isempty-vs-count,qrequiredresult-candidates,reserve-candidates,signal-with-return-value,unneeded-cast,function-args-by-ref,function-args-by-value,returning-void-expression,no-ctor-missing-parent-argument,isempty-vs-count,qhash-with-char-pointer-key,raw-environment-function,qproperty-type-mismatch,old-style-connect,qstring-allocations,container-inside-loop,heap-allocated-small-trivial-type,inefficient-qlist,qstring-varargs,level2,detaching-member,heap-allocated-small-trivial-type,isempty-vs-count,qstring-varargs,qvariant-template-instantiation,raw-environment-function,reserve-candidates,signal-with-return-value,thread-with-slots,no-ctor-missing-parent-argument,no-missing-typeinfo", 102 | "CCACHE_DISABLE" : "ON" 103 | } 104 | } 105 | ] 106 | } 107 | -------------------------------------------------------------------------------- /src/gui/digitdisplay.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2014 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "digitdisplay.h" 8 | 9 | #include 10 | #include 11 | 12 | DigitDisplay::DigitDisplay(QWidget *parent, Digits digits) : QWidget(parent) 13 | { 14 | auto layout = new QHBoxLayout {this}; 15 | m_leftmostDigit = new QLabel {this}; 16 | m_centerDigit = new QLabel {this}; 17 | m_rightmostDigit = new QLabel {this}; 18 | 19 | m_leftmostDigit->setAlignment(Qt::AlignCenter); 20 | m_centerDigit->setAlignment(Qt::AlignCenter); 21 | m_rightmostDigit->setAlignment(Qt::AlignCenter); 22 | 23 | layout->addWidget(m_leftmostDigit); 24 | layout->addWidget(m_centerDigit); 25 | layout->addWidget(m_rightmostDigit); 26 | 27 | setDigits(digits); 28 | } 29 | 30 | void DigitDisplay::setDigits(Digits digits) 31 | { 32 | m_digits = digits; 33 | 34 | switch (m_digits) { 35 | case Digits::One: 36 | m_leftmostDigit->show(); 37 | m_centerDigit->hide(); 38 | m_rightmostDigit->hide(); 39 | break; 40 | case Digits::Two: 41 | m_leftmostDigit->show(); 42 | m_centerDigit->show(); 43 | m_rightmostDigit->hide(); 44 | break; 45 | case Digits::Three: 46 | m_leftmostDigit->show(); 47 | m_centerDigit->show(); 48 | m_rightmostDigit->show(); 49 | break; 50 | default: 51 | m_leftmostDigit->hide(); 52 | m_centerDigit->hide(); 53 | m_rightmostDigit->hide(); 54 | break; 55 | } 56 | } 57 | 58 | void DigitDisplay::showDigits(const QString& digits) const 59 | { 60 | switch (m_digits) { 61 | case Digits::One: 62 | showOneDigit(digits); 63 | break; 64 | case Digits::Two: 65 | showTwoDigits(digits); 66 | break; 67 | case Digits::Three: 68 | showThreeDigits(digits); 69 | break; 70 | default: 71 | break; 72 | } 73 | } 74 | 75 | void DigitDisplay::setFont(const QFont& font) 76 | { 77 | m_displayFont = font; 78 | 79 | m_leftmostDigit->setFont(m_displayFont); 80 | m_centerDigit->setFont(m_displayFont); 81 | m_rightmostDigit->setFont(m_displayFont); 82 | } 83 | 84 | QSize DigitDisplay::minimumSizeHint() const 85 | { 86 | auto width = 0; 87 | auto fontMetrics = QFontMetrics {m_displayFont}; 88 | 89 | switch (m_digits) { 90 | case Digits::One: 91 | width = fontMetrics.boundingRect(m_leftmostDigit->text()).width(); 92 | break; 93 | case Digits::Two: 94 | width = fontMetrics.boundingRect(m_leftmostDigit->text()).width() + fontMetrics.boundingRect(m_centerDigit->text()).width(); 95 | break; 96 | case Digits::Three: 97 | width = fontMetrics.boundingRect(m_leftmostDigit->text()).width() + fontMetrics.boundingRect(m_centerDigit->text()).width() + fontMetrics.boundingRect(m_rightmostDigit->text()).width(); 98 | break; 99 | default: 100 | break; 101 | } 102 | 103 | width += (width * 10 / 100); // 10% used as padding between digits 104 | 105 | return {width, QWidget::minimumSizeHint().height()}; 106 | } 107 | 108 | bool DigitDisplay::isValid(const QString &text) const 109 | { 110 | switch (m_digits) { 111 | case Digits::One: 112 | return text.size() == 1; 113 | case Digits::Two: 114 | return text.size() == 2; 115 | case Digits::Three: 116 | return text.size() == 3; 117 | default: 118 | return false; 119 | } 120 | } 121 | 122 | void DigitDisplay::showOneDigit(const QString& digit) const 123 | { 124 | if (!isValid(digit)) { 125 | return; 126 | } 127 | 128 | m_leftmostDigit->setText(digit.at(0)); 129 | } 130 | 131 | void DigitDisplay::showTwoDigits(const QString& digits) const 132 | { 133 | if (!isValid(digits)) { 134 | return; 135 | } 136 | 137 | // digits are displayed from right to left 138 | m_centerDigit->setText(digits.at(1)); 139 | m_leftmostDigit->setText(digits.at(0)); 140 | } 141 | 142 | void DigitDisplay::showThreeDigits(const QString& digits) const 143 | { 144 | if (!isValid(digits)) { 145 | return; 146 | } 147 | 148 | // digits are displayed from right to left 149 | m_rightmostDigit->setText(digits.at(2)); 150 | m_centerDigit->setText(digits.at(1)); 151 | m_leftmostDigit->setText(digits.at(0)); 152 | } 153 | 154 | #include "moc_digitdisplay.cpp" 155 | -------------------------------------------------------------------------------- /src/gui/sessiondialog.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2015 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "sessiondialog.h" 8 | #include "sessionmodel.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | SessionDialog::SessionDialog(SessionModel *sessionModel, QWidget *parent) : QDialog(parent, Qt::Dialog) 23 | { 24 | setupUi(this); 25 | m_sessionModel = sessionModel; 26 | 27 | m_proxyModel = new QSortFilterProxyModel {this}; 28 | m_proxyModel->setSourceModel(m_sessionModel); 29 | 30 | m_sessionView->setModel(m_proxyModel); 31 | m_sessionView->resizeColumnsToContents(); 32 | // TODO: the user may want to select/remove more than one session 33 | 34 | m_msgWidget->hide(); 35 | m_buttonBox->button(QDialogButtonBox::Ok)->setText(i18nc("@action:button", "Open session")); 36 | 37 | connect(m_sessionView, &QTableView::doubleClicked, this, &SessionDialog::slotDoubleClicked); 38 | connect(m_sessionView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &SessionDialog::slotSelectionChanged); 39 | connect(m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); 40 | connect(m_sessionModel, &SessionModel::rowsInserted, this, &SessionDialog::slotSessionAdded); 41 | connect(m_sessionModel, &SessionModel::rowsRemoved, this, &SessionDialog::slotEmptyModel); 42 | 43 | slotEmptyModel(); 44 | slotSelectionChanged(); 45 | 46 | auto screens = QGuiApplication::screens(); 47 | // Set a good default size, tested on 1920x1200 and 1366x768 screens. 48 | resize(screens[0]->size() / 2.5); 49 | } 50 | 51 | Session SessionDialog::selectedSession() const 52 | { 53 | return m_selectedSession; 54 | } 55 | 56 | void SessionDialog::keyPressEvent(QKeyEvent *event) 57 | { 58 | if (event->key() == Qt::Key_Delete && !m_sessionModel->isEmpty()) { 59 | removeDialog(); 60 | } 61 | 62 | QDialog::keyPressEvent(event); 63 | } 64 | 65 | void SessionDialog::accept() 66 | { 67 | m_selectedSession = m_sessionModel->data(selectedIndex(), static_cast(SessionModel::Roles::SessionRole)).value(); 68 | QDialog::accept(); 69 | } 70 | 71 | void SessionDialog::slotDoubleClicked(const QModelIndex& index) 72 | { 73 | if (m_sessionModel->isEditable(index)) 74 | return; 75 | 76 | this->accept(); 77 | } 78 | 79 | void SessionDialog::slotSelectionChanged() 80 | { 81 | auto openButton = m_buttonBox->button(QDialogButtonBox::Ok); 82 | m_sessionView->selectionModel()->hasSelection() ? openButton->setEnabled(true) : openButton->setEnabled(false); 83 | } 84 | 85 | void SessionDialog::slotSessionAdded() 86 | { 87 | auto openButton = m_buttonBox->button(QDialogButtonBox::Ok); 88 | 89 | if (openButton->isEnabled()) 90 | return; 91 | 92 | openButton->setEnabled(true); 93 | openButton->setToolTip(QString()); 94 | } 95 | 96 | void SessionDialog::slotEmptyModel() 97 | { 98 | if (!m_sessionModel->isEmpty()) 99 | return; 100 | 101 | const auto message = i18nc("@info", "You don't have any saved session yet."); 102 | 103 | auto openButton = m_buttonBox->button(QDialogButtonBox::Ok); 104 | openButton->setEnabled(false); 105 | openButton->setToolTip(message); 106 | 107 | m_msgWidget->setMessageType(KMessageWidget::Information); 108 | m_msgWidget->setText(message); 109 | m_msgWidget->animatedShow(); 110 | } 111 | 112 | QModelIndex SessionDialog::selectedIndex() 113 | { 114 | auto sortedIndex = m_sessionView->selectionModel()->currentIndex(); 115 | 116 | return m_proxyModel->mapToSource(sortedIndex); 117 | } 118 | 119 | void SessionDialog::removeDialog() 120 | { 121 | const auto buttonCode = KMessageBox::warningTwoActions( 122 | this, 123 | i18nc("@info", "Do you want to remove the selected session?"), 124 | i18nc("@title:window", "Confirm deletion"), 125 | KStandardGuiItem::remove(), 126 | KStandardGuiItem::cancel(), 127 | QStringLiteral("delete-session")); 128 | 129 | if (buttonCode != KMessageBox::PrimaryAction) 130 | return; 131 | 132 | m_sessionModel->removeRow(selectedIndex().row()); 133 | } 134 | 135 | 136 | #include "moc_sessiondialog.cpp" 137 | -------------------------------------------------------------------------------- /desktop/org.kde.kronometer.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Type=Application 3 | Exec=kronometer 4 | Icon=kronometer 5 | Terminal=false 6 | Name=Kronometer 7 | Name[ar]=كرونومتر 8 | Name[bs]=Kronometer 9 | Name[ca]=Kronometer 10 | Name[ca@valencia]=Kronometer 11 | Name[cs]=Kronometer 12 | Name[da]=Kronometer 13 | Name[de]=Kronometer 14 | Name[el]=Kronometer 15 | Name[en_GB]=Kronometer 16 | Name[eo]=Kronometer 17 | Name[es]=Kronometer 18 | Name[et]=Kronometer 19 | Name[eu]=Kronometer 20 | Name[fi]=Kronometer 21 | Name[fr]=Kronometer 22 | Name[gl]=Kronometer 23 | Name[he]=קרונומטר 24 | Name[hu]=Kronometer 25 | Name[ia]=Kronometer 26 | Name[it]=Kronometer 27 | Name[ka]=Kronometer 28 | Name[ko]=Kronometer 29 | Name[lt]=Kronometer 30 | Name[lv]=Kronometer 31 | Name[nds]=Kronometer 32 | Name[nl]=Kronometer 33 | Name[nn]=Kronometer 34 | Name[pl]=Kronometer 35 | Name[pt]=Kronometer 36 | Name[pt_BR]=Kronometer 37 | Name[ro]=Kronometer 38 | Name[ru]=Kronometer 39 | Name[sa]=क्रोनोमीटर् 40 | Name[sk]=Kronometer 41 | Name[sl]=Kronometer 42 | Name[sv]=Kronometer 43 | Name[tr]=Kronometre 44 | Name[uk]=Kronometer 45 | Name[zh_CN]=Kronometer 计时器 46 | Name[zh_TW]=Kronometer 47 | GenericName=Chronometer 48 | GenericName[ar]=مقياس الزمن 49 | GenericName[bs]=Mjerač vremena 50 | GenericName[ca]=Cronòmetre 51 | GenericName[ca@valencia]=Cronòmetre 52 | GenericName[cs]=Stopky 53 | GenericName[da]=Kronometer 54 | GenericName[de]=Zeitmesser 55 | GenericName[el]=Χρονόμετρο 56 | GenericName[en_GB]=Chronometer 57 | GenericName[eo]=Kronometro 58 | GenericName[es]=Cronómetro 59 | GenericName[et]=Kronomeeter 60 | GenericName[eu]=kronometroa 61 | GenericName[fi]=Sekuntikello 62 | GenericName[fr]=Chronomètre 63 | GenericName[gl]=Cronómetro 64 | GenericName[he]=כרונומטר 65 | GenericName[hu]=Kronométer 66 | GenericName[ia]=Chronometro 67 | GenericName[it]=Cronometro 68 | GenericName[ka]=ქრონომეტრი 69 | GenericName[ko]=크로노미터 70 | GenericName[lt]=Chronometras 71 | GenericName[lv]=Hronometrs 72 | GenericName[nds]=Tietmeter 73 | GenericName[nl]=Chronometer 74 | GenericName[nn]=Kronometer 75 | GenericName[pl]=Chronometr 76 | GenericName[pt]=Cronómetro 77 | GenericName[pt_BR]=Cronômetro 78 | GenericName[ro]=Cronometru 79 | GenericName[ru]=Секундомер 80 | GenericName[sa]=क्रोनोमीटर 81 | GenericName[sk]=Chronometer 82 | GenericName[sl]=Časomer 83 | GenericName[sv]=Kronometer 84 | GenericName[tr]=Kronometre 85 | GenericName[uk]=Хронометр 86 | GenericName[zh_CN]=计时器 87 | GenericName[zh_TW]=精密計時器 88 | Comment=A simple chronometer application by KDE 89 | Comment[ar]=تطبيق مقياس زمن بسيط من كيدي 90 | Comment[ca]=Una aplicació senzilla de cronòmetre, creada per la comunitat KDE 91 | Comment[ca@valencia]=Una aplicació senzilla de cronòmetre, creada per la comunitat KDE 92 | Comment[cs]=Jednoduchá aplikace stopek od KDE 93 | Comment[da]=Et simpelt kronometerprogram af KDE 94 | Comment[de]=Eine einfache Anwendung für die Zeitmessung von KDE 95 | Comment[el]=Μια απλή εφαρμογή χρονομέτρου από το KDE 96 | Comment[en_GB]=A simple chronometer application by KDE 97 | Comment[eo]=Simpla kronometra aplikaĵo de KDE 98 | Comment[es]=Una sencilla aplicación de cronómetro creada por KDE 99 | Comment[et]=KDE lihtne stopperirakendus 100 | Comment[eu]=KDE-ren kronometro sinple aplikazioa 101 | Comment[fi]=KDE:n yksinkertainen sekuntikellosovellus 102 | Comment[fr]=Une simple application de chronomètre par KDE 103 | Comment[gl]=Unha aplicación sinxela creada por KDE para cronometrar 104 | Comment[he]=יישום כרונומטר פשוט מבית KDE 105 | Comment[ia]=Un simple applicatin de chronometro per KDE 106 | Comment[it]=Un semplice cronometro da KDE 107 | Comment[ka]=ქრონომეტრის მარტივი აპლიკაცია KDE-სგან 108 | Comment[ko]=KDE의 간단한 크로노미터 앱 109 | Comment[lt]=Paprasta KDE chronometro programa 110 | Comment[lv]=Vienkāršs KDE hronometrs 111 | Comment[nl]=Een eenvoudige chronometer-toepassing door KDE 112 | Comment[nn]=Enkelt kronometerprogram frå KDE 113 | Comment[pl]=Prosta aplikacja chronometru autorstwa KDE 114 | Comment[pt]=Uma aplicação simples de cronómetro do KDE 115 | Comment[pt_BR]=Um cronômetro simples do KDE 116 | Comment[ro]=Aplicație simplă de cronometru de la KDE 117 | Comment[ru]=Простое приложение-секундомер от KDE 118 | Comment[sa]=KDE द्वारा एकः सरलः क्रोनोमीटर् अनुप्रयोगः 119 | Comment[sk]=Jednoduchá aplikácia chronometra pre KDE 120 | Comment[sl]=Preprost časomer s strani KDE 121 | Comment[sv]=Ett enkelt kronometerprogram av KDE 122 | Comment[tr]=KDE tarafından yapılan yalın bir kronometre uygulaması 123 | Comment[uk]=Проста програма-хронометр від KDE 124 | Comment[zh_CN]=由 KDE 打造的简单计时器应用程序 125 | Comment[zh_TW]=來自 KDE 的精密計時應用程式 126 | Categories=Qt;KDE;Utility;Clock; 127 | X-DocPath=kronometer/index.html 128 | -------------------------------------------------------------------------------- /src/core/stopwatch.h: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2014 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef STOPWATCH_H 8 | #define STOPWATCH_H 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | class QTimerEvent; 15 | 16 | /** 17 | * @brief A Stopwatch class. 18 | * Stopwatch is a simple QObject implementing a real stopwatch. 19 | * The class provides public Q_SLOTS to start/pause/reset its internal timer. 20 | * A slot for laps recording exists too, but the computing of lap times is not a task of this class: 21 | * Stopwatch simply emits a signal, that the receiver can use to compute lap times. 22 | */ 23 | class Stopwatch : public QObject 24 | { 25 | Q_OBJECT 26 | 27 | public: 28 | 29 | enum class Granularity : int 30 | { 31 | Milliseconds = 1, /**< Stopwatch refreshed every msec. */ 32 | Hundredths = 10, /**< Stopwatch refreshed every 10 msec. */ 33 | Tenths = 100, /**< Stopwatch refreshed every 100 msec. */ 34 | Seconds = 1000 /**< Stopwatch refreshed every sec. */ 35 | }; 36 | 37 | explicit Stopwatch(QObject *parent = nullptr); 38 | 39 | /** 40 | * Set the stopwatch refresh granularity 41 | * @param g The granularity to be set. 42 | */ 43 | void setGranularity(Granularity g); 44 | 45 | /** 46 | * Check if the stopwatch is running 47 | * @return true if running, false otherwise 48 | */ 49 | bool isRunning() const; 50 | 51 | /** 52 | * Check if the stopwatch is paused 53 | * @return true if paused, false otherwise 54 | */ 55 | bool isPaused() const; 56 | 57 | /** 58 | * Check if the stopwatch is inactive 59 | * @return true if inactive, false otherwise 60 | */ 61 | bool isInactive() const; 62 | 63 | /** 64 | * Read-only access to the stopwatch underlying data 65 | * @return The stopwatch raw counter 66 | */ 67 | int raw() const; 68 | 69 | /** 70 | * (Re)-initialize (deserialize) the stopwatch from the given raw data counter. 71 | * Only an inactive stopwatch is meant to be (re)-initialized (deserialized). 72 | * @param rawData The raw milliseconds counter for the stopwatch 73 | * @return true if the operation succeeds (i.e. the stopwatch was inactive), false otherwise 74 | */ 75 | bool initialize(int rawData); 76 | 77 | public Q_SLOTS: 78 | 79 | /** 80 | * Start the stopwatch, if inactive or paused. 81 | */ 82 | void start(); 83 | 84 | /** 85 | * Pause the stopwatch, if running. 86 | */ 87 | void pause(); 88 | 89 | /** 90 | * Reset the stopwatch to the inactive state. 91 | */ 92 | void reset(); 93 | 94 | /** 95 | * Tells the stopwatch to compute a new lap time. 96 | */ 97 | void storeLap(); 98 | 99 | Q_SIGNALS: 100 | 101 | /** 102 | * The stopwatch has been started. 103 | */ 104 | void running(); 105 | 106 | /** 107 | * The stopwatch has been paused. 108 | */ 109 | void paused(); 110 | 111 | /** 112 | * The stopwatch has been reset. 113 | */ 114 | void inactive(); 115 | 116 | /** 117 | * Emits a signal with the last lap *absolute* time. 118 | * This class does not compute *relatives* lap times. 119 | * You can compute them simply by the difference between consecutives absolute times. 120 | * @param lapTime The absolute time of the last lap. 121 | */ 122 | void lap(const QTime& lapTime); 123 | 124 | /** 125 | * Emits a signal with the current stopwatch time. 126 | * @param t Current stopwatch time. 127 | */ 128 | void time(int t); 129 | 130 | protected: 131 | 132 | void timerEvent(QTimerEvent *event) override; 133 | 134 | private: 135 | 136 | int granularity() const; 137 | 138 | enum class State 139 | { 140 | Inactive, /**< Inactive stopwatch. */ 141 | Running, /**< Running stopwatch. */ 142 | Paused /**< Paused stopwatch. */ 143 | }; 144 | 145 | static constexpr int INACTIVE_TIMER_ID = -1; /** Used for timerId initialization */ 146 | 147 | int m_timerId = INACTIVE_TIMER_ID; /** ID for the QObject timer */ 148 | int m_accumulator = 0; /** milliseconds internal counter */ 149 | State m_state = State::Inactive; /** Stopwatch current state */ 150 | Granularity m_granularity = Granularity::Hundredths; /** Stopwatch current granularity */ 151 | 152 | QElapsedTimer m_elapsedTimer; /** Stopwatch core class*/ 153 | 154 | Q_DISABLE_COPY(Stopwatch) 155 | }; 156 | 157 | 158 | 159 | #endif 160 | -------------------------------------------------------------------------------- /src/models/lapmodel.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2014 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "lapmodel.h" 8 | 9 | #include 10 | 11 | #include 12 | 13 | LapModel::LapModel(QObject* parent) : QAbstractTableModel(parent) 14 | {} 15 | 16 | int LapModel::columnCount(const QModelIndex& parent) const 17 | { 18 | Q_UNUSED(parent) 19 | 20 | return m_roles.count(); 21 | } 22 | 23 | int LapModel::rowCount(const QModelIndex& parent) const 24 | { 25 | Q_UNUSED(parent) 26 | 27 | return m_laps.size(); 28 | } 29 | 30 | QVariant LapModel::data(const QModelIndex& index, int role) const 31 | { 32 | if (!index.isValid()) { 33 | return QVariant::Invalid; 34 | } 35 | 36 | if (index.row() >= rowCount() || index.row() < 0) { 37 | return QVariant::Invalid; 38 | } 39 | 40 | if (role == Qt::DisplayRole) { 41 | return data(index, Qt::UserRole + index.column()); 42 | } 43 | 44 | switch (static_cast(role)) { 45 | case Roles::LapIdRole: 46 | return index.row() + 1; 47 | case Roles::RelativeTimeRole: 48 | return m_laps.at(index.row()).relativeTime(); 49 | case Roles::AbsoluteTimeRole: 50 | return m_laps.at(index.row()).absoluteTime(); 51 | case Roles::NoteRole: 52 | return m_laps.at(index.row()).note(); 53 | case Roles::LapRole: 54 | return QVariant::fromValue(m_laps.at(index.row())); 55 | } 56 | 57 | if (role == Qt::EditRole && index.column() == columnForRole(Roles::NoteRole)) { 58 | // prevent the disappear of the old value when double-clicking the item 59 | return m_laps.at(index.row()).note(); 60 | } 61 | 62 | return QVariant::Invalid; 63 | } 64 | 65 | QVariant LapModel::headerData(int section, Qt::Orientation orientation, int role) const 66 | { 67 | if (role != Qt::DisplayRole || orientation != Qt::Horizontal) 68 | return QVariant::Invalid; 69 | 70 | switch (roleForColumn(section)) { 71 | case Roles::LapIdRole: 72 | return i18nc("lap number", "Lap #"); 73 | case Roles::RelativeTimeRole: 74 | return i18nc("@title:column", "Lap Time"); 75 | case Roles::AbsoluteTimeRole: 76 | return i18nc("@title:column", "Global Time"); 77 | case Roles::NoteRole: 78 | return i18nc("@title:column", "Note"); 79 | case Roles::LapRole: 80 | break; 81 | } 82 | 83 | return QVariant::Invalid; 84 | } 85 | 86 | bool LapModel::setData(const QModelIndex& index, const QVariant& value, int role) 87 | { 88 | if (!index.isValid() || role != Qt::EditRole) 89 | return false; 90 | 91 | if (index.column() != columnForRole(Roles::NoteRole)) 92 | return false; 93 | 94 | m_laps[index.row()].setNote(value.toString()); 95 | Q_EMIT dataChanged(index, index); 96 | 97 | return true; 98 | } 99 | 100 | Qt::ItemFlags LapModel::flags(const QModelIndex& index) const 101 | { 102 | if (!index.isValid()) 103 | return Qt::ItemIsEnabled; 104 | 105 | if (index.column() != columnForRole(Roles::NoteRole)) 106 | return QAbstractTableModel::flags(index); 107 | 108 | return QAbstractTableModel::flags(index) | Qt::ItemIsEditable; 109 | } 110 | 111 | void LapModel::setTimeFormat(const TimeFormat& format) 112 | { 113 | m_timeFormat = format; 114 | 115 | if (!isEmpty()) { 116 | reload(); 117 | } 118 | } 119 | 120 | void LapModel::append(const Lap& lap) 121 | { 122 | // Append the new row at the end. 123 | beginInsertRows(QModelIndex(), rowCount(), rowCount()); 124 | 125 | // Either the time of the first lap or the time relative to the last lap. 126 | const auto relativeTime = m_laps.isEmpty() ? lap.time() : m_laps.last().timeTo(lap); 127 | 128 | auto newLap = Lap {lap}; 129 | newLap.setRelativeTime(m_timeFormat.format(relativeTime)); 130 | newLap.setAbsoluteTime(m_timeFormat.format(newLap.time())); 131 | 132 | m_laps.append(newLap); 133 | endInsertRows(); 134 | } 135 | 136 | bool LapModel::isEmpty() const 137 | { 138 | return m_laps.isEmpty(); 139 | } 140 | 141 | int LapModel::columnForRole(LapModel::Roles role) const 142 | { 143 | return m_roles.indexOf(role); 144 | } 145 | 146 | void LapModel::addLap(const QTime& lapTime) 147 | { 148 | append(Lap {lapTime}); 149 | } 150 | 151 | void LapModel::clear() 152 | { 153 | beginResetModel(); 154 | m_laps.clear(); 155 | endResetModel(); 156 | } 157 | 158 | void LapModel::reload() 159 | { 160 | const auto laps = m_laps; 161 | clear(); 162 | 163 | for (const auto& lap : laps) { 164 | append(lap); 165 | } 166 | } 167 | 168 | LapModel::Roles LapModel::roleForColumn(int column) const 169 | { 170 | return m_roles.at(column); 171 | } 172 | 173 | #include "moc_lapmodel.cpp" 174 | -------------------------------------------------------------------------------- /src/core/timeformat.h: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2014 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #ifndef TIMEFORMAT_H 8 | #define TIMEFORMAT_H 9 | 10 | #include 11 | 12 | class QTime; 13 | 14 | /** 15 | * @brief A wrapper for a QTime-like format time string. 16 | * A TimeFormat is an abstraction for a QTime-like string used for time formats. 17 | * A TimeFormat can be customized using booleans in the constructor. 18 | * The QTime-syntax used is the following: 19 | * "hh:" whether to show hours (00 to 24) 20 | * "mm:" whether to show minutes (00 to 59) 21 | * "ss." whether to show seconds (00 to 59). Seconds are always showed. 22 | * "zzz" whether to show second fractions (tenths or hundredths or milliseconds) 23 | * An example of time formatted with the complete syntax might be the following: 0:05:38.582 24 | */ 25 | class TimeFormat 26 | { 27 | 28 | public: 29 | 30 | enum SecondFraction 31 | { 32 | UpToTenths, /**< Second fraction is tenths of second. */ 33 | UpToHundredths, /**< Second fraction is hundrdths of second. */ 34 | UpToMilliseconds, /**< Second fraction is milliseconds. */ 35 | NoFractions /**< Second fraction disabled. */ 36 | }; 37 | 38 | explicit TimeFormat(bool showHours = false, bool showMinutes = true, SecondFraction fractions = UpToHundredths); 39 | 40 | /** 41 | * Format the given time with the current time format. 42 | * @param time The time to be formatted. 43 | * @return The time formatted as string. 44 | */ 45 | QString format(const QTime& time) const; 46 | 47 | /** 48 | * Format the given time's hours with the current time format. 49 | * @param time The time to be formatted. 50 | * @return The time's hours formatted as string, or empty string if hour is not in the format. 51 | */ 52 | QString formatHours(const QTime& time) const; 53 | 54 | /** 55 | * Format the given time's minutes with the current time format. 56 | * @param time The time to be formatted. 57 | * @return The time's minutes formatted as string, or empty string if minute is not in the format. 58 | */ 59 | QString formatMinutes(const QTime& time) const; 60 | 61 | /** 62 | * Format the given time's seconds with the current time format. 63 | * @param time The time to be formatted. 64 | * @return The time's seconds formatted as string, or empty string if second is not in the format. 65 | */ 66 | QString formatSeconds(const QTime& time) const; 67 | 68 | /** 69 | * Format the given time's second fractions with the current time format. 70 | * @param time The time to be formatted. 71 | * @return The time's second fractions formatted as string, or empty string if second fraction is not in the format. 72 | */ 73 | QString formatFractions(const QTime& time) const; 74 | 75 | /** 76 | * Enable the hours in the time format. 77 | */ 78 | void overrideHours(); 79 | 80 | /** 81 | * Enable minutes in the time format. 82 | */ 83 | void overrideMinutes(); 84 | 85 | /** 86 | * Whether the hour is in the time format. 87 | * @return true if hour is in the format, false otherwise. 88 | */ 89 | bool hasHours() const; 90 | 91 | /** 92 | * Whether the minute is in the time format. 93 | * @return true if minute is in the format, false otherwise. 94 | */ 95 | bool hasMinutes() const; 96 | 97 | /** 98 | * Whether the second fraction is in the time format. 99 | * @return true if second fraction is in the format, false otherwise. 100 | */ 101 | bool hasFractions() const; 102 | 103 | /** 104 | * @return The current FractionType in the time format. 105 | */ 106 | SecondFraction secondFractions() const; 107 | 108 | /** 109 | * Whether to show the symbols ':' and '.' used as dividers in the time format. 110 | * @param show true Whether to show the dividers. 111 | */ 112 | void showDividers(bool show); 113 | 114 | bool operator==(const TimeFormat& right) const; 115 | bool operator!=(const TimeFormat& right) const; 116 | 117 | private: 118 | 119 | bool m_showHours; /** Whether hour is in the internal time format */ 120 | bool m_showMinutes; /** Whether minute is in the internal time format */ 121 | bool m_showDividers = true; /** Whether to show the symbols used as dividers */ 122 | 123 | QString m_hourFormat; /** Hour string format */ 124 | QString m_minFormat; /** Minute string format */ 125 | QString m_secFormat; /** Secondstring format */ 126 | SecondFraction m_fractions; /** Second fraction internal time format */ 127 | 128 | /** 129 | * Setup the format strings based on the internal formats 130 | */ 131 | void setupFormat(); 132 | }; 133 | 134 | #endif 135 | -------------------------------------------------------------------------------- /src/gui/timedisplay.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2014 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "timedisplay.h" 8 | #include "digitdisplay.h" 9 | 10 | #include 11 | 12 | #include 13 | 14 | TimeDisplay::TimeDisplay(QWidget *parent) : QWidget(parent) 15 | { 16 | setupUi(this); 17 | 18 | m_hourDisplay->setDigits(DigitDisplay::Digits::Two); 19 | m_minDisplay->setDigits(DigitDisplay::Digits::Two); 20 | m_secDisplay->setDigits(DigitDisplay::Digits::Two); 21 | 22 | m_hourDisplay->showDigits(m_currentFormat.formatHours(m_displayTime)); 23 | m_minDisplay->showDigits(m_currentFormat.formatMinutes(m_displayTime)); 24 | m_secDisplay->showDigits(m_currentFormat.formatSeconds(m_displayTime)); 25 | m_fracDisplay->showDigits(m_currentFormat.formatFractions(m_displayTime)); 26 | } 27 | 28 | void TimeDisplay::setTimeFormat(const TimeFormat& format) 29 | { 30 | m_defaultFormat = format; 31 | m_currentFormat = format; 32 | updateTimeFormat(); 33 | } 34 | 35 | void TimeDisplay::setHoursFont(const QFont& font) 36 | { 37 | m_hourDisplay->setFont(font); 38 | updateWidth(); 39 | } 40 | 41 | void TimeDisplay::setMinutesFont(const QFont& font) 42 | { 43 | m_minDisplay->setFont(font); 44 | updateWidth(); 45 | } 46 | 47 | void TimeDisplay::setSecondsFont(const QFont& font) 48 | { 49 | m_secDisplay->setFont(font); 50 | updateWidth(); 51 | } 52 | 53 | void TimeDisplay::setFractionsFont(const QFont& font) 54 | { 55 | m_fracDisplay->setFont(font); 56 | updateWidth(); 57 | } 58 | 59 | void TimeDisplay::setBackgroundColor(const QColor& color) 60 | { 61 | setGroupboxColor(m_hourGroup, m_hourGroup->backgroundRole(), color); 62 | setGroupboxColor(m_minGroup, m_minGroup->backgroundRole(), color); 63 | setGroupboxColor(m_secGroup, m_secGroup->backgroundRole(), color); 64 | setGroupboxColor(m_fracGroup, m_fracGroup->backgroundRole(), color); 65 | update(); 66 | } 67 | 68 | void TimeDisplay::setTextColor(const QColor& color) 69 | { 70 | setGroupboxColor(m_hourGroup, m_hourGroup->foregroundRole(), color); 71 | setGroupboxColor(m_minGroup, m_minGroup->foregroundRole(), color); 72 | setGroupboxColor(m_secGroup, m_secGroup->foregroundRole(), color); 73 | setGroupboxColor(m_fracGroup, m_fracGroup->foregroundRole(), color); 74 | update(); 75 | } 76 | 77 | QString TimeDisplay::currentTime() 78 | { 79 | m_currentFormat.showDividers(true); 80 | const auto currentTime = m_currentFormat.format(m_displayTime); 81 | m_currentFormat.showDividers(false); 82 | 83 | return currentTime; 84 | } 85 | 86 | void TimeDisplay::setTime(int time) 87 | { 88 | m_displayTime.setHMS(time / MSECS_PER_HOUR, 89 | (time % MSECS_PER_HOUR) / MSECS_PER_MIN, 90 | (time / MSECS_PER_SEC) % 60, 91 | time % MSECS_PER_SEC); 92 | 93 | updateTimer(); 94 | } 95 | 96 | void TimeDisplay::reset() 97 | { 98 | if (m_currentFormat == m_defaultFormat) 99 | return; 100 | 101 | setTimeFormat(m_defaultFormat); 102 | } 103 | 104 | void TimeDisplay::updateTimer() 105 | { 106 | if (m_currentFormat.hasHours()) { 107 | m_hourDisplay->showDigits(m_currentFormat.formatHours(m_displayTime)); 108 | } 109 | else if (m_displayTime.hour() >= 1) { 110 | m_currentFormat.overrideHours(); 111 | updateTimeFormat(); 112 | } 113 | 114 | if (m_currentFormat.hasMinutes()) { 115 | m_minDisplay->showDigits(m_currentFormat.formatMinutes(m_displayTime)); 116 | } 117 | else if (m_displayTime.minute() >= 1) { 118 | m_currentFormat.overrideMinutes(); 119 | updateTimeFormat(); 120 | } 121 | 122 | m_secDisplay->showDigits(m_currentFormat.formatSeconds(m_displayTime)); 123 | 124 | if (m_currentFormat.hasFractions()) { 125 | m_fracDisplay->showDigits(m_currentFormat.formatFractions(m_displayTime)); 126 | } 127 | } 128 | 129 | void TimeDisplay::updateWidth() 130 | { 131 | auto width = qMax(qMax(m_hourDisplay->minimumSizeHint().width(), 132 | m_minDisplay->minimumSizeHint().width()), 133 | qMax(m_secDisplay->minimumSizeHint().width(), 134 | m_fracDisplay->minimumSizeHint().width())); 135 | 136 | width = width + (width * 40 / 100); // 40% as padding, i.e. 20% as right padding and 20% as left padding 137 | 138 | m_hourGroup->setMinimumWidth(width); 139 | m_minGroup->setMinimumWidth(width); 140 | m_secGroup->setMinimumWidth(width); 141 | m_fracGroup->setMinimumWidth(width); 142 | } 143 | 144 | void TimeDisplay::updateTimeFormat() 145 | { 146 | m_hourGroup->setVisible(m_currentFormat.hasHours()); 147 | m_minGroup->setVisible(m_currentFormat.hasMinutes()); 148 | m_fracGroup->setVisible(m_currentFormat.hasFractions()); 149 | 150 | if (m_currentFormat.hasFractions()) { 151 | switch (m_currentFormat.secondFractions()) { 152 | case TimeFormat::UpToTenths: 153 | m_fracGroup->setTitle(i18nc("@title:column", "Tenths")); 154 | m_fracDisplay->setDigits(DigitDisplay::Digits::One); 155 | break; 156 | case TimeFormat::UpToHundredths: 157 | m_fracGroup->setTitle(i18nc("@title:column", "Hundredths")); 158 | m_fracDisplay->setDigits(DigitDisplay::Digits::Two); 159 | break; 160 | case TimeFormat::UpToMilliseconds: 161 | m_fracGroup->setTitle(i18nc("@title:column", "Milliseconds")); 162 | m_fracDisplay->setDigits(DigitDisplay::Digits::Three); 163 | break; 164 | default: 165 | break; 166 | } 167 | } 168 | 169 | updateTimer(); 170 | } 171 | 172 | void TimeDisplay::setGroupboxColor(QGroupBox *groupBox, QPalette::ColorRole role, const QColor& color) 173 | { 174 | if (!groupBox) { 175 | return; 176 | } 177 | 178 | auto palette = QPalette {groupBox->palette()}; 179 | palette.setColor(role, color); 180 | groupBox->setPalette(palette); 181 | } 182 | 183 | 184 | #include "moc_timedisplay.cpp" 185 | -------------------------------------------------------------------------------- /src/gui/mainwindow.h: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2014 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | 8 | #ifndef MAINWINDOW_H 9 | #define MAINWINDOW_H 10 | 11 | #include "session.h" 12 | 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | class LapModel; 21 | class SessionModel; 22 | class Stopwatch; 23 | class TimeDisplay; 24 | 25 | class KToggleAction; 26 | 27 | class QAction; 28 | class QDBusInterface; 29 | class QLabel; 30 | class QSortFilterProxyModel; 31 | class QSplitter; 32 | class QTableView; 33 | class QTextStream; 34 | class QToolButton; 35 | 36 | /** 37 | * @brief Kronometer main window. 38 | */ 39 | class MainWindow : public KXmlGuiWindow 40 | { 41 | Q_OBJECT 42 | 43 | public: 44 | 45 | explicit MainWindow(SessionModel *sessionModel, QWidget *parent = nullptr, const Session& session = Session {}); 46 | virtual ~MainWindow(); 47 | 48 | /** 49 | * @param title The title for this window. 50 | */ 51 | void setWindowTitle(const QString& title); 52 | 53 | void enableLapShortcuts(bool enable); 54 | 55 | protected: 56 | 57 | bool queryClose() override; 58 | 59 | private Q_SLOTS: 60 | 61 | /** 62 | * Stopwatch running state triggers. 63 | */ 64 | void slotRunning(); 65 | 66 | /** 67 | * Stopwatch paused state triggers. 68 | */ 69 | void slotPaused(); 70 | 71 | /** 72 | * Stopwatch inactive state triggers. 73 | */ 74 | void slotInactive(); 75 | 76 | /** 77 | * Slot for the system bus PrepareForSleep signal. 78 | * @param beforeSleep Whether the signal has been emitted before suspension. 79 | */ 80 | void slotPrepareForSleep(bool beforeSleep); 81 | 82 | /** 83 | * Setup the settings dialog. 84 | */ 85 | void slotShowSettings(); 86 | 87 | /** 88 | * Write the new settings on filesystem. 89 | */ 90 | void slotWriteSettings(); 91 | 92 | /** 93 | * Fix lap dock appereance. 94 | */ 95 | void slotUpdateLapDock(); 96 | 97 | /** 98 | * Open a new MainWindow instance. 99 | */ 100 | void slotNewSession(); 101 | 102 | /** 103 | * Open an existing session in a new MainWindow instance. 104 | */ 105 | void slotOpenSession(); 106 | 107 | /** 108 | * Save current times in the current session. 109 | */ 110 | void slotSaveSession(); 111 | 112 | /** 113 | * Save current times as a new session. 114 | */ 115 | void slotSaveSessionAs(); 116 | 117 | /** 118 | * Export current lap times on a file. 119 | */ 120 | void slotExportLapsAs(); 121 | 122 | /** 123 | * Copy current stopwatch time to clipboard. 124 | */ 125 | void slotCopyToClipboard(); 126 | 127 | /** 128 | * Toggle menubar visibility. 129 | */ 130 | void slotToggleMenuBar(); 131 | 132 | void slotUpdateControlMenu(); 133 | 134 | void slotToolBarUpdated(); 135 | 136 | private: 137 | 138 | bool m_startTimerImmediately = false; 139 | Stopwatch *m_stopwatch; 140 | TimeDisplay *m_stopwatchDisplay; 141 | QTableView *m_lapView; 142 | 143 | QAction *m_startAction; 144 | QAction *m_pauseAction; 145 | QAction *m_resetAction; 146 | QAction *m_lapAction; 147 | QAction *m_exportAction; 148 | std::unique_ptr m_controlMenuTimer; 149 | QPointer m_controlMenuButton; 150 | KToggleAction *m_toggleMenuAction; 151 | 152 | LapModel *m_lapModel; 153 | SessionModel *m_sessionModel; 154 | 155 | Session m_session; 156 | 157 | #ifndef Q_OS_WINDOWS 158 | QDBusInterface *m_screensaverInterface = nullptr; 159 | quint32 m_screenInhibitCookie = 0; 160 | #endif 161 | 162 | /** 163 | * Setup the central widget of the window. 164 | */ 165 | void setupCentralWidget(); 166 | 167 | /** 168 | * Setup standard and custom QActions. 169 | */ 170 | void setupActions(); 171 | 172 | /** 173 | * Load settings from app Config and apply them to the other objects. 174 | */ 175 | void loadSettings(); 176 | 177 | /** 178 | * Set the stopwatch refresh granularity. 179 | */ 180 | void setupGranularity(); 181 | 182 | /** 183 | * Create a session with the current stopwatch time and lap times. 184 | * @param name The name of the session to be saved. 185 | */ 186 | void saveSessionAs(const QString& name); 187 | 188 | /** 189 | * Load a saved session. 190 | */ 191 | void loadSession(); 192 | 193 | /** 194 | * Export current lap times on a new file. 195 | * @param name The name of the file to be created. 196 | * @param mimeType The mime type of the file to be created. 197 | */ 198 | void exportLapsAs(const QString& name, const QString& mimeType); 199 | 200 | /** 201 | * Write the JSON laps representation on the given object. 202 | * @param json The JSON object to be written. 203 | */ 204 | void exportLapsAsJson(QJsonObject& json); 205 | 206 | /** 207 | * Write the CSV laps representation on the given stream. 208 | * @param out The stream to be written. 209 | */ 210 | void exportLapsAsCsv(QTextStream& out); 211 | 212 | /** 213 | * @return Whether there is a window size saved in the kronometer config. 214 | */ 215 | bool isWindowSizeSaved() const; 216 | 217 | /** 218 | * A "comment" message with timestamp, to be used in the created files. 219 | * @return The string "Created by Kronomer on " 220 | */ 221 | QString timestampMessage(); 222 | 223 | void createControlMenuButton(); 224 | 225 | void deleteControlMenuButton(); 226 | 227 | /** 228 | * @return true if @p action has been added to @p menu; 229 | * false if @p action or @p menu is null, or if @p action 230 | * is already on the toolBar(). 231 | */ 232 | bool addActionToMenu(QAction* action, QMenu* menu); 233 | 234 | void activateScreenInhibition(); 235 | 236 | void disactivateScreenInhibition(); 237 | 238 | Q_DISABLE_COPY(MainWindow) 239 | }; 240 | 241 | 242 | #endif 243 | -------------------------------------------------------------------------------- /src/gui/fontsettings.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | FontSettings 4 | 5 | 6 | 7 | 0 8 | 0 9 | 1031 10 | 681 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Hours Font: 24 | 25 | 26 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 0 35 | 0 36 | 37 | 38 | 39 | 40 | Sans Serif 41 | 54 42 | 50 43 | false 44 | false 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | Minutes Font: 57 | 58 | 59 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 0 68 | 0 69 | 70 | 71 | 72 | 73 | Sans Serif 74 | 54 75 | 50 76 | false 77 | false 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | Seconds Font: 90 | 91 | 92 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 0 101 | 0 102 | 103 | 104 | 105 | 106 | Sans Serif 107 | 54 108 | 50 109 | false 110 | false 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | Second Fractions Font: 123 | 124 | 125 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 0 134 | 0 135 | 136 | 137 | 138 | 139 | Sans Serif 140 | 54 141 | 50 142 | false 143 | false 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | Qt::Horizontal 156 | 157 | 158 | 159 | 40 160 | 20 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | Qt::Vertical 171 | 172 | 173 | 174 | 20 175 | 278 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | KFontRequester 185 | QWidget 186 |
kfontrequester.h
187 |
188 |
189 | 190 | 191 |
192 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | v2.3.0 2 | * Introduced Qt6 support. 3 | * Added option to start the stopwatch automatically (thanks to Miguel Carrillo). 4 | * Added support for HiDpi screens. 5 | * Fixed wrong times restored from session (BUG 421515) 6 | * Fixed stopwatch restart after system sleep (BUG 439998) 7 | * Fixed deletion of sessions (BUG 353077, thanks to Johnny Jazeix) 8 | * Qt 5.15 and C++17 are now required. 9 | * Fixed compilation on Windows (thanks to Johnny Jazeix). 10 | * Updated translations. 11 | 12 | v2.2.3 13 | * Fixed bug #349861 (thanks to Gaurav Shah): https://bugs.kde.org/show_bug.cgi?id=349861 14 | * Updated translations. 15 | 16 | v2.2.2 17 | * Updated translations. 18 | 19 | v2.2.1 20 | * Fixed laps sorting. 21 | * Updated translations. 22 | 23 | v2.2.0 24 | * Fixed laps export feature. 25 | * Implemented screen inhibition while a stopwatch is running. 26 | 27 | v2.1.5 28 | * Fixed width of columns in the laps view. 29 | * Updated translations. 30 | 31 | v2.1.4 32 | * Updated homepage links 33 | 34 | v2.1.3 35 | * Fix build with ECM >= 5.31 36 | * Prevent warning messagebox with kxmlgui >= 5.30 37 | 38 | v2.1.2 39 | * Fix default size of Session dialog. 40 | * Don't assume there are always sessions saved. 41 | * Updated translations. 42 | 43 | v2.1.1 44 | * Window size can now be restored (BUG 361494) 45 | * Fix wrongly-enabled Save action (BUG 352993) 46 | * Fix appereance of Lap View (BUG 365101) 47 | 48 | v2.1.0 49 | * Improved usability of dialogs. 50 | * Moved toolbar to top position. 51 | * Menubar is now hidden by default. 52 | * Dropped statusbar. 53 | 54 | v2.0.2 55 | * Fixed invisible main window with Qt 5.6 56 | 57 | v2.0.1 58 | * Fixed default height of the Kronometer window (BUG 351746) 59 | 60 | v2.0.0 61 | * Port to Qt5 and KDE Frameworks 5 62 | * New Breeze icons: app icon and start/pause/reset/lap icons 63 | * Sessions persistence through a simple Session dialog, instead of XML files 64 | * Improved the Settings dialog and removed useless settings 65 | * Hours are now hidden by default, both in stopwatch time and laps times. 66 | * Laps absolute times are now hidden by default 67 | * Laps notes can now be hidden 68 | * Suspension awareness: pause running stopwatch if the OS is going to sleep (BUG 349824) 69 | * Cleaned up UI and visible string messages 70 | * Stopwatch time format is automatically ovverridden when needed (BUG 343130) 71 | * Fixed BUG 344714 72 | * Laps can now be exported to the JSON format, but not anymore to XML 73 | * Fixed Kronometer handbook not being shown from Help -> Kronometer Handbook 74 | * Added manpage 75 | * Development: added autotests 76 | 77 | v1.6.0 78 | * UI cleanup in the Settings dialog (bug 343127: http://bugs.kde.org/show_bug.cgi?id=343127) 79 | * Removed the 'Ask On Exit' option (bug 343126: http://bugs.kde.org/show_bug.cgi?id=343126) 80 | * Lap times format is no more ignored (bug 343128: http://bugs.kde.org/show_bug.cgi?id=343128) 81 | 82 | v1.5.2 83 | * Fixed wrong GPLv2 version in COPYING file 84 | 85 | v1.5.1 86 | * Fixed error preventing the building of Opensuse RPM packages 87 | 88 | v1.5.0 89 | * Laps annotations: now you can place a custom text note over a certain lap time 90 | * Option to disable the laps feature and hide the lap button and table 91 | * AppData support 92 | * Fixed bug 338540: https://bugs.kde.org/show_bug.cgi?id=338540 93 | 94 | v1.4.2 95 | * Removed option to hide the statusbar, since it's a built-in KDE feature 96 | * Small fix for digits appearance 97 | 98 | v1.4.1 99 | * Upper toolbar is now correctly removed from the UI 100 | 101 | v1.4.0 102 | * Latest lap time is now automatically selected 103 | * Fixed bug 336904: https://bugs.kde.org/show_bug.cgi?id=336904 104 | * First release with localization in over 11 languages 105 | 106 | v1.3.0 107 | * Major improvements in the stopwatch display UI 108 | * Fixed critical bug with exotic fonts in the stopwatch display 109 | * Removed the upper toolbar to make the UI less crowded (those actions are always available in the File menu) 110 | * Use the official KDE bugtracking system 111 | * Minor layout fix in the settings dialog 112 | 113 | v1.2.2 114 | * Fixed small bug preventing compilation on old compilers 115 | 116 | v1.2.1 117 | * Option to hide the statusbar from the main window 118 | * Official documentation, *Kronometer Handbook* now available in the Help menu 119 | 120 | v1.1.2 121 | * Fixed window-modified placeholder (*) bug on stopwatch reset 122 | 123 | v1.1.1 124 | * Minor bug fixes and improvements 125 | 126 | v1.1.0 127 | * Export lap times to CSV (Comma Separated Values) format 128 | * Export lap times to XML format 129 | 130 | v1.0.0 131 | * First "stable" release of Kronometer 132 | * Fixed the appereance of the laps table-widget 133 | * Added tooltips in Settings dialogs 134 | 135 | v0.9.0 136 | * Times saved on XML files instead of binary files 137 | * Fixed bug on aborting a file opening 138 | 139 | v0.8.0 140 | * Added *Edit* menu with the ability to copy current stopwatch time to clipboard 141 | * Color settings: choose stopwatch display background/text color 142 | 143 | v0.7.1 144 | * Fix compilation bug 145 | 146 | v0.7.0 147 | * Timer central *display* re-designed 148 | * Now each time "slot" has its own display 149 | * The displays are *splittable* between them 150 | * Display *time headers*, which can be disabled from settings 151 | 152 | v0.6.0 153 | * Initial implementation of times saving on binary files 154 | * You can save a stopwatch *frame* (time and laps) to a file and resume it (open it) later 155 | * Due to the new *save toolbar* (new/open/save/save as buttons), the old *main* toolbar is moved on the window bottom by default. If you don't like it, you can always move it by right-clicking on it 156 | * Added **Kronometer** menu, separating the *save* actions (menu File) from the *stopwatch* actions 157 | * Save settings. You can disable the dialog on application exit if there are unsaved times 158 | 159 | v0.5.0 160 | * Now you can choose also the time format for lap times 161 | * Font settings for timer display font 162 | * Fixed general settings appereance, with a scrollable layout 163 | 164 | v0.4.0 165 | * Initial implementantation of Kronometer settings dialog (Settings -> Configure Kronometer) 166 | * Stopwatch time format settings: show or not show hours/minutes/seconds/tenths/hundredths/milliseconds 167 | * Now you can resize time label and lap times table without resize the application window 168 | 169 | v0.3.0 170 | * Lap recording feature 171 | * Lap times sorting 172 | 173 | v0.2.0 174 | * *Panel-like* look for time label 175 | * Time format in statusbar 176 | * Tooltip messages for labels in statusbar 177 | 178 | v0.1.2 179 | * Switched install prefix from (cmake-default) **/usr/local** to **/usr** 180 | 181 | v0.1.1 182 | * Added **.desktop** file for KMenu integration 183 | 184 | v0.1.0 185 | * First public and stable release 186 | * Initial basic features: start, pause, resume and reset the stopwatch widget 187 | * Basic KDE settings: toolbar/shortcuts configuration, statusbar visibility 188 | -------------------------------------------------------------------------------- /LICENSES/CC0-1.0.txt: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | CC0 1.0 Universal 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS 10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM 11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED 12 | HEREUNDER. 13 | 14 | Statement of Purpose 15 | 16 | The laws of most jurisdictions throughout the world automatically confer 17 | exclusive Copyright and Related Rights (defined below) upon the creator 18 | and subsequent owner(s) (each and all, an "owner") of an original work of 19 | authorship and/or a database (each, a "Work"). 20 | 21 | Certain owners wish to permanently relinquish those rights to a Work for 22 | the purpose of contributing to a commons of creative, cultural and 23 | scientific works ("Commons") that the public can reliably and without fear 24 | of later claims of infringement build upon, modify, incorporate in other 25 | works, reuse and redistribute as freely as possible in any form whatsoever 26 | and for any purposes, including without limitation commercial purposes. 27 | These owners may contribute to the Commons to promote the ideal of a free 28 | culture and the further production of creative, cultural and scientific 29 | works, or to gain reputation or greater distribution for their Work in 30 | part through the use and efforts of others. 31 | 32 | For these and/or other purposes and motivations, and without any 33 | expectation of additional consideration or compensation, the person 34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she 35 | is an owner of Copyright and Related Rights in the Work, voluntarily 36 | elects to apply CC0 to the Work and publicly distribute the Work under its 37 | terms, with knowledge of his or her Copyright and Related Rights in the 38 | Work and the meaning and intended legal effect of CC0 on those rights. 39 | 40 | 1. Copyright and Related Rights. A Work made available under CC0 may be 41 | protected by copyright and related or neighboring rights ("Copyright and 42 | Related Rights"). Copyright and Related Rights include, but are not 43 | limited to, the following: 44 | 45 | i. the right to reproduce, adapt, distribute, perform, display, 46 | communicate, and translate a Work; 47 | ii. moral rights retained by the original author(s) and/or performer(s); 48 | iii. publicity and privacy rights pertaining to a person's image or 49 | likeness depicted in a Work; 50 | iv. rights protecting against unfair competition in regards to a Work, 51 | subject to the limitations in paragraph 4(a), below; 52 | v. rights protecting the extraction, dissemination, use and reuse of data 53 | in a Work; 54 | vi. database rights (such as those arising under Directive 96/9/EC of the 55 | European Parliament and of the Council of 11 March 1996 on the legal 56 | protection of databases, and under any national implementation 57 | thereof, including any amended or successor version of such 58 | directive); and 59 | vii. other similar, equivalent or corresponding rights throughout the 60 | world based on applicable law or treaty, and any national 61 | implementations thereof. 62 | 63 | 2. Waiver. To the greatest extent permitted by, but not in contravention 64 | of, applicable law, Affirmer hereby overtly, fully, permanently, 65 | irrevocably and unconditionally waives, abandons, and surrenders all of 66 | Affirmer's Copyright and Related Rights and associated claims and causes 67 | of action, whether now known or unknown (including existing as well as 68 | future claims and causes of action), in the Work (i) in all territories 69 | worldwide, (ii) for the maximum duration provided by applicable law or 70 | treaty (including future time extensions), (iii) in any current or future 71 | medium and for any number of copies, and (iv) for any purpose whatsoever, 72 | including without limitation commercial, advertising or promotional 73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each 74 | member of the public at large and to the detriment of Affirmer's heirs and 75 | successors, fully intending that such Waiver shall not be subject to 76 | revocation, rescission, cancellation, termination, or any other legal or 77 | equitable action to disrupt the quiet enjoyment of the Work by the public 78 | as contemplated by Affirmer's express Statement of Purpose. 79 | 80 | 3. Public License Fallback. Should any part of the Waiver for any reason 81 | be judged legally invalid or ineffective under applicable law, then the 82 | Waiver shall be preserved to the maximum extent permitted taking into 83 | account Affirmer's express Statement of Purpose. In addition, to the 84 | extent the Waiver is so judged Affirmer hereby grants to each affected 85 | person a royalty-free, non transferable, non sublicensable, non exclusive, 86 | irrevocable and unconditional license to exercise Affirmer's Copyright and 87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the 88 | maximum duration provided by applicable law or treaty (including future 89 | time extensions), (iii) in any current or future medium and for any number 90 | of copies, and (iv) for any purpose whatsoever, including without 91 | limitation commercial, advertising or promotional purposes (the 92 | "License"). The License shall be deemed effective as of the date CC0 was 93 | applied by Affirmer to the Work. Should any part of the License for any 94 | reason be judged legally invalid or ineffective under applicable law, such 95 | partial invalidity or ineffectiveness shall not invalidate the remainder 96 | of the License, and in such case Affirmer hereby affirms that he or she 97 | will not (i) exercise any of his or her remaining Copyright and Related 98 | Rights in the Work or (ii) assert any associated claims and causes of 99 | action with respect to the Work, in either case contrary to Affirmer's 100 | express Statement of Purpose. 101 | 102 | 4. Limitations and Disclaimers. 103 | 104 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 105 | surrendered, licensed or otherwise affected by this document. 106 | b. Affirmer offers the Work as-is and makes no representations or 107 | warranties of any kind concerning the Work, express, implied, 108 | statutory or otherwise, including without limitation warranties of 109 | title, merchantability, fitness for a particular purpose, non 110 | infringement, or the absence of latent or other defects, accuracy, or 111 | the present or absence of errors, whether or not discoverable, all to 112 | the greatest extent permissible under applicable law. 113 | c. Affirmer disclaims responsibility for clearing rights of other persons 114 | that may apply to the Work or any use thereof, including without 115 | limitation any person's Copyright and Related Rights in the Work. 116 | Further, Affirmer disclaims responsibility for obtaining any necessary 117 | consents, permissions or other rights required for any use of the 118 | Work. 119 | d. Affirmer understands and acknowledges that Creative Commons is not a 120 | party to this document and has no duty or obligation with respect to 121 | this CC0 or use of the Work. 122 | -------------------------------------------------------------------------------- /src/models/sessionmodel.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2015 Elvis Angelaccio 3 | 4 | SPDX-License-Identifier: GPL-2.0-or-later 5 | */ 6 | 7 | #include "sessionmodel.h" 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | SessionModel::SessionModel(QObject *parent) : QAbstractTableModel(parent) 19 | { 20 | QFile saveFile {QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + QLatin1String("/sessions.json")}; 21 | if (saveFile.exists()) { 22 | if (saveFile.open(QIODevice::ReadOnly)) { 23 | auto saveData = saveFile.readAll(); 24 | auto saveDoc = QJsonDocument::fromJson(saveData); 25 | read(saveDoc.object()); 26 | } else { 27 | qDebug().nospace() << "cannot open " << saveFile.fileName() << ": " << saveFile.errorString(); 28 | } 29 | } 30 | 31 | connect(this, &QAbstractTableModel::dataChanged, this, &SessionModel::slotWriteData); 32 | connect(this, &QAbstractTableModel::rowsInserted, this, &SessionModel::slotWriteData); 33 | connect(this, &QAbstractTableModel::rowsRemoved, this, &SessionModel::slotWriteData); 34 | } 35 | 36 | int SessionModel::columnCount(const QModelIndex& parent) const 37 | { 38 | Q_UNUSED(parent) 39 | 40 | return m_roles.count(); 41 | } 42 | 43 | int SessionModel::rowCount(const QModelIndex& parent) const 44 | { 45 | Q_UNUSED(parent) 46 | 47 | return m_sessionList.size(); 48 | } 49 | 50 | QVariant SessionModel::data(const QModelIndex& index, int role) const 51 | { 52 | if (!index.isValid()) { 53 | return QVariant::Invalid; 54 | } 55 | 56 | if (index.row() >= rowCount() || index.row() < 0) { 57 | return QVariant::Invalid; 58 | } 59 | 60 | if (role == Qt::DisplayRole) { 61 | return data(index, Qt::UserRole + index.column()); 62 | } 63 | 64 | switch (static_cast(role)) { 65 | case Roles::SessionIdRole: 66 | return QString::number(index.row() + 1); 67 | case Roles::NameRole: 68 | return m_sessionList.at(index.row()).name(); 69 | case Roles::DateRole: 70 | return m_sessionList.at(index.row()).date(); 71 | case Roles::NoteRole: 72 | return m_sessionList.at(index.row()).note(); 73 | case Roles::SessionRole: 74 | return QVariant::fromValue(m_sessionList.at(index.row())); 75 | } 76 | 77 | if (role == Qt::EditRole && index.column() == columnForRole(Roles::NameRole)) { 78 | // prevent the disappear of the old value when double-clicking the item 79 | return m_sessionList.at(index.row()).name(); 80 | } 81 | 82 | if (role == Qt::EditRole && index.column() == columnForRole(Roles::NoteRole)) { 83 | return m_sessionList.at(index.row()).note(); 84 | } 85 | 86 | return QVariant::Invalid; 87 | } 88 | 89 | 90 | QVariant SessionModel::headerData(int section, Qt::Orientation orientation, int role) const 91 | { 92 | if (role != Qt::DisplayRole || orientation != Qt::Horizontal) 93 | return QVariant::Invalid; 94 | 95 | switch (roleForColumn(section)) { 96 | case Roles::SessionIdRole: 97 | return i18nc("session number", "Session #"); 98 | case Roles::NameRole: 99 | return i18n("Name"); 100 | case Roles::DateRole: 101 | return i18n("Date"); 102 | case Roles::NoteRole: 103 | return i18n("Note"); 104 | case Roles::SessionRole: 105 | break; 106 | } 107 | 108 | return QVariant::Invalid; 109 | } 110 | 111 | bool SessionModel::setData(const QModelIndex& index, const QVariant& value, int role) 112 | { 113 | if (!index.isValid() || role != Qt::EditRole) 114 | return false; 115 | 116 | if (index.column() == columnForRole(Roles::NameRole)) { 117 | if (value.toString().isEmpty()) 118 | return false; 119 | 120 | m_sessionList[index.row()].setName(value.toString()); 121 | Q_EMIT dataChanged(index, index); 122 | 123 | return true; 124 | } 125 | 126 | if (index.column() == columnForRole(Roles::NoteRole)) { 127 | m_sessionList[index.row()].setNote(value.toString()); 128 | Q_EMIT dataChanged(index, index); 129 | 130 | return true; 131 | } 132 | 133 | return false; 134 | } 135 | 136 | Qt::ItemFlags SessionModel::flags(const QModelIndex& index) const 137 | { 138 | if (!index.isValid()) 139 | return Qt::ItemIsEnabled; 140 | 141 | if (isEditable(index)) 142 | return QAbstractTableModel::flags(index) | Qt::ItemIsEditable; 143 | 144 | return QAbstractTableModel::flags(index); 145 | } 146 | 147 | bool SessionModel::removeRows(int row, int count, const QModelIndex& parent) 148 | { 149 | if (row < 0 || row + count - 1 >= rowCount()) 150 | return false; 151 | 152 | beginRemoveRows(parent, row, row + count - 1); 153 | 154 | for (int i = 0; i < count; i++) { 155 | m_sessionList.removeAt(row); 156 | } 157 | 158 | endRemoveRows(); 159 | 160 | return true; 161 | } 162 | 163 | void SessionModel::append(const Session& session) 164 | { 165 | beginInsertRows(QModelIndex(), rowCount(), rowCount()); // i.e. append the new row at the table end 166 | m_sessionList.append(session); 167 | endInsertRows(); 168 | } 169 | 170 | void SessionModel::update(Session& session) 171 | { 172 | int i = m_sessionList.indexOf(session); 173 | 174 | if (i == -1) 175 | return; 176 | 177 | session.setDate(QDateTime::currentDateTime()); 178 | m_sessionList[i] = session; 179 | 180 | Q_EMIT dataChanged({}, {}); 181 | } 182 | 183 | bool SessionModel::isEmpty() const 184 | { 185 | return m_sessionList.isEmpty(); 186 | } 187 | 188 | bool SessionModel::isEditable(const QModelIndex& index) const 189 | { 190 | auto role = roleForColumn(index.column()); 191 | return role == Roles::NameRole || role == Roles::NoteRole; 192 | } 193 | 194 | void SessionModel::read(const QJsonObject& json) 195 | { 196 | const auto sessions = json[QStringLiteral("sessions")].toArray(); 197 | for (const auto& session : sessions) { 198 | append(Session::fromJson(session.toObject())); 199 | } 200 | } 201 | 202 | void SessionModel::slotWriteData() 203 | { 204 | QFile saveFile {QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + QLatin1String("/sessions.json")}; 205 | if (!saveFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) { 206 | qDebug().nospace() << "cannot open " << saveFile.fileName() << ": " << saveFile.errorString(); 207 | return; 208 | } 209 | 210 | auto json = QJsonObject {}; 211 | json[QStringLiteral("sessions")] = jsonSessions(); 212 | 213 | auto saveDoc = QJsonDocument {json}; 214 | saveFile.write(saveDoc.toJson()); 215 | } 216 | 217 | int SessionModel::columnForRole(SessionModel::Roles role) const 218 | { 219 | return m_roles.indexOf(role); 220 | } 221 | 222 | SessionModel::Roles SessionModel::roleForColumn(int column) const 223 | { 224 | return m_roles.at(column); 225 | } 226 | 227 | QJsonArray SessionModel::jsonSessions() const 228 | { 229 | auto array = QJsonArray {}; 230 | const auto sessions = m_sessionList; 231 | for (const auto& session : sessions) { 232 | auto object = QJsonObject {}; 233 | session.write(object); 234 | array.append(object); 235 | } 236 | 237 | return array; 238 | } 239 | 240 | 241 | #include "moc_sessionmodel.cpp" 242 | -------------------------------------------------------------------------------- /doc/index.docbook: -------------------------------------------------------------------------------- 1 | 2 | Kronometer"> 4 | 5 | 6 | 7 | ]> 8 | 9 | 10 | 11 | 12 | The &kronometer; Handbook 13 | 14 | 15 | ElvisAngelaccio 16 | 17 |
18 | elvis.angelaccio@kde.org 19 |
20 |
21 |
22 | 23 |
24 | 25 | 26 | 2014-2016 27 | Elvis Angelaccio 28 | 29 | 30 | 2016-04-10 31 | &kronometer; 2.1 32 | 33 | 34 | &FDLNotice; 35 | 36 | 37 | 38 | 39 | &kronometer; is a stopwatch application. It can be used for basic tasks like timer start/pause/resume, as well as lap times recording. 40 | 41 | 42 | &kronometer; is able to save a complete session (timer and lap times) and to restore it later. 43 | 44 | 45 | 46 | 47 | KDE 48 | Kronometer 49 | stopwatch 50 | 51 | 52 |
53 | 54 | 55 | Introduction 56 | 57 | &kronometer; is a simple stopwatch application. It is meant to be simple and pleasant to use, thanks to a use cases driven development. 58 | 59 | 60 | &kronometer; main features are the following: 61 | 62 | 63 | 64 | 65 | &kronometer; provides a timer that can be started, paused, resumed and reset. 66 | 67 | 68 | 69 | 70 | &kronometer; allows you to record lap times and export them to a file. 71 | 72 | 73 | 74 | 75 | &kronometer; allows you to save a session and restore it later. 76 | 77 | 78 | 79 | 80 | &kronometer; allows you to copy the timer numbers from its display. 81 | 82 | 83 | 84 | 85 | 86 | 87 | Usage 88 | 89 | General Usage 90 | 91 | &kronometer; main use case is of course the interaction with the timer. You can start/pause/resume the timer by clicking on the proper actions in the toolbar or in the &kronometer; menu. 92 | 93 | 94 | Even simpler, you can use the keyboard instead of the mouse: you start the timer with the keyboard's Space and you pause the timer with Space too. You might recognize this behavior from many media player applications. 95 | 96 | 97 | By pressing the &Enter; key when the timer is running, you freeze that particular time and you create a new lap time. These times are always visible in the table on the left of the application, where you can sort them by clicking the Lap time column's header. 98 | You can also add a custom text annotation to each lap, by double-clicking the cells within the Note column. 99 | 100 | 101 | The menubar (hidden by default) provides access to all commands and configuration options. 102 | The menubar can be toggled with Show Menubar (&Ctrl;M) 103 | from the Settings menu or the menu button in the toolbar. 104 | 105 | 106 | Save and Restore Sessions 107 | 108 | When you pause a running stopwatch you create a session: a stopwatch time and zero or more lap times. 109 | You can save a session and you can restore it later. 110 | 111 | 112 | 113 | Save a Session 114 | 115 | Pause a running stopwatch, then click on the Save As button in the File menu. 116 | You can choose a name for the session that you are going to save. 117 | 118 | 119 | 120 | Restore a Session 121 | 122 | Click the Open button on the toolbar or in the File menu. 123 | Then choose an existing session to be loaded from the session's dialog. 124 | 125 | 126 | 127 | Update a Session 128 | 129 | When the session is restored, you can resume the stopwatch and you can record new lap times. 130 | If you want to save the updated session, you can simply click the Save button in the File menu. 131 | 132 | 133 | 134 | Edit a Session 135 | 136 | Click the Open button on the toolbar or in the File menu. 137 | If you select an existing session in the session's dialog, you will be able to: 138 | 139 | 140 | Rename the session, by double-clicking on its name. 141 | 142 | 143 | Delete the session, by pressing Del. 144 | 145 | 146 | Add a note to the session or edit it. 147 | 148 | 149 | 150 | 151 | 152 | 153 | Additional Features 154 | 155 | Export Lap Times 156 | 157 | When you record one or more lap times, the export features in the File menu is made available, under the entry Export laps as. 158 | Click on it and then choose a name for the exported file. 159 | You can export in the Comma Separated Values (CSV) format or in the JSON one. 160 | 161 | 162 | 163 | Clipboard Support 164 | 165 | &kronometer; is able to copy the current stopwatch time to the system clipboard. 166 | Use the &Ctrl;C key combination or the Copy entry in the Edit menu. 167 | 168 | 169 | 170 | 171 | 172 | 173 | Configuration 174 | 175 | Settings Dialog 176 | 177 | &kronometer; is customizable in many aspects. 178 | You can open the settings dialog clicking on the Configure &kronometer; entry in the Settings menu. 179 | The settings dialog is organized in the following categories. 180 | 181 | 182 | General Settings 183 | 184 | In the general settings page you can find the settings for the stopwatch and for the laps. 185 | Under the stopwatch tab you can set your preferred time format for the stopwatch display. 186 | You can choose whether to show hours, minutes or second fractions (while seconds are always shown). 187 | &kronometer; supports time granularity up to millisecond, although this requires high CPU usage due to the high refresh rate of the User Interface. 188 | 189 | 190 | Within the laps tab you can enable or disable the laps recording feature. 191 | If the laps are enabled, you can choose their time format, whether to show their notes and whether to show their absolute times, which are the stopwatch times when they were recorded. 192 | 193 | 194 | 195 | Font Settings 196 | 197 | In the font settings page you can customize the font of the stopwatch display. 198 | You can choose different font families, styles and sizes for each timer component (hours, minutes, &etc;). 199 | By default every timer component will use the same font, according the current default font in the system. 200 | 201 | 202 | 203 | Color Settings 204 | 205 | In the color settings page you can customize the default color of the stopwatch display. 206 | You can change the background color and the text color. 207 | The default colors will respect the currently selected system's theme. 208 | 209 | 210 | 211 | &kde; Built-in Settings 212 | 213 | &kronometer; makes use of the standard &kde; configuration tools. 214 | You find them in the Settings menu, under the Configure shortcuts and Configure Toolbars entries. 215 | They allow you to change the shortcuts of the &kronometer;'s actions, and to change the position of the toolbar and its content. 216 | 217 | 218 | 219 | 220 | 221 | 222 | Credits and License 223 | 224 | &kronometer; 225 | 226 | 227 | Program copyright © 2014-2016 Elvis Angelaccio 228 | elvis.angelaccio@kde.org 229 | 230 | 231 | Documentation copyright © 2014-2016 Elvis Angelaccio 232 | elvis.angelaccio@kde.org 233 | 234 | 235 | &underFDL; 236 | &underGPL; 237 | 238 | 239 | &documentation.index; 240 | 241 |
242 | 243 | 254 | -------------------------------------------------------------------------------- /po/sv/docs/kronometer/index.docbook: -------------------------------------------------------------------------------- 1 | 2 | Kronometer"> 6 | 7 | 8 | 9 | ]> 10 | 11 | 12 | 13 | 14 | Handbok &kronometer; 16 | 17 | 18 | ElvisAngelaccio
elvis.angelaccio@kde.org 27 |
28 |
29 |
30 | Stefan Asserhäll
stefan.asserhall@gmail.com
Översättare
45 |
46 | 47 | 48 | 2014-2016 50 | Elvis Angelaccio 52 | 53 | 54 | 2016-04-10 56 | &kronometer; 2.1 58 | 59 | 60 | &FDLNotice; 61 | 62 | 63 | 64 | &kronometer; är ett tidtagarurprogram. Det kan användas för grundfunktioner som att starta, pausa och återstarta tidtagning, samt för att mäta varvtider. 66 | &kronometer; kan spara en hel session (tid och varvtider) och återställa den senare. 68 | 69 | 70 | 71 | KDE 73 | Kronometer 75 | tidtagarur 77 | 78 | 79 |
80 | 81 | 82 | Inledning 84 | &kronometer; är ett enkelt tidtagarur. Det är avsett att vara enkelt och bekvämt att använda, tack vara en utveckling baserad på användarfall. 86 | Huvudfunktionerna i &kronometer; är följande: 88 | 89 | 90 | &kronometer; tillhandahåller ett tidtagarur som kan startas, pausas, återstartas och nollställas. 92 | 93 | 94 | &kronometer; låter dig mäta varvtider och exportera dem till en fil. 96 | 97 | 98 | &kronometer; låter dig spara en session och återställa den senare. 100 | 101 | 102 | &kronometer; låter dig kopiera tiderna från dess urtavla. 104 | 105 | 106 | 107 | 108 | 109 | Användning 111 | 112 | Allmän användning 114 | Huvudanvändningen av &kronometer; är förstås interaktion med tidtagningen. Man kan starta, pausa, återstarta tidtagning genom att klicka på lämpliga alternativ i verktygsraden eller i &kronometer;s meny. 116 | Det är ännu enklare att använda tangentbordet istället för musen: Man startar tidtagning med Mellanslag på tangentbordet och pausar också med Mellanslag. Beteendet kanske känns igen från många mediaspelare. 122 | Genom att trycka på returtangenten när tidtagningen pågår, kan man frysa den specifika tiden och skapa en ny varvtid. Tiderna är alltid synliga i tabellen till vänster i programmet, där de kan sorteras genom att klicka på kolumnrubriken Varvtid. Det går också att lägga till en egen textanmärkning för varje varv genom att dubbelklicka på cellerna i kolumnen Anmärkning. 130 | Menyraden (normalt dold), ger tillgång till alla kommandon och inställningsalternativ. Menyraden kan visas eller döljas med Visa menyrad (&Ctrl;M) i menyn Inställningar eller menyknappen i verktygsraden. 140 | 141 | Spara och återställa sessioner 143 | När ett tidtagarur som mäter pausas, skapas en session: en tid mätt med tidtagaruret och noll eller flera varvtider. En session kan sparas och kan senare återställas. 145 | 146 | 147 | Spara en session 149 | Pausa ett tidtagarur som mäter, klicka därefter på knappen Spara som i menyn Arkiv. Därefter kan du välja ett namn på sessionen som ska lagras. 155 | 156 | 157 | Återställa en session 159 | Klicka på knappen Öppna på verktygsraden eller i menyn Arkiv. Välj därefter en befintlig session som ska läsas in i sessionens dialogruta. 165 | 166 | 167 | Uppdatera en session 169 | När sessionen har återställts, kan man återstarta tidtagaruret och mäta nya varvtider. Om man vill spara den uppdaterade sessionen kan man helt enkelt klicka på knappen Spara i menyn Arkiv. 175 | 176 | 177 | Redigera en session 179 | Klicka på knappen Öppna på verktygsraden eller i menyn Arkiv. Om du väljer en befintlig session i sessionens dialogruta kan du: 185 | 186 | Byta namn på sessionen genom att dubbelklicka på dess namn. 188 | 189 | 190 | Ta bort sessionen genom att trycka på Delete. 194 | 195 | 196 | Lägga till en anmärkning i sessionen eller redigera den. 198 | 199 | 200 | 201 | 202 | 203 | 204 | Ytterligare funktioner 206 | 207 | Exportera varvtider 209 | När en eller flera varvtider mäts, blir exportfunktionen i menyn Arkiv tillgänglig, med alternativet Exportera varv som. Klicka på det och väl ett namn på den exporterade filen. Du kan exportera med formaten CSV (värden åtskilda med kommatecken) eller JSON. 215 | 216 | 217 | Stöd för klippbordet 219 | &kronometer; kan kopiera den aktuella tiden i tidtagaruret till systemets klippbord. Använd tangentkombinationen &Ctrl;C eller alternativet Kopiera i menyn Redigera. 229 | 230 | 231 | 232 | 233 | 234 | Inställning 236 | 237 | Inställningsdialogruta 239 | &kronometer; kan anpassas på många sätt. Det går att visa inställningsdialogrutan genom att klicka på Anpassa &kronometer; i menyn Inställningar. Inställningsdialogrutan är organiserad i följande kategorier: 245 | 246 | Allmänna inställningar 248 | På den allmänna inställningssidan finns tidtagarurets inställningar och för varvtiderna. Under tidtagarursfliken kan önskat tidsformat för tidtagarurets urtavla ställas in. Man kan välja att visa timmar, minuter eller delar av sekunder (medan sekunder alltid visas). &kronometer; stöder tidsupplösning ner till millisekunder, även om det kräver hög processoranvändning på grund av den höga uppdateringsfrekvensen av användargränssnittet. 250 | Under varvtidsfliken kan du aktivera eller inaktivera lagringsfunktionen för varvtider. Om varvtider är aktiverade kan deras tidsformat väljas, om deras anmärkningar ska visas, och om deras absoluta tider ska visas, vilka är tidtagarurets tider när de lagrades. 252 | 253 | 254 | Teckensnittsinställningar 256 | På inställningssidan för teckensnitt kan man anpassa teckensnittet för tidtagarurets urtavla. Det går att välja olika teckenfamiljer, stilar och storlekar för varje tidskomponent (timmar, minuter, etc.). Normalt använder alla tidskomponenter samma teckensnitt enligt systemets nuvarande standardteckensnitt. 258 | 259 | 260 | Färginställningar 262 | På färginställningssidan kan man ställa in den normala färgen på tidtagarurets urtavla. Det går att ändra bakgrundsfärg och textfärg. Standardfärgerna följer temat som för närvarande är valt i systemet. 264 | 265 | 266 | &kde;:s inbyggda inställningar 268 | &kronometer; använder &kde;:s vanliga inställningsverktyg. De finns i menyn Inställningar under alternativen Anpassa genvägar och Anpassa verktygsrader. De gör det möjligt att ändra genvägarna för &kronometer;s funktioner, och ändra verktygsradens plats och dess innehåll. 276 | 277 | 278 | 279 | 280 | 281 | Tack till och licens 283 | &kronometer; 285 | Program copyright © 2014-2016 Elvis Angelaccio elvis.angelaccio@kde.org 289 | Dokumentation copyright © 2014-2016 Elvis Angelaccio elvis.angelaccio@kde.org 293 | Översättning Stefan Asserhäll stefan.asserhall@gmail.com &underFDL; &underGPL; 298 | 299 | &documentation.index; 300 | 301 |
302 | 303 | 314 | -------------------------------------------------------------------------------- /po/nl/docs/kronometer/index.docbook: -------------------------------------------------------------------------------- 1 | 2 | Kronometer"> 6 | 7 | 8 | 9 | ]> 10 | 11 | 12 | 13 | 14 | Het handboek van &kronometer; 16 | 17 | 18 | ElvisAngelaccio
elvis.angelaccio@kde.org 27 |
28 |
29 |
30 | &Freek.de.Kruijf;&Ronald.Stroethoff; 31 |
32 | 33 | 34 | 2014-2016 36 | Elvis Angelaccio 38 | 39 | 40 | 2016-04-10 42 | &kronometer; 2.1 44 | 45 | 46 | &FDLNotice; 47 | 48 | 49 | 50 | &kronometer; is een stopwatch-toepassing. Het kan gebruikt worden voor basistaken zoals starten/pauzeren/doorgaan van een stopwatch, evenals opnemen van rondetijden. 52 | &kronometer; kan een volledige sessie opslaan (stopwatch en rondetijden) en deze later herstellen. 54 | 55 | 56 | 57 | KDE 59 | Kronometer 61 | stopwatch 63 | 64 | 65 |
66 | 67 | 68 | Inleiding 70 | &kronometer; is een toepassing met een eenvoudige stopwatch. Het is bedoeld om eenvoudig te zijn en prettig in gebruik, dankzij op gebruik gerichte ontwikkeling. 72 | De hoofdfunctie van &kronometer; zijn als volgt: 74 | 75 | 76 | &kronometer; biedt een stopwatch die gestart, gepauzeerd, doorgestart en gereset kan worden. 78 | 79 | 80 | &kronometer; kan rondetijden opnemen en ze exporteren naar een bestand. 82 | 83 | 84 | &kronometer; kan een sessie opslaan en deze later herstellen. 86 | 87 | 88 | &kronometer; kan de stopwatchgetallen vanaf zijn scherm kopiëren. 90 | 91 | 92 | 93 | 94 | 95 | Gebruik 97 | 98 | Algemeen gebruik 100 | De hoofdfunctie van &kronometer; is natuurlijk de interactie met de stopwatch. U kunt de stopwatch starten/pauzeren/laten doorgaan door te klikken op de juiste acties in de werkbalk of in het menu van &kronometer;. 102 | Nog makkelijker, u kunt in plaats van de muis het toetsenbord gebruiken: u start de stopwatch met de toets Space en u zet de stopwatch op pauze ook met Space. U herkent dit wellicht van vele media spelers. 108 | Door op de toets &Enter; te drukken, wanneer de timer loopt, kunt u die specifieke tijd bevriezen en u kunt een nieuwe rondetijd maken. Deze tijden zijn altijd zichtbaar in de tabel aan de linkerkant van de toepassing, waar u ze kunt sorteren door te klikken op de kolomkop van Rondetijden. U kunt ook een eigen tekstannotatie aan elke ronde toevoegen door dubbel te klikken in de cellen in de kolom Notitie. 116 | De menubalk (standaard verborgen) biedt toegang tot alle commando en configuratie opties. De menubalk kan omgeschakeld worden met Menubalk tonen (&Ctrl;M) uit het menu Instellingen of de menuknop in de werkbalk. 126 | 127 | Opslaan en herstellen van sessies 129 | Als u een lopende stopwatch pauzeert dan creëert u een sessie: een stopwatchtijd en een of meer rondetijden. U kunt een sessie opslaan en u kunt deze later weer herstellen. 131 | 132 | 133 | Sessie opslaan 135 | Pauzeer een lopende stopwatch, klik vervolgens op de knop Opslaan als of in het menu Bestand. U kunt een naam voor de sessie die u wilt opslaan kiezen. 141 | 142 | 143 | Sessie herstellen 145 | Klik op de knop Openen op de werkbalk of in het menu Bestand. Kies vervolgens een bestaand sessie-bestand dat u wilt laden in de sessie-dialoog. 151 | 152 | 153 | Sessie bijwerken 155 | Als de sessie is hersteld, dan kunt u de stopwatch zijn taak laten hervatten en weer rondetijden laten registreren. Als u de bijgewerkte sessie weer wilt opslaan, dan kunt u weer op de knop Opslaan of in het menu Bestand klikken. 161 | 162 | 163 | Sessie bewerken 165 | Klik op de knop Openen op de werkbalk of in het menu Bestand. Als u een bestaande sessie in de sessie-dialoog selecteert, zult in staat zijn: 171 | 172 | De sessie te hernoemen door dubbel te klikken op zijn naam. 174 | 175 | 176 | De sessie verwijderen door op Del te drukken. 180 | 181 | 182 | Een notitie aan de sessie toevoegen of deze bewerken. 184 | 185 | 186 | 187 | 188 | 189 | 190 | Verdere mogelijkheden 192 | 193 | Rondetijden te exporteren 195 | Nadat u een of meerdere rondetijden heeft opgenomen, komt in het menuitem Ronden exporteren als van het menu Bestand de mogelijkheid tot exporteren beschikbaar. Klik erop en kies een naam voor het te exporteren bestand. U kunt exporteren naar het formaat Comma Separated Values (CSV) of naar het JSON-bestand. 201 | 202 | 203 | Ondersteuning van het klembord 205 | &kronometer; is in staat om de huidige stopwatchtijd naar klembord van het systeem te kopiëren. Gebruik de toetscombinatie &Ctrl;C of het item Kopiërenuit het menu Bewerken. 215 | 216 | 217 | 218 | 219 | 220 | Configuratie 222 | 223 | Instellingendialoog 225 | U kunt vele aspecten van &kronometer; aanpassen. U kunt de instellingendialoog openen door op het item &kronometer; instellen te klikken in het menu Instellingen. De instellingendialoog heeft de volgende categorieën. 231 | 232 | Algemene instellingen 234 | In de algemene instellingenpagina kunt u de instellingen vinden voor de stopwatch en de rondetijden. Onder het tabblad stopwatch kunt u uw voorkeur voor het tijdsindeling op de display van de stopwatch instellen. U kunt kiezen of u fracties van uren, minuten of seconden laat tonen (terwijl seconden altijd getoond worden). &kronometer; ondersteunt tijden tot op de milliseconde, hoewel dat een hoog CPU-gebruik eist vanwege de hoge snelheid voor verversing van het gebruikersinterface. 236 | In het tabblad rondentijden kunt u het opnemen van rondetijden aan of uitschakelen. Als deze zijn ingeschakeld kunt u hun tijdindeling kiezen, om hun notities te tonen en hun absolute tijden, die de tijden van de stopwatch zijn op het moment dat ze zijn opgenomen. 238 | 239 | 240 | Lettertype-instellingen 242 | In pagina voor instellingen voor lettertypen kunt de keuze voor het lettertype van het stopwatchbeeldscherm aanpassen. U kunt verschillende families lettertypen, stijlen en formaten voor elke tijdseenheid (uren, minuten, &etc;) kiezen. Standaard zal elke component van de timer hetzelfde lettertype gebruiken, overeenkomstig het huidige standaard lettertype van het systeem. 244 | 245 | 246 | Kleurinstellingen 248 | In de pagina voor de kleurinstellingen kunt u de standaard kleur van het beeldscherm van de stopwatch aanpassen. U kunt de achtergrondkleur en de tekstkleur wijzigen. De standaard kleuren volgen het huidige geselecteerde thema van het systeem. 250 | 251 | 252 | &kde; ingebouwde instellingen 254 | &kronometer; maakt gebruik van de standaard &kde;-hulpmiddelen voor instellingen. U kunt ze vinden in het menu Instellingen, onder de items Sneltoetsen instellen en Werkbalken instellen. U kunt hier de sneltoetsen voor de acties in &kronometer;, de locatie van de werkbalk en zijn inhoud wijzigen. 262 | 263 | 264 | 265 | 266 | 267 | Dankbetuigingen en licentie 269 | &kronometer; 271 | Programma copyright © 2014-2016 Elvis Angelaccio elvis.angelaccio@kde.org 275 | Documentatie copyright © 2014-2016 Elvis Angelaccio elvis.angelaccio@kde.org 279 | &meld.fouten;&vertaling.freek;&vertaling.ronald;&nagelezen.freek; &underFDL; &underGPL; 280 | 281 | &documentation.index; 282 | 283 |
284 | 285 | 296 | --------------------------------------------------------------------------------