├── .gitignore ├── CountDown.pro ├── LICENSE ├── README.md ├── main.cpp ├── res ├── Icon │ ├── canlendar.ico │ ├── canlendar.png │ └── canlendar.svg ├── Translation │ ├── CountDown_zh_CN.qm │ └── CountDown_zh_CN.ts ├── fileinfo.rc └── res.qrc ├── settingdialog.cpp ├── settingdialog.h ├── settingdialog.ui ├── settings.h ├── widget.cpp ├── widget.h └── widget.ui /.gitignore: -------------------------------------------------------------------------------- 1 | # C++ objects and libs 2 | 3 | *.slo 4 | *.lo 5 | *.o 6 | *.a 7 | *.la 8 | *.lai 9 | *.so 10 | *.dll 11 | *.dylib 12 | 13 | # Qt-es 14 | 15 | *.pro.user 16 | *.pro.user.* 17 | moc_*.cpp 18 | qrc_*.cpp 19 | Makefile 20 | *-build-* 21 | -------------------------------------------------------------------------------- /CountDown.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2015-11-07T12:37:27 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core gui 8 | 9 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 10 | 11 | TARGET = CountDown 12 | TEMPLATE = app 13 | 14 | CONFIG += c++11 15 | 16 | SOURCES += main.cpp \ 17 | widget.cpp \ 18 | settingdialog.cpp 19 | 20 | HEADERS += widget.h \ 21 | settingdialog.h \ 22 | settings.h 23 | 24 | FORMS += widget.ui \ 25 | settingdialog.ui 26 | 27 | RESOURCES += \ 28 | res/res.qrc 29 | 30 | TRANSLATIONS += res/Translation/CountDown_zh_CN.ts 31 | 32 | RC_FILE += \ 33 | res/fileinfo.rc 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 LingDong Computer Society of Maoming No.1 High School 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 高考倒计时 2 | 3 | ## 编译依赖 4 | 5 | * Qt5 6 | 7 | ## 截图 8 | 9 | ![倒计时](http://i1.piimg.com/567571/05165820f7d4b7f0.png) 10 | ![应用设置](http://i1.piimg.com/567571/0398ee9f76c80618.png) 11 | 12 | ## 许可协议 13 | 14 | [The MIT License](./LICENSE) 15 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "widget.h" 2 | #include "settings.h" 3 | #include 4 | #include 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | QApplication a(argc, argv); 9 | QTranslator appTr; 10 | appTr.load(QLocale::system(), St::AppName, "_", ":/translation"); 11 | a.installTranslator(&appTr); 12 | Widget w; 13 | w.show(); 14 | 15 | return a.exec(); 16 | } 17 | -------------------------------------------------------------------------------- /res/Icon/canlendar.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ldmmyz/CountDown/b95f8bd65ca7568d78c23c1c6c6dbeafb56dfe6a/res/Icon/canlendar.ico -------------------------------------------------------------------------------- /res/Icon/canlendar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ldmmyz/CountDown/b95f8bd65ca7568d78c23c1c6c6dbeafb56dfe6a/res/Icon/canlendar.png -------------------------------------------------------------------------------- /res/Icon/canlendar.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 38 | 45 | 46 | 48 | 50 | 51 | 53 | image/svg+xml 54 | 56 | 57 | 58 | 59 | 60 | 63 | 68 | 74 | 79 | 84 | 89 | 94 | 99 | 104 | 109 | 114 | 115 | -------------------------------------------------------------------------------- /res/Translation/CountDown_zh_CN.qm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ldmmyz/CountDown/b95f8bd65ca7568d78c23c1c6c6dbeafb56dfe6a/res/Translation/CountDown_zh_CN.qm -------------------------------------------------------------------------------- /res/Translation/CountDown_zh_CN.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SettingDialog 6 | 7 | 8 | Preference 9 | 设置 10 | 11 | 12 | 13 | Data 14 | 数据 15 | 16 | 17 | 18 | Date 19 | 日期 20 | 21 | 22 | 23 | Text 24 | 文字 25 | 26 | 27 | 28 | Behavior 29 | 行为 30 | 31 | 32 | 33 | Autorun 34 | 开机启动 35 | 36 | 37 | 38 | Opacity 39 | 不透明度 40 | 41 | 42 | 43 | Use %0 to represent the number generated automatically 44 | 请使用 %0 表示自动生成的数字 45 | 46 | 47 | 48 | Save 49 | 保存 50 | 51 | 52 | 53 | Cancel 54 | 取消 55 | 56 | 57 | 58 | Restore Defaults 59 | 恢复默认 60 | 61 | 62 | 63 | %0 Days Before Entrance Exam 64 | 离高考还有%0天 65 | 66 | 67 | 68 | Widget 69 | 70 | 71 | 72 | Count Down 73 | 高考倒计时 74 | 75 | 76 | 77 | Preference (&S) 78 | 设置 (&S) 79 | 80 | 81 | 82 | About (&A) 83 | 关于 (&A) 84 | 85 | 86 | 87 | Quit (&Q) 88 | 退出 (&Q) 89 | 90 | 91 | 92 | %0 Days Before Entrance Exam 93 | 离高考还有%0天 94 | 95 | 96 | 97 | About 98 | 关于 99 | 100 | 101 | 102 | <h1>Count Down</h1><p><strong>Copyright 2015 <a href='http://ld.mmyz.net/'>LingDong Computer Society</a></strong><br>This is an opensource software under The MIT License.</p><p>Home Page: <a href='https://github.com/ziqin/CountDown'>https://github.com/ziqin/CountDown</a></p> 103 | <h1>高考倒计时</h1><p><strong>版权所有 2015 <a href='http://ld.mmyz.net/'>灵动计算机社</a></strong><br>本程序以 MIT 协议开放源代码。</p><p>项目主页: <a href='https://github.com/ziqin/CountDown'>https://github.com/ziqin/CountDown</a></p> 104 | 105 | 106 | 107 | Tip 108 | 提醒 109 | 110 | 111 | 112 | Find me here next time! 113 | 下次可以在这里找到我! 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /res/fileinfo.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ldmmyz/CountDown/b95f8bd65ca7568d78c23c1c6c6dbeafb56dfe6a/res/fileinfo.rc -------------------------------------------------------------------------------- /res/res.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | Icon/canlendar.png 4 | 5 | 6 | Translation/CountDown_zh_CN.qm 7 | 8 | 9 | -------------------------------------------------------------------------------- /settingdialog.cpp: -------------------------------------------------------------------------------- 1 | #include "settingdialog.h" 2 | #include "widget.h" 3 | #include "settings.h" 4 | #include 5 | #include 6 | 7 | SettingDialog::SettingDialog(QWidget *parent) : 8 | QDialog(parent), 9 | filePath(QApplication::applicationFilePath().replace('/', '\\')) 10 | { 11 | setupUi(this); 12 | 13 | setting = new QSettings(St::OrgName, St::AppName, this); 14 | reg = new QSettings(R"(HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run)", 15 | QSettings::NativeFormat, this); 16 | readSetting(); 17 | 18 | textLineEdit->setToolTip(tr("Use %0 to represent the number generated automatically").arg(St::Default_Symbol)); 19 | 20 | buttonBox->button(QDialogButtonBox::Save)->setText(tr("Save")); 21 | buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel")); 22 | buttonBox->button(QDialogButtonBox::RestoreDefaults)->setText(tr("Restore Defaults")); 23 | } 24 | 25 | void SettingDialog::readSetting() 26 | { 27 | calendar->setSelectedDate(setting->value(St::Date_ExamDate, St::Default_Date).toDate()); 28 | textLineEdit->setText( 29 | setting->value( 30 | St::Date_Text, 31 | tr("%0 Days Before Entrance Exam").arg(St::Default_Symbol) 32 | ).toString()); 33 | opacityDoubleSpinBox->setValue(setting->value(St::Action_Opacity, St::Default_Opacity).toDouble()); 34 | 35 | // Read startup state 36 | if (reg->value(St::AppName).toString() == filePath) { 37 | autoRunCheckBox->setChecked(true); 38 | } else { 39 | autoRunCheckBox->setChecked(false); 40 | } 41 | } 42 | 43 | /// Save new Settings 44 | void SettingDialog::on_buttonBox_accepted() 45 | { 46 | // Set exam date 47 | setting->setValue(St::Date_ExamDate, calendar->selectedDate()); 48 | setting->setValue(St::Date_Text, textLineEdit->text()); 49 | setting->setValue(St::Action_Opacity, opacityDoubleSpinBox->value()); 50 | 51 | // Change startup state 52 | if (autoRunCheckBox->isChecked()) { 53 | if (reg->value(St::AppName).toString() != filePath) { 54 | reg->setValue(St::AppName, filePath); 55 | } 56 | } else { 57 | reg->remove(St::AppName); 58 | } 59 | } 60 | 61 | /// Restore Defaults Settings 62 | void SettingDialog::on_buttonBox_clicked(QAbstractButton *button) 63 | { 64 | if (button == buttonBox->button(QDialogButtonBox::RestoreDefaults)) { 65 | bool isFirstRun = setting->value(St::Action_FirstRun, true).toBool(); 66 | setting->remove(St::Date); 67 | setting->remove(St::Action); 68 | reg->remove(St::AppName); 69 | setting->setValue(St::Action_FirstRun, isFirstRun); 70 | readSetting(); // Read Default Settings 71 | Widget *p = dynamic_cast(parentWidget()); 72 | if (p) 73 | p->readSetting(); 74 | } 75 | } 76 | 77 | /// Sync opacitySlider to opacityDoubleSpinBox 78 | void SettingDialog::on_opacitySlider_valueChanged(int value) 79 | { 80 | opacityDoubleSpinBox->setValue(value * 0.01); 81 | } 82 | 83 | /// Sync opacityDoubleSpinBox to opacitySlider 84 | void SettingDialog::on_opacityDoubleSpinBox_valueChanged(double value) 85 | { 86 | opacitySlider->setValue(int(value * 100 + 0.5)); // int(n+0.5), get a round number 87 | } 88 | -------------------------------------------------------------------------------- /settingdialog.h: -------------------------------------------------------------------------------- 1 | #ifndef SETTINGDIALOG_H 2 | #define SETTINGDIALOG_H 3 | 4 | #include "ui_settingdialog.h" 5 | 6 | class QSettings; 7 | 8 | class SettingDialog : public QDialog, private Ui::SettingDialog 9 | { 10 | Q_OBJECT 11 | 12 | public: 13 | explicit SettingDialog(QWidget *parent = nullptr); 14 | 15 | private slots: 16 | void on_buttonBox_accepted(); 17 | void on_buttonBox_clicked(QAbstractButton *button); 18 | void on_opacitySlider_valueChanged(int value); 19 | void on_opacityDoubleSpinBox_valueChanged(double value); 20 | 21 | private: 22 | QSettings *setting, *reg; 23 | const QString filePath; 24 | void readSetting(); 25 | }; 26 | 27 | #endif // SETTINGDIALOG_H 28 | -------------------------------------------------------------------------------- /settingdialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | SettingDialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 400 10 | 440 11 | 12 | 13 | 14 | 15 | 400 16 | 440 17 | 18 | 19 | 20 | 21 | 400 22 | 440 23 | 24 | 25 | 26 | Preference 27 | 28 | 29 | 30 | 31 | 32 | 33 | 0 34 | 0 35 | 36 | 37 | 38 | 39 | 0 40 | 280 41 | 42 | 43 | 44 | Data 45 | 46 | 47 | 48 | 49 | 50 | Date 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | Text 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 16777215 69 | 200 70 | 71 | 72 | 73 | 74 | 2015 75 | 6 76 | 7 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | Qt::Horizontal 85 | 86 | 87 | QSizePolicy::Minimum 88 | 89 | 90 | 91 | 40 92 | 20 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | Qt::Vertical 104 | 105 | 106 | QSizePolicy::Maximum 107 | 108 | 109 | 110 | 20 111 | 8 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 0 121 | 0 122 | 123 | 124 | 125 | 126 | 0 127 | 85 128 | 129 | 130 | 131 | Behavior 132 | 133 | 134 | 135 | 136 | 137 | Autorun 138 | 139 | 140 | 141 | 142 | 143 | 144 | 1.000000000000000 145 | 146 | 147 | 0.050000000000000 148 | 149 | 150 | 151 | 152 | 153 | 154 | Opacity 155 | 156 | 157 | 158 | 159 | 160 | 161 | 100 162 | 163 | 164 | Qt::Horizontal 165 | 166 | 167 | 168 | 169 | 170 | 171 | Qt::Horizontal 172 | 173 | 174 | QSizePolicy::Minimum 175 | 176 | 177 | 178 | 22 179 | 20 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | QDialogButtonBox::Cancel|QDialogButtonBox::RestoreDefaults|QDialogButtonBox::Save 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | buttonBox 207 | accepted() 208 | SettingDialog 209 | accept() 210 | 211 | 212 | 248 213 | 254 214 | 215 | 216 | 157 217 | 274 218 | 219 | 220 | 221 | 222 | buttonBox 223 | rejected() 224 | SettingDialog 225 | reject() 226 | 227 | 228 | 316 229 | 260 230 | 231 | 232 | 286 233 | 274 234 | 235 | 236 | 237 | 238 | 239 | -------------------------------------------------------------------------------- /settings.h: -------------------------------------------------------------------------------- 1 | #ifndef SETTINGS_H 2 | #define SETTINGS_H 3 | 4 | #include 5 | #include 6 | 7 | namespace St { 8 | const char * const OrgName = "LingDong"; 9 | const char * const AppName = "CountDown"; 10 | 11 | const char * const Date = "data"; 12 | const char * const Date_ExamDate = "data/examDate"; 13 | const char * const Date_Text = "data/text"; 14 | 15 | const char * const Action = "action"; 16 | const char * const Action_FirstRun = "action/firstRun"; 17 | const char * const Action_Pos = "action/pos"; 18 | const char * const Action_Opacity = "action/opacity"; 19 | 20 | const char Default_Symbol = '%'; 21 | const QDate Default_Date = []{ 22 | QDate today = QDate::currentDate(); 23 | QDate examDate = QDate(today.year(), 6, 7); 24 | return today.daysTo(examDate) < 0 ? examDate.addYears(1) : examDate; 25 | }(); 26 | const double Default_Opacity = 0.75; 27 | } 28 | 29 | #endif // SETTINGS_H 30 | -------------------------------------------------------------------------------- /widget.cpp: -------------------------------------------------------------------------------- 1 | #include "widget.h" 2 | #include "settings.h" 3 | #include "settingdialog.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | Widget::Widget(QWidget *parent) : 13 | QWidget(parent), 14 | settingDialog(nullptr) 15 | { 16 | setupUi(this); 17 | 18 | QIcon icon(":/icon/icon"); 19 | setWindowIcon(icon); 20 | 21 | settingAction = new QAction(tr("Preference (&S)"), this); 22 | aboutAction = new QAction(tr("About (&A)"), this); 23 | quitAction = new QAction(tr("Quit (&Q)"), this); 24 | connect(settingAction, &QAction::triggered, this, &Widget::showSetting); 25 | connect(aboutAction, &QAction::triggered, [this]{ 26 | QMessageBox::about(this, tr("About"), 27 | tr("

Count Down

Copyright 2015 " 28 | "LingDong Computer Society" 29 | "
This is an opensource software under The MIT License.

" 30 | "

Home Page: " 31 | "https://github.com/ziqin/CountDown

")); 32 | }); 33 | connect(quitAction, &QAction::triggered, qApp, &QApplication::quit); 34 | 35 | // Set system tray icon 36 | trayIcon = new QSystemTrayIcon(icon, this); 37 | trayIcon->show(); 38 | trayIcon->setToolTip(tr("Count Down")); 39 | trayIconMenu = new QMenu(this); 40 | trayIconMenu->addAction(settingAction); 41 | trayIconMenu->addAction(aboutAction); 42 | trayIconMenu->addSeparator(); 43 | trayIconMenu->addAction(quitAction); 44 | trayIcon->setContextMenu(trayIconMenu); 45 | 46 | setting = new QSettings(St::OrgName, St::AppName, this); 47 | readSetting(); 48 | firstRun(); 49 | 50 | setWindowFlags(Qt::FramelessWindowHint | Qt::Tool); // no window border, no taskbar icon 51 | 52 | // Update once every 10 seconds 53 | timer = new QTimer(this); 54 | connect(timer, &QTimer::timeout, this, &Widget::setText); 55 | timer->start(10000); 56 | } 57 | 58 | Widget::~Widget() 59 | { 60 | setting->setValue(St::Action_Pos, pos()); 61 | } 62 | 63 | /// Make it possible to drag the window without titlebar 64 | void Widget::mousePressEvent(QMouseEvent *event) 65 | { 66 | dPos = event->globalPos() - this->pos(); 67 | } 68 | void Widget::mouseMoveEvent(QMouseEvent *event) 69 | { 70 | move(event->globalPos() - dPos); 71 | } 72 | 73 | void Widget::setText() 74 | { 75 | label->setText(QString(text).replace(St::Default_Symbol, QString::number(QDate::currentDate().daysTo(examDate)))); 76 | } 77 | 78 | void Widget::readSetting() 79 | { 80 | examDate = setting->value(St::Date_ExamDate, St::Default_Date).toDate(); 81 | text = setting->value( 82 | St::Date_Text, 83 | tr("%0 Days Before Entrance Exam").arg(St::Default_Symbol) 84 | ).toString(); 85 | setWindowOpacity(setting->value(St::Action_Opacity, St::Default_Opacity).toDouble()); 86 | setText(); 87 | adjustSize(); 88 | // Move to the position last time 89 | // If it's the first execution, move to the rightside 90 | move(setting->value(St::Action_Pos, 91 | QPoint(QApplication::desktop()->width() - width() - 35, 35)).toPoint()); 92 | } 93 | 94 | void Widget::showSetting() 95 | { 96 | if (!settingDialog) { 97 | settingDialog = new SettingDialog(this); 98 | if (settingDialog->exec() == QDialog::Accepted) 99 | readSetting(); 100 | delete settingDialog; 101 | settingDialog = nullptr; 102 | } else { 103 | settingDialog->raise(); 104 | } 105 | } 106 | 107 | /// Show Setting Dialog & Tip Message if it's the first execution 108 | void Widget::firstRun() 109 | { 110 | if (setting->value(St::Action_FirstRun, true).toBool()) { 111 | showSetting(); 112 | trayIcon->showMessage(tr("Tip"), tr("Find me here next time!")); 113 | setting->setValue(St::Action_FirstRun, false); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /widget.h: -------------------------------------------------------------------------------- 1 | #ifndef WIDGET_H 2 | #define WIDGET_H 3 | 4 | #include "ui_widget.h" 5 | #include 6 | 7 | class QSystemTrayIcon; 8 | class QSettings; 9 | class SettingDialog; 10 | 11 | class Widget : public QWidget, private Ui::Widget 12 | { 13 | Q_OBJECT 14 | 15 | private: 16 | QPoint dPos; 17 | QSystemTrayIcon *trayIcon; 18 | QSettings *setting; 19 | QMenu *trayIconMenu; 20 | QAction *quitAction; 21 | QAction *settingAction; 22 | QAction *aboutAction; 23 | QDate examDate; 24 | QString text; 25 | QTimer *timer; 26 | SettingDialog *settingDialog; 27 | 28 | void mousePressEvent(QMouseEvent *event) override; 29 | void mouseMoveEvent(QMouseEvent *event) override; 30 | void setTrayIcon(); 31 | void setText(); 32 | void showSetting(); 33 | void firstRun(); 34 | 35 | public: 36 | explicit Widget(QWidget *parent = nullptr); 37 | ~Widget(); 38 | void readSetting(); 39 | }; 40 | 41 | #endif // WIDGET_H 42 | -------------------------------------------------------------------------------- /widget.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Widget 4 | 5 | 6 | 7 | 0 8 | 0 9 | 150 10 | 150 11 | 12 | 13 | 14 | 15 | 150 16 | 150 17 | 18 | 19 | 20 | 21 | 16777215 22 | 150 23 | 24 | 25 | 26 | Count Down 27 | 28 | 29 | 30 | 31 | 32 | Qt::Horizontal 33 | 34 | 35 | QSizePolicy::Fixed 36 | 37 | 38 | 39 | 20 40 | 20 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 微软雅黑 50 | 20 51 | 75 52 | true 53 | 54 | 55 | 56 | Qt::AlignCenter 57 | 58 | 59 | 60 | 61 | 62 | 63 | Qt::Horizontal 64 | 65 | 66 | QSizePolicy::Fixed 67 | 68 | 69 | 70 | 20 71 | 20 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | --------------------------------------------------------------------------------