1 #include "mainwindow.h"
2 #include "ui_mainwindow.h"
3
4 #include "todotablemodel.h"
5
6 #include "todotxt.h"
7 #include "settingsdialog.h"
8 #include "quickadddialog.h"
9 #include "aboutbox.h"
10 #include "globals.h"
11 #include "def.h"
12
13 #include <QSortFilterProxyModel>
14 #include <QFileSystemWatcher>
15 #include <QTime>
16 #include <QDebug>
17 #include <QSettings>
18 #include <QShortcut>
19 #include <QCloseEvent>
20 #include <QtAwesome.h>
21 #include <QDesktopWidget>
22 #include <QDir>
23 #include <QSystemTrayIcon>
24 #include <QDesktopServices>
25 #include <QUuid>
26
27 QNetworkAccessManager *networkaccessmanager;
28 TodoTableModel *model=NULL;
29 QString saved_selection; // Used for selection memory
30
MainWindow(QWidget * parent)31 MainWindow::MainWindow(QWidget *parent) :
32 QMainWindow(parent),
33 ui(new Ui::MainWindow)
34 {
35
36 ui->setupUi(this);
37 QString title=this->windowTitle();
38
39 #ifdef QT_NO_DEBUG
40 QCoreApplication::setOrganizationName("Nerdur");
41 QCoreApplication::setOrganizationDomain("nerdur.com");
42 QCoreApplication::setApplicationName("Todour");
43 title.append("-");
44 #else
45 QCoreApplication::setOrganizationName("Nerdur-debug");
46 QCoreApplication::setOrganizationDomain("nerdur-debug.com");
47 QCoreApplication::setApplicationName("Todour-Debug");
48 title.append("-DEBUG-");
49 #endif
50
51 title.append(VER);
52 baseTitle=title;
53 this->setWindowTitle(title);
54
55
56
57 // Check if we're supposed to have the settings from .ini file or not
58 if(QCoreApplication::arguments().contains("-portable")){
59 QSettings::setDefaultFormat(QSettings::IniFormat);
60 QSettings::setPath(QSettings::IniFormat,QSettings::UserScope,QDir::currentPath());
61 qDebug()<<"Setting ini file path to: "<<QDir::currentPath()<<Qt::endl;
62 }
63
64 hotkey = new UGlobalHotkeys();
65 setHotkey();
66
67 // Restore the position of the window
68 auto rec = QApplication::desktop()->screenGeometry();
69 auto maxx = rec.height();
70 auto maxy = rec.width();
71 auto minx = rec.topLeft().x();
72 auto miny = rec.topLeft().y();
73
74 QSettings settings;
75 restoreGeometry(settings.value( SETTINGS_GEOMETRY, saveGeometry() ).toByteArray());
76 restoreState(settings.value( SETTINGS_SAVESTATE, saveState() ).toByteArray());
77 auto p = settings.value(SETTINGS_POSITION, pos()).toPoint();
78
79 if(p.x()>=maxx-100 || p.x()<minx){
80 p.setX(minx); // Set to minx for safety
81 }
82 if(p.y()>=maxy-100 || p.y()<miny ){
83 p.setY(miny); // Set to miny for safety
84 }
85 move(p);
86 resize(settings.value( SETTINGS_SIZE, size() ).toSize());
87 if ( settings.value( SETTINGS_MAXIMIZED, isMaximized() ).toBool() )
88 showMaximized();
89
90 ui->lineEdit_2->setText(settings.value(SETTINGS_SEARCH_STRING,DEFAULT_SEARCH_STRING).toString());
91
92 // Check that we have an UUID for this application (used for undo for example)
93 if(!settings.contains(SETTINGS_UUID)){
94 settings.setValue(SETTINGS_UUID,QUuid::createUuid().toString());
95 }
96
97 // Fix some font-awesome stuff
98 QtAwesome* awesome = new QtAwesome(qApp);
99 awesome->initFontAwesome(); // This line is important as it loads the font and initializes the named icon map
100 awesome->setDefaultOption("scale-factor",0.9);
101 ui->btn_Alphabetical->setIcon(awesome->icon( fa::sortalphaasc ));
102 ui->pushButton_3->setIcon(awesome->icon( fa::signout ));
103 ui->pushButton_4->setIcon(awesome->icon( fa::refresh ));
104 ui->pushButton->setIcon(awesome->icon( fa::plus ));
105 ui->pushButton_2->setIcon(awesome->icon( fa::minus ));
106 ui->context_lock->setIcon(awesome->icon(fa::lock));
107 ui->pb_closeVersionBar->setIcon(awesome->icon(fa::times));
108
109 // Set some defaults if they dont exist
110 if(!settings.contains(SETTINGS_LIVE_SEARCH)){
111 settings.setValue(SETTINGS_LIVE_SEARCH,DEFAULT_LIVE_SEARCH);
112 }
113
114 // Started. Lets open the todo.txt file, parse it and show it.
115 parse_todotxt();
116 setFileWatch();
117 networkaccessmanager = new QNetworkAccessManager(this);
118
119
120 // Set up shortcuts . Mac translates the Ctrl -> Cmd
121 // http://doc.qt.io/qt-5/qshortcut.html
122 auto editshortcut = new QShortcut(QKeySequence(tr("Ctrl+n")),this);
123 QObject::connect(editshortcut,SIGNAL(activated()),ui->lineEdit,SLOT(setFocus()));
124 auto findshortcut = new QShortcut(QKeySequence(tr("Ctrl+f")),this);
125 QObject::connect(findshortcut,SIGNAL(activated()),ui->lineEdit_2,SLOT(setFocus()));
126 //auto contextshortcut = new QShortcut(QKeySequence(tr("Ctrl+l")),this);
127 //QObject::connect(contextshortcut,SIGNAL(activated()),ui->context_lock,SLOT(setChecked(!(ui->context_lock->isChecked()))));
128 QObject::connect(model,SIGNAL(dataChanged (const QModelIndex , const QModelIndex )),this,SLOT(dataInModelChanged(QModelIndex,QModelIndex)));
129
130 /*
131 These should now be handled in the menu system
132 auto undoshortcut = new QShortcut(QKeySequence(tr("Ctrl+z")),this);
133 QObject::connect(undoshortcut,SIGNAL(activated()),this,SLOT(undo()));
134 auto redoshortcut = new QShortcut(QKeySequence(tr("Ctrl+r")),this);
135 QObject::connect(redoshortcut,SIGNAL(activated()),this,SLOT(redo()));*/
136
137
138 // Do this late as it triggers action using data
139 ui->btn_Alphabetical->setChecked(settings.value(SETTINGS_SORT_ALPHA).toBool());
140 ui->context_lock->setChecked(settings.value(SETTINGS_CONTEXT_LOCK,DEFAULT_CONTEXT_LOCK).toBool());
141 updateSearchResults(); // Since we may have set a value in the search window
142
143 ui->lv_activetags->hide(); // Not being used yet
144 ui->newVersionView->hide(); // This defaults to not being shown
145 ui->actionShow_All->setChecked(settings.value(SETTINGS_SHOW_ALL,DEFAULT_SHOW_ALL).toBool());
146 ui->actionStay_On_Top->setChecked(settings.value(SETTINGS_STAY_ON_TOP,DEFAULT_STAY_ON_TOP).toBool());
147 ui->cb_threshold_inactive->setChecked(settings.value(SETTINGS_THRESHOLD_INACTIVE,DEFAULT_THRESHOLD_INACTIVE).toBool());
148 stayOnTop();
149 setTray();
150 setFontSize();
151
152 // Version check
153 if(settings.value(SETTINGS_CHECK_UPDATES,DEFAULT_CHECK_UPDATES).toBool()){
154 QString last_check = settings.value(SETTINGS_LAST_UPDATE_CHECK,"").toString();
155 if(last_check.isEmpty()){
156 // We set this up so that first check will be later, giving users ample time to turn off the feature.
157 last_check = QDate::currentDate().toString("yyyy-MM-dd");
158 settings.setValue(SETTINGS_LAST_UPDATE_CHECK,last_check);
159
160 }
161 QDate lastCheck = QDate::fromString(last_check,"yyyy-MM-dd");
162 QDate nextCheck = lastCheck.addDays(7);
163
164 qDebug()<<"Last update check date: "<<last_check<<" and next is "<<nextCheck.toString("yyyy-MM-dd")<<Qt::endl;
165 int daysToNextcheck = QDate::currentDate().daysTo(nextCheck);
166 if(daysToNextcheck<0){
167 QString URL = VERSION_URL;
168 requestPage(URL);
169 }
170 }
171
172 }
173
174
175
176 // This method is for making sure we're re-selecting the item that has been edited
dataInModelChanged(QModelIndex i1,QModelIndex i2)177 void MainWindow::dataInModelChanged(QModelIndex i1,QModelIndex i2){
178 Q_UNUSED(i2);
179 //qDebug()<<"Data in Model changed emitted:"<<i1.data(Qt::UserRole)<<"::"<<i2.data(Qt::UserRole)<<endl;
180 //qDebug()<<"Changed:R="<<i1.row()<<":C="<<i1.column()<<endl;
181 saved_selection = i1.data(Qt::UserRole).toString();
182 resetTableSelection();
183 updateTitle();
184
185 }
186
187
~MainWindow()188 MainWindow::~MainWindow()
189 {
190 delete ui;
191 delete networkaccessmanager;
192 delete model;
193 }
194
195 QSortFilterProxyModel *proxyModel=NULL;
196
197 QFileSystemWatcher *watcher;
198
updateTitle()199 void MainWindow::updateTitle(){
200 // The title is initialized to the name and version number at start and that is stored in baseTitle
201
202 if(proxyModel != NULL){
203 int visible = proxyModel->rowCount();
204 int total = proxyModel->sourceModel()->rowCount();
205
206 this->setWindowTitle(baseTitle+" ("+QString::number(visible)+"/"+QString::number(total)+")");
207 }
208
209 // Check the undo and redo meny items
210 ui->actionUndo->setEnabled(model->undoPossible());
211 ui->actionRedo->setEnabled(model->redoPossible());
212
213 }
214
215
216 // A simple delay function I pulled of the 'net.. Need to delay reading a file a little bit.. A second seems to be enough
217 // really don't like this though as I have no idea of knowing when a second is enough.
218 // Having more than one second will impact usability of the application as it changes the focus.
delay()219 void delay()
220 {
221 QTime dieTime= QTime::currentTime().addSecs(1);
222 while( QTime::currentTime() < dieTime )
223 QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
224 }
225
226
227
fileModified(const QString & str)228 void MainWindow::fileModified(const QString &str){
229 Q_UNUSED(str);
230 //qDebug()<<"MainWindow::fileModified "<<watcher->files()<<" --- "<<str;
231 saveTableSelection();
232 model->refresh();
233 if(model->count()==0){
234 // This sometimes happens when the file is being updated. We have gotten the signal a bit soon so the file is still empty. Wait and try again
235 delay();
236 model->refresh();
237 updateTitle();
238 }
239 resetTableSelection();
240 setFileWatch();
241 }
242
clearFileWatch()243 void MainWindow::clearFileWatch(){
244 if(watcher != NULL){
245 delete watcher;
246 watcher = NULL;
247 }
248 }
249
setFileWatch()250 void MainWindow::setFileWatch(){
251 QSettings settings;
252 if(settings.value(SETTINGS_AUTOREFRESH).toBool()==false)
253 return;
254
255 clearFileWatch();
256
257 watcher = new QFileSystemWatcher();
258 //qDebug()<<"Mainwindow::setFileWatch :: "<<watcher->files();
259 watcher->removePaths(watcher->files()); // Make sure this is empty. Should only be this file we're using in this program, and only one instance
260 watcher->addPath(model->getTodoFile());
261 QObject::connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(fileModified(QString)));
262 }
263
264
265
parse_todotxt()266 void MainWindow::parse_todotxt(){
267
268 model = new TodoTableModel(this);
269 proxyModel = new QSortFilterProxyModel(this);
270 proxyModel->setSourceModel(model);
271 proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
272 ui->tableView->setModel(proxyModel);
273 //ui->tableView->resizeColumnsToContents();
274 //ui->tableView->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
275 ui->tableView->horizontalHeader()->setSectionResizeMode(1,QHeaderView::Stretch);
276 ui->tableView->resizeColumnToContents(0); // Checkboxes kept small
277 //ui->tableView->resizeRowsToContents(); Om denna körs senare blir det riktigt bra, men inte här..
278 }
279
on_lineEdit_2_textEdited(const QString & arg1)280 void MainWindow::on_lineEdit_2_textEdited(const QString &arg1)
281 {
282 Q_UNUSED(arg1);
283 QSettings settings;
284
285 bool liveUpdate = settings.value(SETTINGS_LIVE_SEARCH).toBool();
286 if(!ui->actionShow_All->isChecked() && liveUpdate){
287 updateSearchResults();
288 }
289 }
290
updateSearchResults()291 void MainWindow::updateSearchResults(){
292 // Take the text of the format of match1 match2 !match3 and turn it into
293 //(?=.*match1)(?=.*match2)(?!.*match3) - all escaped of course
294 QSettings settings;
295 QChar search_not_char = settings.value(SETTINGS_SEARCH_NOT_CHAR,DEFAULT_SEARCH_NOT_CHAR).toChar();
296 QStringList words = ui->lineEdit_2->text().split(QRegularExpression("\\s+"));
297 QString regexpstring="(?=^.*$)"; // Seems a negative lookahead can't be first (!?), so this is a workaround
298 for(QString word:words){
299 QString start = "(?=^.*";
300 if(word.length()>0 && word.at(0)==search_not_char){
301 start = "(?!^.*";
302 word = word.remove(0,1);
303 }
304 if(word.length()==0) break;
305 regexpstring += start+QRegExp::escape(word)+".*$)";
306 }
307 QRegExp regexp(regexpstring,Qt::CaseInsensitive);
308 proxyModel->setFilterRegExp(regexp);
309 //qDebug()<<"Setting filter: "<<regexp.pattern();
310 proxyModel->setFilterKeyColumn(1);
311 updateTitle();
312 }
313
on_lineEdit_2_returnPressed()314 void MainWindow::on_lineEdit_2_returnPressed()
315 {
316 QSettings settings;
317 bool liveUpdate = settings.value(SETTINGS_LIVE_SEARCH).toBool();
318
319 if(!liveUpdate || ui->actionShow_All->isChecked()){
320 updateSearchResults();
321 }
322
323 }
324
on_hotkey()325 void MainWindow::on_hotkey(){
326 auto dlg = new QuickAddDialog();
327 dlg->setModal(true);
328 dlg->show();
329 dlg->exec();
330 if(dlg->accepted){
331 this->addTodo(dlg->text);
332 }
333 }
334
setHotkey()335 void MainWindow::setHotkey(){
336 QSettings settings;
337 if(settings.value(SETTINGS_HOTKEY_ENABLE).toBool()){
338 hotkey->registerHotkey(settings.value(SETTINGS_HOTKEY,DEFAULT_HOTKEY).toString());
339 connect(hotkey,&UGlobalHotkeys::activated,[=](size_t id){
340 Q_UNUSED(id);
341 on_hotkey();
342 });
343 } else {
344 hotkey->unregisterAllHotkeys();
345 }
346 }
347
on_actionAbout_triggered()348 void MainWindow::on_actionAbout_triggered(){
349 AboutBox d;
350 d.setModal(true);
351 d.show();
352 d.exec();
353 //myanalytics->check_update();
354 }
355
on_actionSettings_triggered()356 void MainWindow::on_actionSettings_triggered()
357 {
358 SettingsDialog d;
359 d.setModal(true);
360 d.show();
361 d.exec();
362 if(d.refresh){
363 delete model;
364 model = new TodoTableModel(this);
365 proxyModel->setSourceModel(model);
366 ui->tableView->setModel(proxyModel);
367 ui->tableView->horizontalHeader()->setSectionResizeMode(1,QHeaderView::Stretch);
368 ui->tableView->resizeColumnToContents(0);
369 saveTableSelection();
370 model->refresh();// Not 100% sure why this is needed.. Should be done by re-setting the model above
371 resetTableSelection();
372 setFileWatch();
373 setTray();
374 setFontSize();
375 }
376 }
377
setFontSize()378 void MainWindow::setFontSize(){
379 QSettings settings;
380 int size = settings.value(SETTINGS_FONT_SIZE).toInt();
381 if(size >0){
382 auto f = qApp->font();
383 f.setPointSize(size);
384 qApp->setFont(f);
385 }
386 }
387
stayOnTop()388 void MainWindow::stayOnTop()
389 {
390 if(ui->actionStay_On_Top->isChecked()){
391 setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
392 } else {
393 setWindowFlags(windowFlags() & ~Qt::WindowStaysOnTopHint);
394 }
395 show(); // This is needed as setWindowFlags can hide the window
396 }
397
setTray()398 void MainWindow::setTray(){
399 QSettings settings;
400 if(settings.value(SETTINGS_TRAY_ENABLED,DEFAULT_TRAY_ENABLED).toBool()){
401 // We should be showing a tray icon. Are we?
402 if(trayicon==NULL){
403 trayicon = new QSystemTrayIcon(this);
404 traymenu = new QMenu(this);
405 minimizeAction = new QAction(tr("Mi&nimize"), this);
406 connect(minimizeAction, SIGNAL(triggered()), this, SLOT(hide()));
407 maximizeAction = new QAction(tr("Ma&ximize"), this);
408 connect(maximizeAction, SIGNAL(triggered()), this, SLOT(showMaximized()));
409 restoreAction = new QAction(tr("&Restore"), this);
410 connect(restoreAction, SIGNAL(triggered()), this, SLOT(showNormal()));
411 quitAction = new QAction(tr("&Quit"), this);
412 connect(quitAction, SIGNAL(triggered()), this, SLOT(cleanup()));
413 connect(QApplication::instance(),SIGNAL(aboutToQuit()),this,SLOT(cleanup()));
414
415 traymenu->addAction(minimizeAction);
416 traymenu->addAction(maximizeAction);
417 traymenu->addAction(restoreAction);
418 traymenu->addSeparator();
419 traymenu->addAction(quitAction);
420 trayicon->setContextMenu(traymenu);
421 connect(trayicon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
422 this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
423
424 trayicon->setIcon(QIcon(":/icons/newicon.png"));
425 }
426 trayicon->show();
427 }
428 else{
429 if(trayicon!=NULL){
430 trayicon->hide();
431 }
432 }
433 }
434
iconActivated(QSystemTrayIcon::ActivationReason reason)435 void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason)
436 {
437 switch (reason) {
438 case QSystemTrayIcon::Trigger:
439 case QSystemTrayIcon::DoubleClick:
440 // Make sure the window is open
441 this->show();
442 break;
443 case QSystemTrayIcon::MiddleClick:
444 // Do nothing
445 break;
446 default:
447 ;
448 }
449 }
450
on_pushButton_clicked()451 void MainWindow::on_pushButton_clicked()
452 {
453 // Adding a new value into the model
454 QString txt = ui->lineEdit->text();
455 addTodo(txt);
456 ui->lineEdit->clear();
457 }
458
addTodo(QString & s)459 void MainWindow::addTodo(QString &s){
460
461 if(ui->context_lock->isChecked()){
462 // The line should have the context of the search field except any negative search
463 QStringList contexts = ui->lineEdit_2->text().split(QRegExp("\\s"));
464 for(QString context:contexts){
465 if(context.length()>0 && context.at(0)=='!') continue; // ignore this one
466 if(!s.contains(context,Qt::CaseInsensitive)){
467 s.append(" "+context);
468 }
469 }
470 }
471 model->add(s);
472 updateTitle();
473 }
474
on_lineEdit_returnPressed()475 void MainWindow::on_lineEdit_returnPressed()
476 {
477 on_pushButton_clicked();
478 }
479
on_pushButton_2_clicked()480 void MainWindow::on_pushButton_2_clicked()
481 {
482 // Remove the selected item
483 QModelIndexList indexes = ui->tableView->selectionModel()->selection().indexes();
484 // Only support for deleting one item at a time
485 if(!indexes.empty()){
486 QModelIndex i=indexes.at(0);
487 QString t=model->data(proxyModel->mapToSource(i),Qt::UserRole).toString(); // User Role is Raw data
488 //QString t=proxyModel->data(i).toString();
489 model->remove(t);
490 }
491 updateTitle();
492 }
493
on_pushButton_3_clicked()494 void MainWindow::on_pushButton_3_clicked()
495 {
496 // Archive
497 saveTableSelection();
498 model->archive();
499 resetTableSelection();
500 updateTitle();
501 }
502
on_pushButton_4_clicked()503 void MainWindow::on_pushButton_4_clicked()
504 {
505 saveTableSelection();
506 model->refresh();
507 resetTableSelection();
508 updateTitle();
509 }
510
511
512
saveTableSelection()513 void MainWindow::saveTableSelection(){
514 //auto index = ui->tableView->selectionModel()->selectedIndexes();
515 auto index = ui->tableView->selectionModel()->currentIndex();
516 // if(index.count()>0){
517 if(index.isValid()){
518 // Vi har någonting valt.
519 // qDebug()<<"Selected index: "<<index.at(0)<<endl;
520 //saved_selection = model->data(index.at(0),Qt::UserRole).toString();
521 saved_selection = model->data(index,Qt::UserRole).toString();
522 //qDebug()<<"Selected text: "<<saved_selection<<endl;
523
524 }
525 }
526
resetTableSelection()527 void MainWindow::resetTableSelection(){
528 if(saved_selection.size()>0){
529 // Set the selection again
530 QModelIndexList foundIndexes = model->match(QModelIndex(),Qt::UserRole,saved_selection);
531 if(foundIndexes.count()>0){
532 //qDebug()<<"Found at index: "<<foundIndexes.at(0)<<endl;
533 ui->tableView->setFocus(Qt::OtherFocusReason);
534 ui->tableView->selectionModel()->select(foundIndexes.at(0),QItemSelectionModel::Select);
535 ui->tableView->selectionModel()->setCurrentIndex(foundIndexes.at(0),QItemSelectionModel::ClearAndSelect);
536 //ui->tableView->setCurrentIndex(foundIndexes.at(0));
537 }
538 }
539 saved_selection="";
540
541 }
542
cleanup()543 void MainWindow::cleanup(){
544 QSettings settings;
545
546 settings.setValue( SETTINGS_GEOMETRY, saveGeometry() );
547 settings.setValue( SETTINGS_SAVESTATE, saveState() );
548 settings.setValue( SETTINGS_MAXIMIZED, isMaximized() );
549 if ( !isMaximized() ) {
550 settings.setValue( SETTINGS_POSITION, pos() );
551 settings.setValue( SETTINGS_SIZE, size() );
552 }
553 settings.setValue(SETTINGS_SEARCH_STRING,ui->lineEdit_2->text());
554 if(trayicon!=NULL){
555 delete trayicon;
556 trayicon = NULL;
557 }
558 qApp->quit();
559 }
560
closeEvent(QCloseEvent * ev)561 void MainWindow::closeEvent(QCloseEvent *ev){
562
563 if (trayicon != NULL && trayicon->isVisible()) {
564 hide();
565 ev->ignore();
566 } else {
567 cleanup();
568 ev->accept();
569 }
570
571 }
572
on_btn_Alphabetical_toggled(bool checked)573 void MainWindow::on_btn_Alphabetical_toggled(bool checked)
574 {
575 QSettings settings;
576 settings.setValue(SETTINGS_SORT_ALPHA,checked);
577 on_pushButton_4_clicked(); // Refresh
578 }
579
on_context_lock_toggled(bool checked)580 void MainWindow::on_context_lock_toggled(bool checked)
581 {
582 QSettings settings;
583 settings.setValue(SETTINGS_CONTEXT_LOCK,checked);
584 }
585
586
on_cb_threshold_inactive_stateChanged(int arg1)587 void MainWindow::on_cb_threshold_inactive_stateChanged(int arg1)
588 {
589 QSettings settings;
590 settings.setValue(SETTINGS_THRESHOLD_INACTIVE,arg1);
591 on_pushButton_4_clicked();
592 }
593
on_pb_closeVersionBar_clicked()594 void MainWindow::on_pb_closeVersionBar_clicked()
595 {
596 ui->newVersionView->hide();
597 }
598
599 bool forced_check_version=false;
requestReceived(QNetworkReply * reply)600 void MainWindow::requestReceived(QNetworkReply* reply){
601 QString replyText;
602 QSettings settings;
603 if(reply->error()==QNetworkReply::NoError){
604
605 // Get the http status code
606 int v = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
607 if (v >= 200 && v < 300) // Success
608 {
609 replyText = reply->readAll();
610 double latest_version = replyText.toDouble();
611 double this_version = QString(VER).toDouble();
612 qDebug()<<"Checked version - Latest: "<<latest_version<<" this version "<<this_version<<Qt::endl;
613 if(latest_version>this_version || forced_check_version){
614 if(latest_version >= this_version){
615 ui->lbl_latestVersion->hide();
616 } else {
617 ui->lbl_newVersion->hide();
618 }
619 ui->txtLatestVersion->setText("(v"+QString::number(latest_version,'f',2)+")");
620 ui->newVersionView->show();
621 forced_check_version=false;
622 }
623 // Update the last checked since we were successful
624 settings.setValue(SETTINGS_LAST_UPDATE_CHECK,QDate::currentDate().toString("yyyy-MM-dd"));
625 }
626 }
627 reply->deleteLater();
628 }
629
undo()630 void MainWindow::undo()
631 {
632 if(model->undo()){
633 model->refresh();
634 }
635 }
636
redo()637 void MainWindow::redo()
638 {
639 if(model->redo()){
640 model->refresh();
641 }
642
643 }
644
645 // Check if there is an update available
requestPage(QString & s)646 void MainWindow::requestPage(QString &s){
647 connect(networkaccessmanager,SIGNAL(finished(QNetworkReply*)),this,SLOT(requestReceived(QNetworkReply*)));
648 networkaccessmanager->get(QNetworkRequest(QUrl(s)));
649
650 }
651
652
on_actionCheck_for_updates_triggered()653 void MainWindow::on_actionCheck_for_updates_triggered()
654 {
655 forced_check_version=true;
656 QString URL = VERSION_URL+(QString)"?v="+VER;
657 requestPage(URL);
658
659 }
660
on_tableView_customContextMenuRequested(const QPoint & pos)661 void MainWindow::on_tableView_customContextMenuRequested(const QPoint &pos)
662 {
663 // This is used for triggering opening of a link.
664 // Find out where we are
665 auto index = ui->tableView->indexAt(pos);
666 QString URL=ui->tableView->model()->data(index,Qt::UserRole+1).toString();
667 if(!URL.isEmpty()){
668 QDesktopServices::openUrl(URL);
669 }
670
671 }
672
on_actionQuit_triggered()673 void MainWindow::on_actionQuit_triggered()
674 {
675 cleanup();
676 }
677
on_actionUndo_triggered()678 void MainWindow::on_actionUndo_triggered()
679 {
680 undo();
681 updateTitle();
682 }
683
on_actionRedo_triggered()684 void MainWindow::on_actionRedo_triggered()
685 {
686 redo();
687 updateTitle();
688 }
689
on_actionShow_All_changed()690 void MainWindow::on_actionShow_All_changed()
691 {
692 QSettings settings;
693 settings.setValue(SETTINGS_SHOW_ALL,ui->actionShow_All->isChecked());
694 on_pushButton_4_clicked();
695 }
696
on_actionStay_On_Top_changed()697 void MainWindow::on_actionStay_On_Top_changed()
698 {
699 QSettings settings;
700 settings.setValue(SETTINGS_STAY_ON_TOP,ui->actionStay_On_Top->isChecked());
701 stayOnTop();
702 }
703